This article is reproduced from: http://blog.csdn.net/teaspring/article/details/78350888
Thank the original author Teaspring share. This article has obtained the original author's reprint permission.
Ethernet as a digital currency of the operating system, it is obvious that it will also have a wallet-like client program, to provide management account balances and other functions. We know that storage (or binding, affiliated) account of the ether, in the code with the address type variables exist, so the ability to manage multiple Ethernet square accounts should be one of the basic functions of the client program. This article starts with the code package for managing account information, and introduces some of the main modules of the Ethernet Square client program from the bottom up. 1. Code package for managing account information accounts
In the accounts code package of the Ethernet square source code, the smallest structure that renders the account address is called account{}, and its main member is a common. Address type variable; Admin account interface class called Wallet, class such as its name,<wallet> declares such operations as caching account objects and parsing account objects, managing multiple <Wallet> The structure of the object is called Manager, and these types of UML relationships are shown in the following illustration:
In the various structures/interfaces within the accounts code package, the accounts. The manager is undoubtedly at the top of the invocation relationship, which is itself a public class, exposing outward including querying a single account, returning single or multiple wallet objects, subscribing to Wallet update events, and so on. Within it, it maintains a wallet list that holds a set of account objects through each wallet implementation class and passes an event. Feed member variables to manage all the requirements for subscribing to it Wallet update events. Update event for manager subscription wallet
To highlight the subscription (subscribe) operation here, the manager's subscribe () function is defined as follows:
[Plain] View plain copy///accounts/manager.go func (AM *manager) Subscribe (sink chan<-) event. Subscription {return am.feed.Subscribe (sink)} First notice that this Subscribe () function is an operation that allows an external calling object to subscribe to the manager, and in fact the manager itself is also The same subscription mechanism to learn about the newly added wallet object, its member variable updates is the channel in which the manager itself obtains the subscribed events. Second, the Manager.subscribe () function has only one Chan parameter, because the channel mechanism in the Golang language is powerful, the subscription operation only needs a Chan object is enough, it is very simple, it is not necessary to know who is behind the subscription. Still, it's worth thinking about what objects are subscribing to the manager. In fact, subscribing to a manager object for Wallet update events is just another manager object, the implementation class for <Backend>.
It is very meaningful to draw the above conclusion. As you can see later, accounts. Manager is primarily used as a eth.ethereum (or les). Ethereum) is a member of the existence, and this eth. Ethereum is the most important part of the Etheric Square client program, which provides the functions required for almost all of the etheric square system to operate in the form of a service, so an Ethernet square client can be considered as a accounts. Manager exists, then the truth is that all the etheric square clients are passing through the accouts. The manager subscribes to Wallet update events to each other.
In addition to the manager, several other important structures here include:
event. feed{}: It manages a One-to-many subscription model, with each caller providing a Chan object to send the subscribed content. The Subscriptions processed by feed{} are of type generalization, and each feed{} object, within its lifecycle, can handle only one type of subscription, that is, the value sent to the Chan object. The Feed.subscribe () method returns the implementation body of the <Subscription> Interface Feedsub{},feed.subscribe () to help the manager implement <Backend> The method declared is subscribe (). Inside the feed structure, caselist is used to manage the Chan objects that are sent by all subscribers. Accounts. account{}: Its members except for a common. The address type, which is a 20bytes-long addressing variable, also has an optional member URL, which can be a URL or a locally stored path + file name. URL when present in the form of a web address. Scheme is the network protocol name, and the URL when the file is stored locally. Scheme is a string constant "KeyStore". Accounts.<wallet>: It is very much like the general "wallet", its management of multiple accounts, just as the individual user in the reality of the multiple bank account, the ether balance on each accounting, can be from the database ( Core.state.StateDB) in the query. In the function of the <Wallet> interface declaration, it is especially necessary to note that signxxx (), where Signtx () is digitally signed a transaction (TX) object, Signhash () is digitally signed a hash value, Since any object (as long as serializable) can be hashed, the Signhash () is actually a digital signature for any object, especially block blocks.
<Wallet> is the interface type, its implementation includes software wallet (keystore.keystorewallet) and hardware wallet (usbwallet.wallet), note that the hardware wallet here is in kind. The code system under <Wallet> is not public to the outside, and all outward-exposed "wallet" objects and related update events are in the form of <Wallet>.
the wallet-keystore of software implementation
Software implementation Wallet mainly through the local storage of files to manage the account address. At the same time, the,<wallet> object needs to provide a digital signature for the transaction or chunk object, which requires the public key + key in the Elliptic Curve Digital signature (ECDSA), and each public key is also the source of an account address. So we also need to store ECDSA key information locally. The mechanism by which the Accounts.<wallet> function is implemented through a scheme for storing files locally in the ether is keystore.
<Wallet> Software Wallet Implementation of the relevant code is under the/accounts/keystore/path, the code of the main UML relationship to the following diagram:
keystorewallet{}: It is a accounts.<wallet> implementation class that has an account object that represents its own address and implements the upper interface through the Account.url () method <wallet ". URL () method; There is also a keystore{} object, which is the core class in this set of code.
keystore{}: It provides the keystorewallet structure with all the substantive data and operations related to account. There are two members within the keystore{} for data caching: Accountcache type member cache, a collection of all address information (account{} types) to be looked up; map[address]unlocked{} members in the form unlocked , because the unlocked{} structure simply encapsulates the key{} object (key{} explicitly contains a digitally signed public key pair), the address variable can be used to find the original public key and the key corresponding to the addresses in map[.
In addition, keystore{} has a member storage for the <keyStore> interface type that is used to manipulate the public key information key stored in the local file.
unlocked{}: The encapsulated class of public key data class key{}, whose internal members, in addition to key{}, also provides a Chan type variable abort, which plays a role in KeyStore's management mechanism for public key information.
key{}: A data class that holds a digitally signed public key secret that explicitly stores a ECDSA inside. privatekey{} type member variable, as described earlier, Golang in the native code package ecdsa.privatekey{} contains members of type publickey{}. While key{} also carries the address type member variable, you can avoid duplication of actions that the public key translates into.
<KEYSTORE>: This interface type declares the function of the operation key, noting that it differs from the keystore{} with only one letter case on the name.
The implementation class of Keystorepassphrase{}:<keystore> interface realizes the encryption management of public key information by WEB3 Secret Storage encryption method.
accountcache{}: In-memory caching of all account objects under a known path in the KeyStore provides an action that is found by the address type to the corresponding client.
Filecache{}:keystore can be observed in the cache of files, it can be stored in a path of the files to scan, respectively, to return new files, missing files, changes in the file collection.
watcher{}: Used to monitor changes in the account files stored in a path, you can periodically call Accountcache to scan files. local files explicitly store account information
Accountcache cached account information is derived from a collection of local files stored under a known path. Each file is in JSON format to explicitly store address: {address: "@Address"}, so accountcache can be directly converted to account{} object after reading the file, and used in code. There is no problem with the explicit file store address information, which can be easily invoked without worrying about the compromise of the location information disclosure (the public key used by the ECDSA of the source cannot be parsed from the reverse).
In use, the Watcher object maintains a timer that constantly notifies Accountcache to scan a given path; Accountcache invokes the Filecache object to scan the file under that path. And according to Filecache returned three kinds of file collection: New add files, missing files, change files, in their own maintenance account set of the corresponding operation.
store public key key with local encrypted file
key{} through ECDSA. The Privatekey object thus carries the public key key used by the ECDSA, so this involves the public key key part, which is the operation against the key object. In the KeyStore mechanism, the JSON format of the encrypted key object is stored locally, and the encryption method used is known as the Web3 Secret Storage, and its implementation details can be found on the ethereum git wiki. The following figure is a simple sketch of how this is stored:
A total of three parameters are required for an encrypted stored key object, including the caller providing an arbitrary string named passphrase, and the two integer number given in keystorepassphrase{} SCRYPTN,SCRYPTP, The two integer parameters are fixed within the Keystorepassphrase object lifecycle and can only be assigned at creation time. So whether it's a new key object each time, or a saved key object, the caller must pass in the correct parameter passphrase, so in practical applications, the client of the ether purse must memorize the string itself. In fact, the password that the customer creates for each account is password, the encryption parameter passphrase in the program. Public key key removed in memory for limited exposure
Key{} objects are encapsulated as unlocked{} objects after they are removed from the encrypted local file and keystore into their map[address]*unlocked type members. Because of the importance of public key, it is obvious that the unlocked object in the KeyStore should also control the open length. For different time requirements, keystore{} provides two functions as follows:
[Plain] View plain copy//accounts/keystore/keystore.go func (KS *keystore) Unlock (a accounts. Account, passphrase String) error {return KS. Timedunlock (A, passphrase, timeout:0)} func (KS *keystore) Timedunlock (a accounts. Account, passphrase string, timeout time. Duration) the error Timedunlock () function destroys the private key of the Privatekey in the unlocked object corresponding to the given account immediately after the arrival of the specified time frame (bit clear 0), and remove the unlocked object from the KeyStore member. The unlock () function exposes the unlocked object until the program exits. Note that the cleanup here is only for key objects in memory, while the presence of encrypted local key files is not affected.
The KeyStore mechanism provides the storage and reading of the public key of account information and digital signature in the form of local files, thus realizing the function of accounts.<wallet> in software way. Its two sets of independent local storage files, both the encryption of public key and the fast reading of account information, embody a very comprehensive design idea.
Wallet of hardware device implementation
In addition to providing software-implemented wallets, the ether has a hardware-implemented wallet. Of course, for hardware wallets, there must be an upper layer of code in the Etheric square code to encapsulate this. The code is under/accounts/usbwallet/, and their uml relationships are shown in the following illustration:
The main structures in Pkg accounts/usbwallet include wallet{}, hub{}, and <driver> interface.
The wallet{} structure realizes the upper-layer interface Accounts.<wallet>, and provides the accounts.<wallet> function to the outside. <driver> interface can be seen from the name, It is used to encapsulate the code for the lower hardware implementation wallet. Although strictly speaking, this interface and its implementation body has nothing to do with the "driver" in general sense. ledgerdriver{},trezordriver{} corresponds to the hardware digital money wallet issued by two vendors, ledger and Trezor are brand names respectively. They can all support a variety of digital currencies, including the etheric currency.
<Hub> structure, which realizes the upper Accounts.<backend> interface, which is equivalent to account. Manager. From the code point of view, all hardware implementation of the <Wallet> part, will be managed by this hub object. hub{} outward in the form of <Backend> interface to expose, so that the higher layer of code does not have to distinguish between the implementation of the lower wallet is the software or hardware.
It is necessary to note that in the current Etheric square backbone code, hardware implementation of the wallet related digital signature part, at present only for the transaction for the original digital signature function, that is only <wallet> The Signtx () function is available, other signature features include Signhash (), and signxxxwithpassphrase () are not supported and do not know if other branch codes are different.
2. Ethereum Service
After understanding the accounts Code pack, we can take a look at the most famous type in the etheric square source code, and also the most core part of the client program-ETH. Ethereum. The type of struct that can be named with the entire system name must be very powerful, and the following figure is a simple uml diagram of it: