Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How did Bihara create an account through interface create-account

2025-02-24 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Internet Technology >

Share

Shulou(Shulou.com)06/01 Report--

This article mainly introduces "how to create an account through the interface create-account". In the daily operation, I believe that many people have doubts about how to create an account through the interface create-account. The editor consulted all kinds of information and sorted out a simple and easy-to-use operation method. I hope it will be helpful for you to answer the question of "how to create an account through the interface create-account". Next, please follow the editor to study!

Configure the interface configuration related to account creation in API.buildHandler:

Api/api.go#L164-L244

Func (a * API) buildHandler () {/ /... If a.wallet! = nil {/ /... M.Handle ("/ create-account", jsonHandler (a.createAccount)) / /...

As you can see, the handler corresponding to / create-account is a.createAccount, which is the focus of this article. The outer jsonHandler is used to automate the conversion between JSON and GO data types, which has been discussed before and will not be discussed here.

Let's first take a look at the a.createAccount code:

Api/accounts.go#L15-L30

/ / POST / create-accountfunc (a * API) createAccount (ctx context.Context, ins struct {RootXPubs [] chainkd.XPub `json: "root_xpubs" `Quorum int `json: "quorum" `Alias string `json: "alias" `}) Response {/ / 1. Acc, err: = a.wallet.AccountMgr.Create (ctx, ins.RootXPubs, ins.Quorum) Ins.Alias) if err! = nil {return NewErrorResponse (err)} / / 2. AnnotatedAccount: = account.Annotated (acc) log.WithField ("account ID", annotatedAccount.ID) .Info ("Created account") / / 3. Return NewSuccessResponse (annotatedAccount)}

As you can see, it requires the front end to pass root_xpubs, quorum and alias these three parameters, as we have seen in the previous article, the front end is indeed passed. These three parameters, through the conversion of jsonHandler, to this method, have become the appropriate GO type, we can use directly.

This method is mainly divided into three parts:

Use a.wallet.AccountMgr.Create and the parameters sent by the user to create the appropriate account

Call account.Annotated (acc) to convert the account object into an object that can be JSON

Send a success message back to the front end. The information will be automatically converted to JSON by jsonHandler and sent to the front end to display the prompt message.

Step 3 there is nothing to say, we mainly focus on the first two steps, the following will be combined with the source code in detail.

Create the appropriate account

The a.wallet.AccountMgr.Create method is used to create the account. Look at the code first:

Account/accounts.go#L145-L174

/ / Create creates a new Account.func (m * Manager) Create (ctx context.Context, xpubs [] chainkd.XPub, quorum int, alias string) (* Account, error) {m.accountMu.Lock () defer m.accountMu.Unlock () / 1. NormalizedAlias: = strings.ToLower (strings.TrimSpace (alias)) / / 2. If existed: = m.db.Get (aliasKey (normalizedAlias)) Existed! = nil {return nil, ErrDuplicateAlias} / / 3. Signer, err: = signers.Create ("account", xpubs, quorum, m.getNextAccountIndex ()) id: = signers.IDGenerate () if err! = nil {return nil, errors.Wrap (err)} / / 4. Account: = & Account {Signer: signer, ID: id, Alias: normalizedAlias} / / 5. RawAccount Err: = json.Marshal (account) if err! = nil {return nil, ErrMarshalAccount} / / 6. StoreBatch: = m.db.NewBatch () accountID: = Key (id) storeBatch.Set (accountID, rawAccount) storeBatch.Set (aliasKey (normalizedAlias), [] byte (id) storeBatch.Write () return account, nil}

We divide the method into six pieces, which are explained here in turn:

Standardize the incoming account aliases, such as removing the blanks and lowercase

Search the database for whether the alias has been used. Because the account and alias are one-to-one, after the account is successfully created, the alias is recorded in the database. So if you can look it up in the database, it means it is already occupied, and an error message will be returned. In this way, the front desk can remind the user to change.

To create a Signer is actually to check the correctness of parameters such as xpubs, quorum, and so on. If there is no problem, the information will be tied together, otherwise an error will be returned. I think I have checked this Signer. No problem. Sign it.

Pick up the signer and id created in step 3, as well as the previous standardized aliases, and put them together to form an account

Change the account object into JSON so that it can be stored in the database later.

Save the data related to the account in the database, where aliases correspond to id (it is convenient to query whether aliases exist later), and id corresponds to account objects (JSON format) to save specific information.

There are many methods involved in step 3 of these steps, which need to be analyzed in detail:

Signers.Create

Blockchain/signers/signers.go#L67-L90

/ Create creates and stores a Signer in the databasefunc Create (signerType string, xpubs [] chainkd.XPub, quorum int, keyIndex uint64) (* Signer, error) {/ / 1. If len (xpubs) = 0 {return nil, errors.Wrap (ErrNoXPubs)} / / 2. Sort.Sort (sortKeys (xpubs)) / / this transforms the input slice for i: = 1; I

< len(xpubs); i++ { if bytes.Equal(xpubs[i][:], xpubs[i-1][:]) { return nil, errors.WithDetailf(ErrDupeXPub, "duplicated key=%x", xpubs[i]) } } // 3. if quorum == 0 || quorum >

Len (xpubs) {return nil, errors.Wrap (ErrBadQuorum)} / / 4. Return & Signer {Type: signerType, XPubs: xpubs, Quorum: quorum, KeyIndex: keyIndex,}, nil}

This method can be divided into four blocks, mainly to check whether the parameters are correct, or relatively clear:

Xpubs cannot be empty

Xpubs cannot be duplicated. When checking, sort first, and then see if the two adjacent ones are equal. I think this piece of code should be extracted, such as findDuplicated. It's too detailed to put it directly here.

Check quorum, which means "number of signatures required". It must be less than or equal to the number of xpubs, but cannot be 0. What exactly is the use of this parameter? this may have touched the core, which will be studied in the future.

Package the information together and call it Singer

In addition, there is a sortKeys that needs to be paid attention to in the second place. It actually corresponds to type sortKeys [] chainkd.XPub, so why would you do that instead of passing xpubs directly to sort.Sort?

This is because the object that sort.Sort needs to pass in has the following interfaces:

Type Interface interface {/ / Len is the number of elements in the collection. Len () int / / Less reports whether the element with / / index i should sort before the element with index j. Less (I, j int) bool / / Swap swaps the elements with indexes i and j. Swap (I, j int)}

But there is no xpubs. So after we redefine its type to sortKeys, we can add these methods:

Blockchain/signers/signers.go#L94-L96

Func (s sortKeys) Len () int {return len (s)} func (s sortKeys) Less (I, j int) bool {return bytes.Compare (s [I] [:], s [j] [:]) < 0} func (s sortKeys) Swap (I, j int) {s [I], s [j] = s [j], s [I]} m.getNextAccountIndex ()

Then there is m.getNextAccountIndex () in signers.Create ("account", xpubs, quorum, m.getNextAccountIndex ()), which has the following code:

Account/accounts.go#L119-L130

Func (m * Manager) getNextAccountIndex () uint64 {m.accIndexMu.Lock () defer m.accIndexMu.Unlock () var nextIndex uint64 = 1 if rawIndexBytes: = m.db.Get (accountIndexKey); rawIndexBytes! = nil {nextIndex = common.BytesToUnit64 (rawIndexBytes) + 1} m.db.Set (accountIndexKey, common.Unit64ToBytes (nextIndex)) return nextIndex}

As can be seen from this method, it is used to generate self-increasing numbers. This number is stored in the database, its key is accountIndexKey (constant, the value is [] byte ("AccountIndex")), the value of value is 1 for the first time, then it is incremented by 1 for each call, and it is saved in the database when it is returned. In this way, even if you restart the original program, the number will not be lost.

Signers.IDGenerate ()

The above code:

Blockchain/signers/idgenerate.go#L21-L41

/ / IDGenerate generate signer unique idfunc IDGenerate () string {var ourEpochMS uint64 = 1496635208000 var n uint64 nowMS: = uint64 (time.Now (). UnixNano () / 1e6) seqIndex: = uint64 (nextSeqID ()) seqID: = uint64 (seqIndex% 1024) shardID: = uint64 (5) n = (nowMS-ourEpochMS)

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Internet Technology

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report