成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

剝開比原看代碼09:通過dashboard創(chuàng)建密鑰時(shí),前端的數(shù)據(jù)是如何傳到后端的?

MangoGoing / 1439人閱讀

摘要:下一步,將進(jìn)入比原的節(jié)點(diǎn)也就是后端。它具體是怎么創(chuàng)建密鑰的,這在以后的文章中將詳細(xì)討論。當(dāng)我們清楚了在本文中,前后端數(shù)據(jù)是如何交互的,就很容易推廣到更多的情景。

作者:freewind

比原項(xiàng)目倉(cāng)庫(kù):

Github地址:https://github.com/Bytom/bytom

Gitee地址:https://gitee.com/BytomBlockc...

在前面一篇文章,我們粗略的研究了一下比原的dashboard是如何做出來的,但是對(duì)里面提到的各種細(xì)節(jié)功能,并沒有深入的去研究。那么從本文開始,我們將在這一段時(shí)間,分別研究里面提到的每一項(xiàng)功能。

在前一篇文章中,當(dāng)我們第一次在瀏覽器中打開dashboard時(shí),因?yàn)檫€沒有創(chuàng)建過密鑰,所以比原會(huì)提示我們輸入一些別名和密碼,為我們創(chuàng)建一個(gè)密鑰和相應(yīng)的帳戶。就是下面這張圖所對(duì)應(yīng)的:

那么本文就將研究一下,當(dāng)我們點(diǎn)擊了"Register"按鈕以后,我們?cè)谇岸隧?yè)面上填寫的參數(shù),到底是如何一步步的傳到比原的后端的。

跟之前一樣,我們將對(duì)這個(gè)問題進(jìn)行細(xì)分,然后各個(gè)擊破:

前端:當(dāng)我們填完表單,點(diǎn)了提交以后,比原在前端是如何發(fā)送數(shù)據(jù)的?

后端:比原的后端是如何接收到數(shù)據(jù)的?

前端:當(dāng)我們填完表單,點(diǎn)了提交以后,數(shù)據(jù)會(huì)發(fā)送到后端的哪個(gè)接口?

當(dāng)我們點(diǎn)擊了"Register"按鈕,在前端頁(yè)面中,一定會(huì)在某個(gè)地方觸發(fā)一個(gè)向比原節(jié)點(diǎn)webapi接口發(fā)出請(qǐng)求的操作。究竟是訪問的哪個(gè)web api?提交的數(shù)據(jù)又是什么樣的呢?讓我們先從前端代碼中尋找一下。

注意,比原的前端代碼位于另一個(gè)項(xiàng)目倉(cāng)庫(kù)bytom/dashboard中。為了能與我們?cè)诒鞠盗形恼轮惺褂玫谋仍璿1.0.1的代碼相匹配,我找到了dashboard中的v1.0.0的代碼,并且提交到了一個(gè)多帶帶的項(xiàng)目中:freewind/bytom-dashboard-v1.0.0。注意該項(xiàng)目代碼未做任何修改,其master分支對(duì)應(yīng)于官方代碼倉(cāng)庫(kù)的v1.0.0分支。之所以要弄一個(gè)多帶帶的出來,這是因?yàn)槲覀冊(cè)谖恼轮校看我靡欢未a的時(shí)候,都會(huì)給出相應(yīng)的github上的鏈接,方便讀者跳過去查看全貌,使用一個(gè)獨(dú)立項(xiàng)目,會(huì)讓這個(gè)過程更簡(jiǎn)便一些。

由于比原的前端頁(yè)面是使用React為主的,所以我猜想在代碼中,也該會(huì)有一個(gè)名為Register的組件,或者某個(gè)表單中有一個(gè)名為Register的按鈕。經(jīng)過搜索,我們幸運(yùn)的發(fā)現(xiàn)了Register.jsx 這個(gè)組件文件,它正好是我們需要的。

經(jīng)過高度簡(jiǎn)化后的代碼如下:

src/features/app/components/Register/Register.jsx#L9-L148

class Register extends React.Component {
  // ...
  // 4. 
  submitWithErrors(data) {
    return new Promise((resolve, reject) => {
      // 5. 
      this.props.registerKey(data)
        .catch((err) => reject({_error: err.message}))
    })
  }
  // ...

  render() {
    // ...
    return (
      // ...
      // 3.
      
// 1. // 2. // .... // ... ) } }

上面的代碼,共有5個(gè)地方需要注意,被我用數(shù)字標(biāo)示出來了。注意這5個(gè)數(shù)字并不是從上到下標(biāo)注,而是按照我們關(guān)注的順序來的:

表單上的各個(gè)輸入框,就是我們填寫別名和密碼的地方。這里需要關(guān)注的是每個(gè)TextFieldfieldProps屬性,它對(duì)應(yīng)我們提交到后臺(tái)的數(shù)據(jù)的name

就是那個(gè)“Register”按鈕了。需要注意的是,它的typesubmit,也就是說,點(diǎn)擊它以后,將會(huì)觸發(fā)所在formonSubmit方法

回到了form的開頭。注意它的onSubmit里面,調(diào)用的是handleSubmit(this.submitWithErrors)。其中的handleSubmit是從該表單所使用的第三方redux-form中傳入的,用來處理表單提交,我們?cè)谶@里不關(guān)注它,只需要知道我們需要把自己的處理函數(shù)this.submitWithErrors傳給它。而在后者中,我們將會(huì)調(diào)用比原節(jié)點(diǎn)提供的web api

第3步中的this.submitWithErrors最終將走到這里定義的submitWithErrors函數(shù)

submitWithErrors將會(huì)發(fā)起一個(gè)異步請(qǐng)求,最終調(diào)用由外部傳進(jìn)來的registerKey函數(shù)

從這里我們還看不到調(diào)用的是哪個(gè)api,所以我們必須繼續(xù)去尋找registerKey。很快就在同文件中找到了registerKey

src/features/app/components/Register/Register.jsx#L176-L180

(dispatch) => ({
    registerKey: (token) => dispatch(actions.core.registerKey(token)),
    // ...
  })

它又將會(huì)調(diào)用actions.core.registerKey這個(gè)函數(shù):

src/features/core/actions.js#L44-L87

const registerKey = (data) => {
  return (dispatch) => {
    // ...
    // 1.1
    const keyData = {
      "alias": data.keyAlias,
      "password": data.password
    }
    // 1.2
    return chainClient().mockHsm.keys.create(keyData)
      .then((resp) => {
        // ...
        // 2.1
        const accountData = {
          "root_xpubs":[resp.data.xpub],
          "quorum":1,
          "alias": data.accountAlias}
        // 2.2
        dispatch({type: "CREATE_REGISTER_KEY", data})

        // 2.3
        chainClient().accounts.create(accountData)
          .then((resp) => {
            // ...
            // 2.4
            if(resp.status === "success") {
              dispatch({type: "CREATE_REGISTER_ACCOUNT", resp})
            }
          })
    // ...
      })
    // ...
  }
}

可以看到,在這個(gè)函數(shù)中,做的事情還是很多的。而且并不是我一開始預(yù)料的調(diào)用一次后臺(tái)接口就行了,而是調(diào)用了兩次(分別是創(chuàng)建密鑰和創(chuàng)建帳戶)。下面進(jìn)行分析:

1.1是為了讓后臺(tái)創(chuàng)建密鑰而需要準(zhǔn)備的參數(shù),一個(gè)是alias,一個(gè)是password,它們都是用戶填寫的

1.2是調(diào)用后臺(tái)用于創(chuàng)建密鑰的接口,把keyData傳過去,并且拿到返回的resp后,進(jìn)行后續(xù)的處理

2.1是為了讓后臺(tái)創(chuàng)建帳戶而需要準(zhǔn)備的參數(shù),分別是root_xpubs, quorumalias,其中root_xpubs是創(chuàng)建密鑰后返回的公鑰,quorum目前不知道(TODO),alias是用戶填寫的帳戶別名

2.2這一句沒有作用(經(jīng)過官方確認(rèn)了),因?yàn)槲以诖a中沒有找到處理CREATE_REGISTER_KEY的代碼??梢钥催@個(gè)issue#28

2.3調(diào)用后臺(tái)創(chuàng)建帳戶,把accountData傳過去,可以拿到返回的resp

2.4調(diào)用成功后,再使用redux的dispatch函數(shù)分發(fā)一個(gè)CREATE_REGISTER_ACCOUNT信息。不過這個(gè)信息好像也沒有太大用處。

關(guān)于CREATE_REGISTER_ACCOUNT,我在代碼中找到了兩處相關(guān):

src/features/core/reducers.js#L229-L234

const accountInit = (state = false, action) => {
  if (action.type == "CREATE_REGISTER_ACCOUNT") {
    return true
  }
  return state
}

src/features/app/reducers.js#L10-L115

export const flashMessages = (state = {}, action) => {
  switch (action.type) {
    // ...
    case "CREATE_REGISTER_ACCOUNT": {
      return newSuccess(state, "CREATE_REGISTER_ACCOUNT")
    }
    // ...
  }
}

第一個(gè)看起來沒什么用,第二個(gè)應(yīng)該是用來在操作完成后,顯示相關(guān)的錯(cuò)誤信息。

那就讓我們把關(guān)注點(diǎn)放在1.22.3這兩個(gè)后臺(tái)調(diào)用的地方吧。

chainClient().mockHsm.keys.create(keyData)對(duì)應(yīng)的是:

src/sdk/api/mockHsmKeys.js#L3-L31

const mockHsmKeysAPI = (client) => {
  return {
    create: (params, cb) => {
      let body = Object.assign({}, params)
      const uri = body.xprv ? "/import-private-key" : "/create-key"

      return shared.tryCallback(
        client.request(uri, body).then(data => data),
        cb
      )
    },
    // ...
  }
}

可以看到在create方法中,如果找不到body.xprv(就是本文對(duì)應(yīng)的情況),則會(huì)調(diào)用后臺(tái)的/create-key接口。經(jīng)過一長(zhǎng)串的跟蹤,我們終于找到了一個(gè)。

chainClient().accounts.create(accountData)對(duì)應(yīng)的是:

src/sdk/api/accounts.js#L3-L30

const accountsAPI = (client) => {
  return {
    create: (params, cb) => shared.create(client, "/create-account", params, {cb, skipArray: true}),
    // ...
  }
}

很快我們?cè)谶@邊,也找到了創(chuàng)建帳戶時(shí)調(diào)用的接口為/create-account

前端這邊,我們終于分析完了。下一步,將進(jìn)入比原的節(jié)點(diǎn)(也就是后端)。

后端:比原的后端是如何接收到數(shù)據(jù)的?

如果我們對(duì)前一篇文章還有印象的話,會(huì)記得比原在啟動(dòng)之后,會(huì)在Node.initAndstartApiServer方法中啟動(dòng)web api對(duì)應(yīng)的http服務(wù),并且在API.buildHandler()方法中會(huì)配置很多的功能點(diǎn),其中一定會(huì)有我們這里調(diào)用的接口。

讓我們看看API.buildHandler方法:

api/api.go#L164-L244

func (a *API) buildHandler() {
    walletEnable := false
    m := http.NewServeMux()

    if a.wallet != nil {
        walletEnable = true
        // ...
        m.Handle("/create-account", jsonHandler(a.createAccount))
        // ...
        m.Handle("/create-key", jsonHandler(a.pseudohsmCreateKey))
        // ...

很快,我們就發(fā)現(xiàn)了:

/create-account: 對(duì)應(yīng)a.createAccount

/create-key: 對(duì)應(yīng)a.pseudohsmCreateKey

讓我們先看一下a.pseudohsmCreateKey

api/hsm.go#L23-L32

func (a *API) pseudohsmCreateKey(ctx context.Context, in struct {
    Alias    string `json:"alias"`
    Password string `json:"password"`
}) Response {
    // ...
}

可以看到,pseudohsmCreateKey的第二個(gè)參數(shù),是一個(gè)struct,它有兩個(gè)字段,分別是AliasPassword,這正好和前面從前端傳過來的參數(shù)keyData對(duì)應(yīng)。那么這個(gè)參數(shù)的值是怎么由提交的JSON數(shù)據(jù)轉(zhuǎn)換過來的呢?上次我們說到,主要是由a.pseudohsmCreateKey外面套著的那個(gè)jsonHandler進(jìn)行的,它會(huì)處理與http協(xié)議相關(guān)的操作,以及把JSON數(shù)據(jù)轉(zhuǎn)換成這里需要的Go類型的參數(shù),pseudohsmCreateKey就可以直接用了。

由于在這個(gè)小問題中,我們問題的邊界是比原后臺(tái)是如何拿到數(shù)據(jù)的,所以我們到這里就可以停止對(duì)這個(gè)方法的分析了。它具體是怎么創(chuàng)建密鑰的,這在以后的文章中將詳細(xì)討論。

再看a.createAccount

api/accounts.go#L15-L30

// POST /create-account
func (a *API) createAccount(ctx context.Context, ins struct {
    RootXPubs []chainkd.XPub `json:"root_xpubs"`
    Quorum    int            `json:"quorum"`
    Alias     string         `json:"alias"`
}) Response {
    // ...
}

與前面一樣,這個(gè)方法的參數(shù)RootXPubsQuorumAlias也是由前端提交,并且由jsonHandler自動(dòng)轉(zhuǎn)換好的。

當(dāng)我們清楚了在本文中,前后端數(shù)據(jù)是如何交互的,就很容易推廣到更多的情景。在前端還在很多的頁(yè)面和表單,在很多地方都需要調(diào)用后端的接口,我相信按照本文的思路,應(yīng)該都可以快速的找到。如果有比較特殊的情況,我們以后會(huì)再專門寫文章講解。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/24183.html

相關(guān)文章

  • 剝開原看代碼10:比原如何通過/create-key接口創(chuàng)建密鑰

    摘要:如果傳的是,就會(huì)在內(nèi)部使用默認(rèn)的隨機(jī)數(shù)生成器生成隨機(jī)數(shù)并生成密鑰。使用的是,生成的是一個(gè)形如這樣的全球唯一的隨機(jī)數(shù)把密鑰以文件形式保存在硬盤上。 作者:freewind 比原項(xiàng)目倉(cāng)庫(kù): Github地址:https://github.com/Bytom/bytom Gitee地址:https://gitee.com/BytomBlockc... 在前一篇,我們探討了從瀏覽器的dashb...

    ccj659 評(píng)論0 收藏0
  • 剝開原看代碼11:比原如何通過接口/create-account創(chuàng)建帳戶

    摘要:而本文將繼續(xù)討論,比原是如何通過接口來創(chuàng)建帳戶的。把各信息打包在一起,稱之為另外,在第處還是一個(gè)需要注意的。比原在代碼中使用它保存各種數(shù)據(jù),比如區(qū)塊帳戶等。到這里,我們已經(jīng)差不多清楚了比原的是如何根據(jù)用戶提交的參數(shù)來創(chuàng)建帳戶的。 作者:freewind 比原項(xiàng)目倉(cāng)庫(kù): Github地址:https://github.com/Bytom/bytom Gitee地址:https://git...

    haobowd 評(píng)論0 收藏0
  • 剝開原看代碼08:比原Dashboard怎么做出來?

    摘要:所以本文本來是想去研究一下,當(dāng)別的節(jié)點(diǎn)把區(qū)塊數(shù)據(jù)發(fā)給我們之后,我們應(yīng)該怎么處理,現(xiàn)在換成研究比原的是怎么做出來的。進(jìn)去后會(huì)看到大量的與相關(guān)的配置。它的功能主要是為了在訪問與的函數(shù)之間增加了一層轉(zhuǎn)換。 作者:freewind 比原項(xiàng)目倉(cāng)庫(kù): Github地址:https://github.com/Bytom/bytom Gitee地址:https://gitee.com/BytomBlo...

    CHENGKANG 評(píng)論0 收藏0
  • 剝開原看代碼12:比原如何通過/create-account-receiver創(chuàng)建地址?

    摘要:繼續(xù)看生成地址的方法由于這個(gè)方法里傳過來的是而不是對(duì)象,所以還需要再用查一遍,然后,再調(diào)用這個(gè)私有方法創(chuàng)建地址該方法可以分成部分在第塊中主要關(guān)注的是返回值。 作者:freewind 比原項(xiàng)目倉(cāng)庫(kù): Github地址:https://github.com/Bytom/bytom Gitee地址:https://gitee.com/BytomBlockc... 在比原的dashboard中...

    oneasp 評(píng)論0 收藏0
  • 剝開原看代碼01:初始化時(shí)生成配置文件在哪兒

    摘要:所以這個(gè)文章系列叫作剝開比原看代碼。所以我的問題是比原初始化時(shí),產(chǎn)生了什么樣的配置文件,放在了哪個(gè)目錄下下面我將結(jié)合源代碼,來回答這個(gè)問題。將用來確認(rèn)數(shù)據(jù)目錄是有效的,并且將根據(jù)傳入的不同,來生成不同的內(nèi)容寫入到配置文件中。 作者:freewind 比原項(xiàng)目倉(cāng)庫(kù): Github地址:https://github.com/Bytom/bytom Gitee地址:https://gitee...

    felix0913 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

閱讀需要支付1元查看
<