1. <nobr id="easjo"><address id="easjo"></address></nobr>

      <track id="easjo"><source id="easjo"></source></track>
      1. 
        

      2. <bdo id="easjo"><optgroup id="easjo"></optgroup></bdo>
      3. <track id="easjo"><source id="easjo"><em id="easjo"></em></source></track><option id="easjo"><span id="easjo"><em id="easjo"></em></span></option>
          貴州做網站公司
          貴州做網站公司~專業!靠譜!
          10年網站模板開發經驗,熟悉國內外開源網站程序,包括DEDECMS,WordPress,ZBlog,Discuz! 等網站程序,可為您提供網站建設,網站克隆,仿站,網頁設計,網站制作,網站推廣優化等服務。我們專注高端營銷型網站,企業官網,集團官網,自適應網站,手機網站,網絡營銷,網站優化,網站服務器環境搭建以及托管運維等。為客戶提供一站式網站解決方案?。?!

          create account(比原是怎么通過接口create-account創建帳戶)

          來源:互聯網轉載 時間:2024-05-10 02:54:01

          API.buildHandler中配置與創建帳戶相關的接口配置:

          api/api.go#L164-L244

          func(a*API)buildHandler(){//...ifa.wallet!=nil{//...m.Handle("/create-account",jsonHandler(a.createAccount))//...

          可以看到,/create-account對應的handler是a.createAccount,它是我們本文將研究的重點。外面套著的jsonHandler是用來自動JSON與GO數據類型之間的轉換的,之前討論過,這里不再說。

          我們先看一下a.createAccount的代碼:

          api/accounts.go#L15-L30

          //POST/create-accountfunc(a*API)createAccount(ctxcontext.Context,insstruct{RootXPubs[]chainkd.XPub`json:"root_xpubs"`Quorumint`json:"quorum"`Aliasstring`json:"alias"`})Response{//1.acc,err:=a.wallet.AccountMgr.Create(ctx,ins.RootXPubs,ins.Quorum,ins.Alias)iferr!=nil{returnNewErrorResponse(err)}//2.annotatedAccount:=account.Annotated(acc)log.WithField("accountID",annotatedAccount.ID).Info("Createdaccount")//3.returnNewSuccessResponse(annotatedAccount)}

          可以看到,它需要前端傳過來root_xpubs、quorumalias這三個參數,我們在之前的文章中也看到,前端也的確傳了過來。這三個參數,通過jsonHandler的轉換,到這個方法的時候,已經成了合適的GO類型,我們可以直接使用。

          這個方法主要分成了三塊:

          1. 使用a.wallet.AccountMgr.Create以及用戶發送的參數去創建相應的帳戶

          2. 調用account.Annotated(acc),把account對象轉換成可以被JSON化的對象

          3. 向前端發回成功信息。該信息會被jsonHandler自動轉為JSON發到前端,用于顯示提示信息

          第3步沒什么好說的,我們主要把目光集中在前兩步,下面將依次結合源代碼詳解。

          創建相應的帳戶

          創建帳戶使用的是a.wallet.AccountMgr.Create方法,先看代碼:

          account/accounts.go#L145-L174

          //CreatecreatesanewAccount.func(m*Manager)Create(ctxcontext.Context,xpubs[]chainkd.XPub,quorumint,aliasstring)(*Account,error){m.accountMu.Lock()deferm.accountMu.Unlock()//1.normalizedAlias:=strings.ToLower(strings.TrimSpace(alias))//2.ifexisted:=m.db.Get(aliasKey(normalizedAlias));existed!=nil{returnnil,ErrDuplicateAlias}//3.signer,err:=signers.Create("account",xpubs,quorum,m.getNextAccountIndex())id:=signers.IDGenerate()iferr!=nil{returnnil,errors.Wrap(err)}//4.account:=&Account{Signer:signer,ID:id,Alias:normalizedAlias}//5.rawAccount,err:=json.Marshal(account)iferr!=nil{returnnil,ErrMarshalAccount}//6.storeBatch:=m.db.NewBatch()accountID:=Key(id)storeBatch.Set(accountID,rawAccount)storeBatch.Set(aliasKey(normalizedAlias),[]byte(id))storeBatch.Write()returnaccount,nil}

          我們把該方法分成了6塊,這里依次講解:

          1. 把傳進來的帳戶別名進行標準化修正,比如去掉兩頭空白并小寫

          2. 從數據庫中尋找該別名是否已經用過。因為帳戶和別名是一一對應的,帳戶創建成功后,會在數據庫中把別名記錄下來。所以如果能從數據庫中查找,說明已經被占用,會返回一個錯誤信息。這樣前臺就可以提醒用戶更換。

          3. 創建一個Signer,實際上就是對xpubs、quorum等參數的正確性進行檢查,沒問題的話會把這些信息捆綁在一起,否則返回錯誤。這個Signer我感覺是檢查過沒問題簽個字的意思。

          4. 把第3步創建的signer和id,還有前面的標準化之后的別名拿起來,放在一起,就組成了一個帳戶

          5. 把帳戶對象變成JSON,方便后面往數據庫里存

          6. 把帳戶相關的數據保存在數據庫,其中別名與id對應(方便以后查詢別名是否存在),id與account對象(JSON格式)對應,保存具體的信息

          這幾步中的第3步中涉及到的方法比較多,需要再細致分析一下:

          signers.Create

          blockchain/signers/signers.go#L67-L90

          //CreatecreatesandstoresaSignerinthedatabasefuncCreate(signerTypestring,xpubs[]chainkd.XPub,quorumint,keyIndexuint64)(*Signer,error){//1.iflen(xpubs)==0{returnnil,errors.Wrap(ErrNoXPubs)}//2.sort.Sort(sortKeys(xpubs))//thistransformstheinputslicefori:=1;i<len(xpubs);i++{ifbytes.Equal(xpubs[i][:],xpubs[i-1][:]){returnnil,errors.WithDetailf(ErrDupeXPub,"duplicatedkey=%x",xpubs[i])}}//3.ifquorum==0||quorum>len(xpubs){returnnil,errors.Wrap(ErrBadQuorum)}//4.return&Signer{Type:signerType,XPubs:xpubs,Quorum:quorum,KeyIndex:keyIndex,},nil}

          這個方法可以分成4塊,主要就是檢查參數是否正確,還是比較清楚的:

          1. xpubs不能為空

          2. xpubs不能有重復的。檢查的時候就先排序,再看相鄰的兩個是否相等。我覺得這一塊代碼應該抽出來,比如findDuplicated這樣的方法,直接放在這里太過于細節了。

          3. 檢查quorum,它是意思是“所需的簽名數量”,它必須小于等于xpubs的個數,但不能為0。這個參數到底有什么用這個可能已經觸及到比較核心的東西,放在以后研究。

          4. 把各信息打包在一起,稱之為Singer

          另外,在第2處還是一個需要注意的sortKeys。它實際上對應的是type sortKeys []chainkd.XPub,為什么要這么做,而不是直接把xpubs傳給sort.Sort呢?

          這是因為,sort.Sort需要傳進來的對象擁有以下接口:

          typeInterfaceinterface{//Lenisthenumberofelementsinthecollection.Len()int//Lessreportswhethertheelementwith//indexishouldsortbeforetheelementwithindexj.Less(i,jint)bool//Swapswapstheelementswithindexesiandj.Swap(i,jint)}

          但是xpubs是沒有的。所以我們把它的類型重新定義成sortKeys后,就可以添加上這些方法了:

          blockchain/signers/signers.go#L94-L96

          func(ssortKeys)Len()int{returnlen(s)}func(ssortKeys)Less(i,jint)bool{returnbytes.Compare(s[i][:],s[j][:])<0}func(ssortKeys)Swap(i,jint){s[i],s[j]=s[j],s[i]}

          m.getNextAccountIndex()

          然后是signers.Create("account", xpubs, quorum, m.getNextAccountIndex())中的m.getNextAccountIndex(),它的代碼如下:

          account/accounts.go#L119-L130

          func(m*Manager)getNextAccountIndex()uint64{m.accIndexMu.Lock()deferm.accIndexMu.Unlock()varnextIndexuint64=1ifrawIndexBytes:=m.db.Get(accountIndexKey);rawIndexBytes!=nil{nextIndex=common.BytesToUnit64(rawIndexBytes)+1}m.db.Set(accountIndexKey,common.Unit64ToBytes(nextIndex))returnnextIndex}

          從這個方法可以看出,它用于產生自增的數字。這個數字保存在數據庫中,其key為accountIndexKey(常量,值為[]byte("AccountIndex")),value的值第一次為1,之后每次調用都會把它加1,返回的同時把它也保存在數據庫里。這樣比原程序就算重啟該數字也不會丟失。

          signers.IDGenerate()

          上代碼:

          blockchain/signers/idgenerate.go#L21-L41

          //IDGenerategeneratesigneruniqueidfuncIDGenerate()string{varourEpochMSuint64=1496635208000varnuint64nowMS:=uint64(time.Now().UnixNano()/1e6)seqIndex:=uint64(nextSeqID())seqID:=uint64(seqIndex%1024)shardID:=uint64(5)n=(nowMS-ourEpochMS)<<23n=n|(shardID<<10)n=n|seqIDbin:=make([]byte,8)binary.BigEndian.PutUint64(bin,n)encodeString:=base32.HexEncoding.WithPadding(base32.NoPadding).EncodeToString(bin)returnencodeString}

          從代碼中可以看到,這個算法還是相當復雜的,從注釋上來看,它是要生成一個“不重復”的id。如果我們細看代碼中的算法,發現它沒并有和我們的密鑰或者帳戶有關系,所以我不太明白,如果僅僅是需要一個不重復的id,為什么不能直接使用如uuid這樣的算法。另外這個算法是否有名字呢?已經提了issue向開發人員詢問:https://github.com/Bytom/bytom/issues/926

          現在可以回到我們的主線a.wallet.AccountMgr.Create上了。關于創建帳戶的流程,上面已經基本講了,但是還有一些地方我們還沒有分析:

          1. 上面多次提到使用了數據庫,那么使用的是什么數據庫?在哪里進行了初始化?

          2. 這個a.wallet.AccountMgr.Create方法中對應的AccountMgr對象是在哪里構造出來的?

          數據庫與AccountMgr的初始化

          比原在內部使用了leveldb這個數據庫,從配置文件config.toml中就可以看出來:

          $catconfig.tomlfast_sync=truedb_backend="leveldb"

          這是一個由Google開發的性能非常高的Key-Value型的NoSql數據庫,比特幣也用的是它。

          比原在代碼中使用它保存各種數據,比如區塊、帳戶等。

          我們看一下,它是在哪里進行了初始化。

          可以看到,在創建比原節點對象的時候,有大量的與數據庫以及帳戶相關的初始化操作:

          node/node.go#L59-L142

          funcNewNode(config*cfg.Config)*Node{//...//GetstorecoreDB:=dbm.NewDB("core",config.DBBackend,config.DBDir())store:=leveldb.NewStore(coreDB)tokenDB:=dbm.NewDB("accesstoken",config.DBBackend,config.DBDir())accessTokens:=accesstoken.NewStore(tokenDB)//...txFeedDB:=dbm.NewDB("txfeeds",config.DBBackend,config.DBDir())txFeed=txfeed.NewTracker(txFeedDB,chain)//...if!config.Wallet.Disable{//1.walletDB:=dbm.NewDB("wallet",config.DBBackend,config.DBDir())//2.accounts=account.NewManager(walletDB,chain)assets=asset.NewRegistry(walletDB,chain)//3.wallet,err=w.NewWallet(walletDB,accounts,assets,hsm,chain)//...}//...}

          那么我們在本文中用到的,就是這里的walletDB,在上面代碼中的數字1對應的地方。

          另外,AccountMgr的初始化在也這個方法中進行了??梢钥吹?在第2處,生成的accounts對象,就是我們前面提到的a.wallet.AccountMgr中的AccountMgr。這可以從第3處看到,accounts以參數形式傳給了NewWallet生成了wallet對象,它對應的字段就是AccountMgr。

          然后,當Node對象啟動時,它會啟動web api服務:

          node/node.go#L169-L180

          func(n*Node)OnStart()error{//...n.initAndstartApiServer()//...}

          initAndstartApiServer方法里,又會創建API對應的對象:

          node/node.go#L161-L167

          func(n*Node)initAndstartApiServer(){n.api=api.NewAPI(n.syncManager,n.wallet,n.txfeed,n.cpuMiner,n.miningPool,n.chain,n.config,n.accessTokens)//...}

          可以看到,它把n.wallet對象傳給了NewAPI,所以/create-account對應的handlera.createAccount中才可以使用a.wallet.AccountMgr.Create,因為這里的a指的就是api。

          這樣的話,與創建帳戶的流程及相關的對象的初始化我們就都清楚了。

          Annotated(acc)

          下面就回到我們的API.createAccount中的第2塊代碼:

          //2.annotatedAccount:=account.Annotated(acc)log.WithField("accountID",annotatedAccount.ID).Info("Createdaccount")

          我們來看一下account.Annotated(acc):

          account/indexer.go#L27-L36

          //AnnotatedinitanannotatedaccountobjectfuncAnnotated(a*Account)*query.AnnotatedAccount{return&query.AnnotatedAccount{ID:a.ID,Alias:a.Alias,Quorum:a.Quorum,XPubs:a.XPubs,KeyIndex:a.KeyIndex,}}

          這里出現的query指的是比原項目中的一個包blockchain/query,相應的AnnotatedAccount的定義如下:

          blockchain/query/annotated.go#L57-L63

          typeAnnotatedAccountstruct{IDstring`json:"id"`Aliasstring`json:"alias,omitempty"`XPubs[]chainkd.XPub`json:"xpubs"`Quorumint`json:"quorum"`KeyIndexuint64`json:"key_index"`}

          可以看到,它的字段與之前我們在創建帳戶過程中出現的字段都差不多,不同的是后面多了一些與json相關的注解。在后在前面的account.Annotated方法中,也是簡單的把Account對象里的數字賦值給它。

          為什么需要一個AnnotatedAccount呢?原因很簡單,因為我們需要把這些數據傳給前端。在API.createAccount的最后,第3步,會向前端返回NewSuccessResponse(annotatedAccount),由于這個值將會被jsonHandler轉換成JSON,所以它需要有一些跟json相關的注解才行。

          同時,我們也可以根據AnnotatedAccount的字段來了解,我們最后將會向前端返回什么樣的數據。

          到這里,我們已經差不多清楚了比原的/create-account是如何根據用戶提交的參數來創建帳戶的。

          到此,關于“比原是怎么通過接口create-account創建帳戶”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注本站網站,小編會繼續努力為大家帶來更多實用的文章!

          標簽:create account-

          c語言中正確的字符常量是用一對單引號將一個字符括起表示合法的字符常量。例如‘a’。數值包括整型、浮點型。整型可用十進制,八進制,十六進制。八進制前面要加0,后面...

          2022年天津專場考試原定于3月19日舉行,受疫情影響確定延期,但目前延期后的考試時間推遲。 符合報名條件的考生,須在規定時間登錄招考資訊網(www.zha...

          :喜歡聽,樂意看。指很受歡迎?!巴卣官Y料”喜聞樂見:[ xǐ wén lè jiàn ]詳細解釋1. 【解釋】:喜歡聽,樂意看。指很受歡迎。2. 【示例】:這是...

          三類股東是什么意思?三類股東指的是契約型私募基金、資產管理計劃、信托計劃。而三類股東企業是指直接或間接投資人中有三類股東的企業。三類股東開展業務的話,一般是以管理人的身份。不過在開展業務期間,也會存在一些問題,比如信息披露、核查缺乏第三方證據、稅收等。不出資可以成為股東嗎?一般情況下,成為公司的股東是需要出資的,只不過出資方式有可能不同,有用貨幣出資的,也可以用實物、知識產權、土地使用權等可以用貨...

          余額寶七日年化收益率是什么意思余額寶七日年化收益率指的是余額寶在之前的7天中貨幣基金的平均收益水平,即晦一萬份基金份額的凈收益換算出的年收益率。通常投資者在首次買入余額寶的貨幣基金產品時,需要選取七日年化收益率較高的產品,以保證短期不會產生太多虧損。七8年化收益率是一個相對實時和短 期的投資盈利量化指標。年化收益率簡介年化收益率指的是將日利率、周利率、利按照時間周期,換算成年度利率和利潤,屬于是一...

          (資料圖片僅供參考)【新股介紹】天承科技發行量為1453.42萬股,網上發行366.25萬股,于6月28日申購,申購代碼787603,單一賬戶申購上限3500股,申購數量500股整數倍?!局鳡I業務】公司主營業務為PCB所需要的專用電子化學品的研發、生產和銷售?!矩攧罩笜恕抗镜呢攧請蟾嬷?,在2023年第一季度總資產約3.88億元,凈資產約3.39億元,營收約7543.8萬元,凈利潤約3.39億元,...

          TOP
          国产初高中生视频在线观看|亚洲一区中文|久久亚洲欧美国产精品|黄色网站入口免费进人
          1. <nobr id="easjo"><address id="easjo"></address></nobr>

              <track id="easjo"><source id="easjo"></source></track>
              1. 
                

              2. <bdo id="easjo"><optgroup id="easjo"></optgroup></bdo>
              3. <track id="easjo"><source id="easjo"><em id="easjo"></em></source></track><option id="easjo"><span id="easjo"><em id="easjo"></em></span></option>