钱包
钱包只存储私钥,不存储币, 币都在链上。
根据钱包包含的多个密钥之间是否有关系,主要分为两种类型:
- 第一种类型是非确定性钱包(nondeterministic wallet),其中每个密钥都是从随机数独立生成的,密钥彼此无关。这种钱包也被称为“Just a Bunch Of Keys(一堆密钥)”,简称 JBOK 钱包。
- 第二种类型是确定性钱包(deterministic wallet),其中所有的密钥都是从一个主密钥派生出来,这个主密钥即为种子(seed)。该类型钱包中所有密钥都相互关联,如果有原始种子,则可以再次生成全部密钥。确定性钱包中使用了许多不同的密钥推导方法。最常用的推导方法是使用树状结构,称为分层确定性(hierarchical deterministic)钱包或 HD 钱包。
相比随机(不确定性)密钥,HD 钱包有两个主要的优势。第一,树状结构可以被用来表达附加的组织含义,比如子密钥的特定分支用来接收交易收入款项,另一个分支用来负责接收对外付款的找零。密钥的分支也可以用于公司设置,将不同的分支分配给部门、子公司、特定功能或会计类别。 HD 钱包的第二个好处是,用户可以创建一系列公钥,而不需要访问对应的私钥。这样,HD 钱包就能用在不安全的服务器上,或者仅作为接收用途,它为每个交易发布不同的公钥。公钥不需要被预先加载或者提前衍生,服务器也不需要有用来支付的私钥。
Substrate
一、Architecture
1.1 Storage
- rocksdb: kv store
1.2 Runtime
- Wasm
1.3 Peer-to-peer network
1.4 Consensus
- POW:
ethash
- POS:
Aure
、BABE
1.5 RPC
- jsonRPC
1.6 Telemetry
1.7 State
- Tire(Patricia Merkle Tree) structure
二、Key Concept
2.1 Runtime
2.1.1 API
BlockBuilder
: Provides the functionality required for building a block.TaggedTransactionQueue
: Handles validating transactions in the transaction queue.OffchainWorkerApi
: Handles off-chain capabilities.AuraApi
: Handles block authorship with Aura consensus.SessionKeys
: Generates and decodes session keys.GrandpaApi
: Integrates the GRANDPA finality gadget into the runtime.AccountNonceApi
: Handles querying transaction indices.TransactionPaymentApi
: Handles querying information about transactions.Benchmark
: Provides a way to benchmark a FRAME runtime.
2.1.2 Core primitives
Hash
: A type which encodes a cryptographic digest of some data. Typically just a 256-bit quantity.DigestItem
: A type which must be able to encode one of a number of "hard-wired" alternatives relevant to consensus and change-tracking as well as any number of "soft-coded" variants, relevant to specific modules within the runtime.Digest
: A series of DigestItems. This encodes all information that is relevant for a light-client to have on hand within the block.Extrinsic
: A type to represent a single piece of data external to the blockchain that is recognized by the blockchain. This typically involves one or more signatures, and some sort of encoded instructions (e.g. for transferring ownership of funds or calling into a smart contract).Header
: A type which is representative (cryptographically or otherwise) of all information relevant to a block. It includes the parent hash, the storage root and the extrinsics trie root, the digest and a block number.Block
: Essentially just a combination ofHeader
and a series ofExtrinsics
, together with a specification of the hashing algorithm to be used.BlockNumber
: A type which encodes the total number of ancestors any valid block has. Typically a 32-bit quantity.
2.1.3 FRAME primitives
additional set of primitives
Call
: The dispatch type that can be called via an extrinsic.Origin
: Represents where a call came from. For example, a signed message (a transaction), an unsigned message (an inherent extrinsic), or a call from the runtime itself (a root call).Index
: An account index (aka nonce) type. This stores the number of previous transactions associated with a sender account.Hashing
: The hashing algorithm being used in the runtime (e.g. Blake2).AccountId
: The type used to identify user accounts in the runtime.Event
: The type used for events emitted by the runtime.Version
: A type which represents the version of the runtime.
2.2 Extrinsic
2.2.1 Block structure
A block in Substrate is composed of a header
and an array of extrinsics
.
- The header contains a
block height
,parent hash
,extrinsics root
,state root
, anddigest
. This section will only focus on the extrinsics root. - Extrinsics are bundled together into a block as a series to be executed as each is defined in the runtime. The extrinsics root is a cryptographic digest of this series. This serves two purposes.
- First, it prevents any alterations to the series of extrinsics after the header has been built and distributed.
- Second, it provides a means of allowing light clients to succinctly verify that any given extrinsic did indeed exist in a block given only knowledge of the header.
2.2.2 Inherents
2.2.3 Signed transactions
2.2.4 Unsigned transactions
2.3 Account Abstractions
Substrate uses multiple sets of public/private key pairs to represent participants of the network, including validators
, nominators
and normal users
.
Stash Key
: a Stash account is meant to hold large amounts of funds. Its private key should be as secure as possible in a cold wallet.Controller Key
: a Controller account signals choices on behalf of the Stash account, like payout preferences, but should only hold a minimal amount of funds to pay transaction fees. Its private key should be secure as it can affect validator settings, but will be used somewhat regularly for validator maintenance.Session Keys
: these are "hot" keys kept in the validator client and used for signing certain validator operations. They should never hold funds.
2.4 Transaction
The transaction pool contains all transactions (signed
and unsigned
) broadcasted to the network that have been received and validated by the local node.
2.4.1 Validity
The transaction pool checks for transaction validity. Example validity checks are:
- Checking if the Transaction Index (nonce) is correct.
- Checking if the account has enough funds to pay for the associated fees.
- Checking if the signature is valid.
2.4.2 Sorting
If the transaction is valid, the transaction queue sorts transactions into two groups:
Ready Queue
Contains transactions that can be included in a new pending block. For runtimes built with FRAME, the transactions must follow the exact order in the ready queue.Future Queue
Contains transactions that may become valid in the future. For example, a transaction may have a nonce that is too high for its account. This transaction will wait in the future queue until the preceding transactions are included in the chain.
2.4.3 Transaction dependencies
The ValidTransaction struct defines the requires
and provides
parameters to build a dependency graph of transactions. Together with priority
(discussed below), this dependency graph allows the pool to produce a valid linear ordering of transactions.
At minimum, FRAME transactions have a provides tag of encode(sender ++ nonce)
and a requires tag of encode(sender ++ (nonce -1)) if nonce > 0
. Transactions do not require anything if nonce=0
. As a result, all transactions coming from a single sender will form a sequence in which they should be included.