A method and computer device for scaling leaf pages / middle pages

By using a Merkle Patricia Tree structure to manage contract account state data in a blockchain system and dynamically adjusting the tree shape, the problem of low organization efficiency of contract account state data is solved, achieving efficient and scalable data storage and retrieval.

CN118964351BActive Publication Date: 2026-07-17ANT BLOCKCHAIN TECHNOLOGY (SHANGHAI) CO LTD

Patent Information

Authority / Receiving Office
CN · China
Patent Type
Patents(China)
Current Assignee / Owner
ANT BLOCKCHAIN TECHNOLOGY (SHANGHAI) CO LTD
Filing Date
2024-07-26
Publication Date
2026-07-17

AI Technical Summary

Technical Problem

Existing blockchain systems suffer from low data organization efficiency and poor scalability when managing smart contract state data, especially contract account state variables, making it difficult to efficiently manage large amounts of contract account state data.

Method used

The Merkle Patricia Tree (MPT tree) structure is used to organize the state data of the contract account. By generating and updating tree nodes, the leaf pages and intermediate pages can be expanded and collapsed. The tree nodes in the logical page structure are generated or updated according to the tree structure construction rules, and the shape of the tree is dynamically adjusted to adapt to data changes.

Benefits of technology

It improves the management efficiency and scalability of contract account status data, ensures efficient storage and query performance of contract account status data, and supports the rapid processing of a large number of contract accounts in the blockchain network.

✦ Generated by Eureka AI based on patent content.

Smart Images

  • Figure CN118964351B_ABST
    Figure CN118964351B_ABST
Patent Text Reader

Abstract

A method for scaling leaf pages / intermediate pages includes: tree nodes corresponding to memory pages according to the divided logical page structure, where a memory page represents the content of all tree nodes corresponding to the logical page; a logical page is the result of aggregating several adjacent tree nodes according to the node association relationship of the tree structure, and a logical page contains at least one tree node, with different logical pages containing different tree nodes; logical pages are divided into intermediate pages and leaf pages, where an intermediate page contains one intermediate node as the root of the logical page and multiple intermediate nodes as child nodes of the root; a leaf page contains one leaf node, or a subtree consisting of at least two leaf nodes and at least one intermediate node; for a leaf page whose subtree shape changes, the leaf page is stretched when any of the following conditions are met: the number of leaf nodes in the leaf page reaches a high watermark threshold; or any intermediate node in the subtree of the leaf page is a full branch.
Need to check novelty before this filing date? Find Prior Art

Description

Technical Field

[0001] The embodiments in this specification belong to the field of blockchain technology, and in particular relate to a method and computer device for scaling leaf pages / middle pages. Background Technology

[0002] Blockchain is a novel application model of computer technologies such as distributed data storage, peer-to-peer transmission, consensus mechanisms, and cryptographic algorithms. In a blockchain system, data blocks are sequentially linked together to form a chain-like data structure, and a distributed ledger is cryptographically guaranteed to be immutable and unforgeable. Due to its decentralized, immutable, and autonomous characteristics, blockchain is receiving increasing attention and application. Summary of the Invention

[0003] The purpose of this invention is to provide a method and computer device for scaling leaf pages / middle pages, comprising:

[0004] A method for stretching leaf pages includes:

[0005] Tree nodes are generated / updated according to the tree structure construction rules; the tree nodes correspond to memory pages according to the divided logical page structure, and the memory pages are used to represent the content of all tree nodes in the corresponding logical pages; the logical page is the result of aggregating several adjacent tree nodes according to the node association relationship of the tree structure. A logical page contains at least one tree node, and different logical pages contain different tree nodes; the logical page is divided into intermediate pages and leaf pages. An intermediate page contains one intermediate node as the root of the logical page and multiple intermediate nodes as children of the root; a leaf page contains one leaf node, or contains at least two leaf nodes and at least one intermediate node to form a subtree;

[0006] For a leaf page whose subtree shape has changed, the leaf page shall be expanded if any of the following conditions are met:

[0007] (1) The number of leaf nodes in this leaf page has reached the high water level threshold;

[0008] (2) Any intermediate node in the subtree of this leaf page is full cross.

[0009] A method for shrinking leaf pages includes:

[0010] Tree nodes are generated / updated according to the tree structure construction rules; the tree nodes correspond to memory pages according to the divided logical page structure, and the memory pages are used to represent the content of all tree nodes in the corresponding logical pages; the logical page is the result of aggregating several adjacent tree nodes according to the node association relationship of the tree structure. A logical page contains at least one tree node, and different logical pages contain different tree nodes; the logical page is divided into intermediate pages and leaf pages. An intermediate page contains one intermediate node as the root of the logical page and multiple intermediate nodes as children of the root; a leaf page contains one leaf node, or contains at least two leaf nodes and at least one intermediate node to form a subtree;

[0011] For a leaf page whose subtree shape has changed, the leaf page shall be shrunk if any of the following conditions are met:

[0012] (1) The number of leaf nodes in this leaf page is lower than the low water level threshold;

[0013] (2) The number of slots occupied by any intermediate node in the subtree of this leaf page is less than the threshold.

[0014] A method for stretching a middle page includes:

[0015] Tree nodes are generated / updated according to the tree structure construction rules; the tree nodes correspond to memory pages according to the divided logical page structure, and the memory pages are used to represent the content of all tree nodes in the corresponding logical pages; the logical page is the result of aggregating several adjacent tree nodes according to the node association relationship of the tree structure. A logical page contains at least one tree node, and different logical pages contain different tree nodes; the logical page is divided into intermediate pages and leaf pages. An intermediate page contains one intermediate node as the root of the logical page and multiple intermediate nodes as children of the root; a leaf page contains one leaf node, or contains at least two leaf nodes and at least one intermediate node to form a subtree;

[0016] For intermediate pages whose subtree structure has changed, the intermediate page should be expanded if any of the following conditions are met:

[0017] (1) The number of intermediate nodes in the intermediate page has reached the high watermark threshold;

[0018] (2) Any intermediate node of the intermediate page is full cross.

[0019] A method for shrinking middle pages includes:

[0020] Tree nodes are generated / updated according to the tree structure construction rules; the tree nodes correspond to memory pages according to the divided logical page structure, and the memory pages are used to represent the content of all tree nodes in the corresponding logical pages; the logical page is the result of aggregating several adjacent tree nodes according to the node association relationship of the tree structure. A logical page contains at least one tree node, and different logical pages contain different tree nodes; the logical page is divided into intermediate pages and leaf pages. An intermediate page contains one intermediate node as the root of the logical page and multiple intermediate nodes as children of the root; a leaf page contains one leaf node, or contains at least two leaf nodes and at least one intermediate node to form a subtree;

[0021] For intermediate pages whose subtree structure changes, the intermediate page should be shrunk if any of the following conditions are met:

[0022] (1) The number of intermediate nodes in the intermediate page is lower than the low water level threshold;

[0023] (2) The number of slots occupied by any intermediate node in any layer of the intermediate page is less than the threshold.

[0024] For a memory page containing a leaf node, read the state from the leaf node into memory.

[0025] A computer device, comprising:

[0026] processor;

[0027] And a memory containing a program, wherein, when the processor executes the program, any of the operations described above are performed. Attached Figure Description

[0028] To more clearly illustrate the technical solutions of the embodiments in this specification, the drawings used in the description of the embodiments will be briefly introduced below. Obviously, the drawings described below are only some embodiments recorded in this specification. For those skilled in the art, other drawings can be obtained based on these drawings without creative effort.

[0029] Figure 1 This is a schematic diagram illustrating the deployment of a smart contract in one embodiment;

[0030] Figure 2 This is a schematic diagram illustrating the invocation of a smart contract in one embodiment;

[0031] Figure 3 This is a schematic diagram of a block storage structure in one embodiment;

[0032] Figure 4 This is a schematic diagram of a block storage structure in one embodiment;

[0033] Figure 5 This is a schematic diagram of an MPT tree in one embodiment;

[0034] Figure 6 This is a schematic diagram illustrating the modules involved in the transaction processing process and the relationship between CPU, memory, and disk in one embodiment;

[0035] Figure 7 This is a schematic diagram illustrating the modules involved in the transaction processing process and the relationship between CPU, memory, and disk in one embodiment;

[0036] Figure 8 This is a schematic diagram of the logical relationship of the state database in one embodiment;

[0037] Figure 9 This is a flowchart of reading status data in one embodiment;

[0038] Figure 10 This is a schematic diagram illustrating the reading of status data using a tree structure in one embodiment;

[0039] Figure 11 This is a schematic diagram illustrating the reading of status data using a tree structure in one embodiment;

[0040] Figure 12 This is a schematic diagram illustrating the reading of status data using a tree structure in one embodiment;

[0041] Figure 13 This is a schematic diagram illustrating the reading of status data using a tree structure in one embodiment;

[0042] Figure 14 This is a schematic diagram illustrating the reading of status data using a tree structure in one embodiment;

[0043] Figure 15 This is a schematic diagram of a block storage structure in one embodiment;

[0044] Figure 16 This is a schematic diagram of a block storage structure in one embodiment;

[0045] Figure 17 This is a schematic diagram of a block storage structure in one embodiment;

[0046] Figure 18 This is a schematic diagram of a block storage structure in one embodiment;

[0047] Figure 19 This is a schematic diagram of a block storage structure in one embodiment;

[0048] Figure 20 This is a schematic diagram of a block storage structure in one embodiment;

[0049] Figure 21 This is a schematic diagram of a block storage structure in one embodiment;

[0050] Figure 22 This is a schematic diagram of a block storage structure in one embodiment;

[0051] Figure 23 This is a schematic diagram of a block storage structure in one embodiment;

[0052] Figure 24 This is a schematic diagram of a block storage structure in one embodiment;

[0053] Figure 25 This is a schematic diagram of a block storage structure in one embodiment;

[0054] Figure 26 This is a schematic diagram of a block storage structure in one embodiment;

[0055] Figure 27 This is a schematic diagram of a block storage structure in one embodiment;

[0056] Figure 28 This is a schematic diagram of a block storage structure in one embodiment. Detailed Implementation

[0057] To enable those skilled in the art to better understand the technical solutions in this specification, the technical solutions in the embodiments of this specification will be clearly and completely described below with reference to the accompanying drawings. Obviously, the described embodiments are only some embodiments of this specification, and not all embodiments. Based on the embodiments in this specification, all other embodiments obtained by those skilled in the art without creative effort should fall within the scope of protection of this specification.

[0058] Blockchains are generally classified into three types: public blockchains, private blockchains, and consortium blockchains. In addition, there are various combinations of these types, such as private blockchain + consortium blockchain, consortium blockchain + public blockchain, etc. Public blockchains offer the highest degree of decentralization. Ethereum is a prime example of a public blockchain. Participants can read data records on the chain, participate in transactions, and compete for the right to record new blocks. Furthermore, participants (represented by nodes on the blockchain) can freely join and leave the network and perform related operations. Private blockchains, on the other hand, have write permissions controlled by a specific organization or institution, and data read permissions are governed by organizational regulations. Simply put, a private blockchain can be a weakly centralized system with strictly limited and few participating nodes. This type of blockchain is more suitable for internal use within specific organizations. Consortium blockchains fall between public and private blockchains, achieving "partial decentralization." Each node in a consortium blockchain typically has a corresponding entity or organization; participants join the network through authorization and form a consortium of interested parties to jointly maintain the blockchain's operation.

[0059] Whether it's a public, private, or consortium blockchain, besides supporting the transfer of native assets on the blockchain between accounts, it also provides smart contract functionality. A smart contract on the blockchain is a contract that can be triggered and executed by transactions on the blockchain system. Smart contracts can be defined in the form of code.

[0060] Taking Ethereum as an example, it allows users to create and invoke complex logic within the Ethereum network. At the core of Ethereum as a programmable blockchain is the Ethereum Virtual Machine (EVM), which can be run by every Ethereum node. The EVM is a Turing-complete virtual machine, meaning that various complex logics can be implemented using it. Users publish and invoke smart contracts in Ethereum, which run on the EVM. In fact, the virtual machine directly runs virtual machine code (virtual machine bytecode, hereinafter referred to as "bytecode"). Smart contracts deployed on the blockchain can be in the form of bytecode.

[0061] For example Figure 1 As shown, after Bob sends a transaction containing information about creating a smart contract to the Ethereum network, Node 1's EVM can execute this transaction and generate the corresponding contract instance. In Figure 1, "0x6f8ae93…" represents the address of this contract. The transaction's data field can store bytecode, and the transaction's to field is an empty account. After the nodes reach a consensus through the consensus mechanism, the contract is successfully created, and users can subsequently call this contract.

[0062] After a contract is created, a contract account corresponding to that smart contract is generated on the blockchain, with a specific address. The contract code and account storage are stored in this contract account. The behavior of the smart contract is controlled by the contract code, while the smart contract's account storage preserves the contract's state. In other words, a smart contract enables the creation of a virtual account on the blockchain that contains both contract code and account storage.

[0063] As mentioned earlier, the `data` field of a transaction that creates a smart contract can store the bytecode of that smart contract. Bytecode consists of a series of bytes, with each byte representing an operation. For reasons of development efficiency and readability, developers can choose to write smart contract code in a high-level language instead of directly writing bytecode. The smart contract code written in a high-level language is compiled by a compiler to generate bytecode, which can then be deployed to the blockchain. Ethereum supports many high-level languages, such as Solidity, Serpent, and LLL.

[0064] Taking Solidity as an example, contracts written in it are very similar to classes in object-oriented programming languages. A contract can declare various members, including state variables, functions, function modifiers, events, etc. State variables are values ​​stored in the smart contract's account store and are used to save the contract's state.

[0065] The following is a simple code example 1 of a smart contract written in the Solidity language:

[0066] Contract SimpleStorage {

[0067] string storedData;

[0068] function set(string s) {

[0069] storedData = s;

[0070] }

[0071] function get() constant returns (string) {

[0072] return storedData;

[0073] }

[0074] }

[0075] In addition, such as Figure 2As shown, still using Ethereum as an example, after Bob sends a transaction containing information about calling a smart contract to the Ethereum network, the EVM of node 1 can execute this transaction and generate the corresponding contract instance. In Figure 2, the `from` field of the transaction is the address of the account initiating the smart contract call, and "0x6f8ae93…" in the `to` field represents the address of the smart contract being called. The `data` field of the transaction stores the method and parameters for calling the smart contract. Additionally, a `value` field may be included. After calling the smart contract, the value of `storedData` may change. Subsequently, a client can access the transaction through a specific blockchain node (e.g., ...). Figure 2 Node 6) View the current value of storedData.

[0076] Smart contracts can be executed independently on each node of the blockchain network in a prescribed manner. All execution records and data are stored on the blockchain. Therefore, when such a transaction is completed, the blockchain stores an immutable and unlost transaction certificate.

[0077] As mentioned earlier, `storedData` in the example above is the state variable, which is stored in the smart contract's account storage. In various blockchain networks that introduce smart contracts, such as Ethereum, accounts typically include two types:

[0078] Contract account: Stores the executed smart contract code and the values ​​of the state within the smart contract code. It can usually only be activated by an external account.

[0079] Externally owned account: The user's account.

[0080] The design of external and contract accounts is essentially a mapping from account addresses to account states. Account states typically include fields such as Nonce, Balance, Storage root, and CodeHash. Nonce and Balance exist in both external and contract accounts. CodeHash and Storage root attributes are generally only valid for contract accounts.

[0081] Nonce: A counter. For external accounts, this number can represent the number of transactions sent from the account address; for contract accounts, it can be the number of contracts created by the account.

[0082] Balance: The balance of this address.

[0083] Storage root: The hash of the root node of an MPT tree that organizes the storage of state variables for contract accounts.

[0084] CodeHash: The hash value of the smart contract code. For contract accounts, this is the hash value of the smart contract; for external accounts, since the smart contract is not included, the CodeHash field can generally be an empty string or a string of all zeros.

[0085] MPT stands for Merkle Patricia Tree, a tree structure that combines the features of a Merkle Tree and a Patricia Tree (a compressed prefix tree, a more space-efficient Trie tree, also known as a dictionary tree). The Merkle Tree algorithm calculates a hash value for each transaction, then joins each pair of transactions and calculates the hash again, continuing until the top-level Merkle root. Ethereum uses an improved MPT tree, such as a 16-ary tree structure, which is often simply referred to as an MPT tree.

[0086] The Ethereum MPT tree data structure includes a state trie. The state trie contains key-value pairs (kv) representing the storage content for each account in the Ethereum network. The "key" in the state trie can be a 160-bit identifier (such as the address of an Ethereum account or part of its hash value, hereinafter referred to as the account address), distributed across storage from the root node to the leaf nodes of the state trie. The "values" in the state trie are generated by encoding the information of the Ethereum account using recursive-length prefix encoding (RLP). As mentioned earlier, for external accounts, the values ​​include nonce and balance; for contract accounts, the values ​​include nonce, balance, codehash, and storageroot.

[0087] A contract account is used to store the state of a smart contract. Once a smart contract is deployed on the blockchain, a corresponding contract account is created. This contract account typically has several states defined by state variables within the smart contract, which generate new values ​​during the smart contract's creation and execution. A smart contract generally refers to a contract defined in code within a blockchain environment that can automatically execute its terms. Once an event triggers a term in the contract (meeting the execution conditions), the code can execute automatically. In the blockchain, the contract's state is stored in a storage trie. The hash value of the storage trie's root node is stored in the aforementioned storage root, thus locking all the contract's states to this contract account through hashing. The storage trie is also an MPT tree structure, storing a key-value mapping from state addresses to state values. Information from the root node to the leaf node of the storage trie tree is arranged sequentially to store the address of a state, and the leaf node stores the state's value.

[0088] like Figure 3 In some blockchain data storage examples, each block header includes several fields, such as the previous block hash (prev Hash in the diagram), a nonce (in some blockchain systems, this nonce is not random, or the nonce in the block header is not enabled), a timestamp, a block number, a state root hash (State_Root), a transaction root hash (Transaction_Root), and a receipt root hash (Receipt_Root). The Prev Hash in the header of the next block (e.g., block N+1) points to the previous block (e.g., block N), which is the hash value of the previous block. In this way, the blockchain achieves locking of the previous block by the next block through the block header. State_Root, Transaction_Root, and Receipt_Root lock the state set, transaction set, and receipt set, respectively. The state set, transaction set, and receipt set are organized in a tree structure. Generally, they can be the same tree structure or different tree structures. For example, Ethereum uses the same MPT structure. In some tree structures like Ethereum that include a set of smart contract states, there is a two-level MPT structure: the leaf nodes of the upper-level MPT structure include two types: external accounts and contract accounts; each contract account includes the lower-level MPT structure, and the leaf nodes of the lower-level structure include the values ​​of the state in the contract account.

[0089] Figure 4This is a schematic diagram of a blockchain data storage structure. Taking Ethereum as an example again, it can be combined with... Figure 3 As shown, `state_root` is the hash value of the root of the MPT tree composed of the states of all accounts in the current block. In other words, pointing to `state_root` is an MPT-style state trie. The root node of this MPT tree is generally an extension node or a branch node, and `state_root` typically stores the hash value of this root node. The root node can be connected to one or more extension nodes / branch nodes below it; these multiple levels of tree nodes can be collectively called internal nodes. A portion of the values ​​from each node from the root node to the leaf node in this MPT can be concatenated sequentially to form an account address as the key. The account information stored in the leaf node is the value corresponding to this account address, thus forming a key-value pair. This key can also be a portion of the hash value of the account address (using a hash algorithm such as SHA3), and its stored value can be an rlp (Account), i.e., the rlp encoding of the account information. The account information consists of a four-tuple of [nonce, balance, storage root, codeHash]. As mentioned earlier, external accounts typically only have the nonce and balance fields, while the storage root and codeHash fields default to storing empty strings or strings of all zeros. This means that external accounts do not store contracts or the state variables generated after contract execution. Contract accounts generally include Nonce, Balance, Storage root, and CodeHash. Nonce is the transaction counter for the contract account; Balance is the account balance; Storage root corresponds to another MPT, which links to contract-related state information; and CodeHash is the hash value of the contract code. Whether external or contract accounts, their account information is generally located in a single leaf node. The path from the root node's Extension Node / BranchNode to each account's Leaf Node may involve several branch nodes and extension nodes.

[0090] The state trie can be an MPT-style tree, typically a 16-ary tree, meaning each level can have a maximum of 16 child nodes. An Extension Node, used to store a common prefix, typically has one child node, which can be a Branch Node. A Branch Node can have a maximum of 16 child nodes, potentially including Extension Nodes and / or Leaf Nodes.

[0091] For a contract account within the state trie, its `storage_root` points to another tree, also in MPT form, which stores data related to the contract's execution state variables. This `storage_root` points to an MPT-form tree called the Storage Trie, specifically the hash value of the root node. Generally, this Storage Trie also stores key-value pairs. The key represents the address of the state variable, and its value can be the result of processing the state variable's declaration location (counting from 0) according to certain rules, such as SHA3 (state variable declaration location) or SHA3 (contract name + state variable declaration location). The value stores the state variable's value (e.g., an RLP-encoded value). A portion of the data stored along the path from the root node through intermediate nodes to the leaf node forms the key, and the leaf node stores the value. As mentioned earlier, this Storage Trie can also be an MPT-form tree, typically a 16-ary tree, meaning that a Branch Node can have a maximum of 16 child nodes, which may include Extension Nodes and / or Leaf Nodes. An ExtensionNode typically has one child node, which can be a Branch Node or a Leaf Node.

[0092] For example Figure 4The Leaf Node Account P in the state trie is a contract account whose Storage Root locks all the states stored in the contract. These states are organized as an MPT tree, with a tree structure like the Storage trie linked by the Storage Root. In this linked Storage trie, taking Leaf Node StateVariable N as an example, if it is the value of storedData in the aforementioned contract code example, then its key is sha3 (the declaration location of storedData, i.e., line 2 of the code), and its value is s (for simplicity, the encoding format of the value is omitted here, such as RLP, and similarly, it will not be elaborated further). The key values ​​are distributed sequentially from the root node to the leaf node (i.e., Leaf Node Variable N) of the storage trie.

[0093] For example, Figure 4 In the state Trie, Leaf Node Account C is an external account. Its key is sha3(Address C), which is the hash value of the address of account C (using a hash algorithm such as sha3). Its stored value can be (Account), where the account information Account is a tuple of [nonce, balance]. As mentioned earlier, since Account C is an external account, its account information consists of nonce and balance (codehash and storage root are omitted here, but similarly below). For example, for an external account with nonce 20 and balance 4550, the leaf node State Variable C will store nonce=20 and balance=4550. The address of Account C is the key, and its values ​​are distributed sequentially from the root node to the leaf node (i.e., Leaf Node Variable C) of the state Trie.

[0094] These states, including the key-value pairs of external accounts and contract accounts, are ultimately stored in the database. However, the database does not directly store the states of these accounts (i.e., it does not directly store their key-value pairs), but rather stores the key-value values ​​of each tree node itself.

[0095] like Figure 5As shown in the example, in the upper-level MPT structure, for leaf node A1, the key of the leaf node is formed by sequentially combining a7 of the shared nibble in the root node A8 (Extension Node), slot 1 of the intermediate node A7 (Branch Node), and key-end 1335 in leaf node A1, which is a711335. Balance=45.0ETH and Nonce=n1 are stored in this leaf node. For leaf node A2, the key of the leaf node is formed by sequentially combining a7 of the shared nibble in the root node A8 (Extension Node), slot 7 of the intermediate node A7 (Branch Node), d3 of the shared nibbles in node A6 (Extension Node), slot 3 of the intermediate node A5 (Branch Node), and key-end 7 in leaf node A2, which is a77d337. Balance=1.00WEI and Nonce=n2 are stored in this leaf node. For leaf node A3, the key is constructed by sequentially combining a7 from the shared nibble in root node A8 (Extension Node), slot f in intermediate node A7 (Branch Node), and key-end 9365 in leaf node A3, resulting in a7f9365. This leaf node stores Balance=1.1ETH and Nonce=n3. For leaf node A4, the key is constructed by sequentially combining a7 from the shared nibble in root node A8 (Extension Node), slot 7 in intermediate node A7 (Branch Node), d3 from the shared nibbles in node A6 (Extension Node), slot 9 in intermediate node A5 (Branch Node), and key-end 7 in leaf node A4, resulting in a77d397. This leaf node stores Balance=0.12ETH, Nonce=n4, CodeHash=c1, and Storage root=s1. s1 can be H(A10), which is the hash of the root node A10 of the next level tree. The leaf nodes of A1, A2, and A3 store information about external accounts, while the leaf node of A4 stores information about contract accounts. For each contract account, there is a next-level MPT, forming a Storage Trie used to store the state variables of that contract account.

[0096] like Figure 5As shown in the example, in the MPT structure of the next level, for the leaf node A11, through the slot 3 in the root node A10 (Branch Node) - the key - end 35b2e4 in the leaf node A11, they are sequentially combined to form the key of this leaf node, which is 335b2e4. In this leaf node, "Zhang San_A = 20" is stored. For example, it means that the share of digital assets of type A defined in the contract belonging to Zhang San is 20, that is, the balance of Zhang San's type - A assets is 20. For the leaf node A12, through the slot 7 in the root node A10 (Branch Node) - the key - end c25988 in the leaf node A12, they are sequentially combined to form the key of this leaf node, which is 7c25988. In this leaf node, "Li Si_B = 20" is stored. For example, it means that the share of digital assets of type B defined in the contract belonging to Li Si is 50, that is, the balance of Li Si's type - B assets is 50. For the leaf node A15, through the slot f in the root node A10 (Branch Node) - the shared nibble a in the intermediate node A13 (Extension Node) - the slot 6 in the intermediate node A14 (Branch Node) - the key - end be33 in the leaf node A15, they are sequentially combined to form the key of this leaf node, which is fa6be33. In this leaf node, "storedData = s" is stored. For the leaf node A16, through the slot f in the root node A10 (Branch Node) - the shared nibble a in the intermediate node A13 (Extension Node) - the slot 9 in the intermediate node A14 (Branch Node) - the key - end 9365 in the leaf node A16, they are sequentially combined to form the key of this leaf node, which is fa99365. In this leaf node, "Wang Wu_A = 35" is stored. For example, it means that the share of digital assets of type A defined in the contract belonging to Wang Wu is 35, that is, the balance of Wang Wu's type - A assets is 35.

[0097] In the node composition of the above - mentioned MPT tree, the prefix "prefix" is used to represent the type of tree node. For example, 0 represents an Extension Node containing an even number of shared nibbles, 1 represents an Extension Node containing an odd number of shared nibbles, 2 represents a Leaf Node containing an even number of nibbles, and 3 represents a Leaf Node containing an odd number of nibbles.

[0098] In the above node structure, the hash value of the entire content of the next tree node is filled into the corresponding position of the previous tree node. The database actually stores the key-value mapping for each tree node, where the value includes the content stored in that tree node, and the corresponding key is the hash value of the entire content of that tree node. Thus, the actual key-value pairs of the tree nodes stored in the database are shown in the following table:

[0099] Key Value (Logical representation, and needs to be RLP encoded in persistent storage) H(A9) Prev Hash: , Nonce: , Timestamp: , Block Num: , State Root: H(A8), Transaction Root: , Receipt Root: ,… H(A8) prefix:0, shared nibble(s): a7, next node: H(A7) H(A7) 0: , 1: H(A1), 2: , 3: , 4: , 5: , 6: , 7: H(A6), 8: , 9: , a: , b: , c: , d: , e: , f: H(A3), value: H(A1) prefix:2, Key-end:1335, balance: 45.0ETH, nonce: n1 H(A6) value: prefix:0, shared nibble(s):d3, next node: H(A5) H(A3) prefix:2, Key-end:9365, balance: 1.1ETH, nonce: n3 H(A5) 0: , 1: , 2: , 3: H(A2), 4: , 5: , 6: , 7:, 8: , 9: H(A4), a: , b: , c: , d: , e: , f:, value: H(A2) prefix:0, Key-end:7, balance: 1.00WEI, nonce: n2 H(A4) prefix:0, Key-end:7, balance: 0.12ETH, nonce: n4, codehash:c1, storage root: H(10) H(A10) 0: , 1: , 2: , 3: H(A11), 4: , 5: , 6: , 7: H(A12), 8: , 9: , a: , b: , c: , d: , e: , f: H(A13), value: H(A11) prefix:2, Key-end:35b2e4, value: Zhang San_A = 20 [[ID= ​ ​ prefix:1, shared nibble(s):a, next node: H(A14) H(A14) 0: ,1: ,2: ,3: ,4: ,5: ,6: H(A15) ,7:, 8: ,9: H(A16) ,a: ,b: ,c: ,d: ,e: ,f:, value: H(A15) prefix:2, Key-end: be33, value: storedData=s H(A16) prefix:2, Key-end: 9365, value: Wang Wu_A=50

[0100] Table 1. Key-value pairs of tree nodes actually stored in the database.

[0101] In Table 1 above, H() represents hash calculation. This anchors the hash value of the next tree node to the previous tree node. Through this layer-by-layer hashing, the root hash of the entire state trie tree is obtained, and this root hash is locked into the state root field of the block header.

[0102] In some blockchain systems, the blockchain platform's code may include P2P (Peer-to-Peer) modules, consensus modules, execution modules, and storage modules. P2P is a way of organizing computer networks; unlike common web networks, P2P is decentralized and distributed. P2P modules enable the distributed propagation of data. For blockchain nodes, P2P modules allow for the peer-to-peer transmission and reception of receipts. Different participants can establish a distributed blockchain network through deployed nodes. The ledger constructed using a chain-like block structure is stored on each node (or most nodes, such as consensus nodes) in the distributed blockchain network; this is also known as a decentralized (or multi-centralized) distributed ledger. Such blockchain systems need to address the issues of consistency and correctness of the ledger data across multiple decentralized (or multi-centralized) nodes. Each node runs the same blockchain platform program. With a certain level of fault tolerance, the consensus module ensures that all loyal nodes have the same transactions, guaranteeing consistent execution results for the same transactions. The transactions and execution results are then packaged into blocks. Current mainstream consensus mechanisms include Proof of Work (POW), Proof of Stake (POS), Delegated Proof of Stake (DPoS), Practical Byzantine Fault Tolerance (PBFT), and Honey Badger Byzantine Fault Tolerance (HoneyBadgerBFT). During the consensus process, the consensus module can also typically generate timestamps for the blocks corresponding to the current transaction set. The execution module can execute transactions, including ordinary transfers and transactions involving contracts, either before or after the consensus module completes consensus. For transactions involving contracts, the execution module can introduce a virtual machine, such as the Ethereum Virtual Machine (EVM), to execute the smart contract code. This EVM shields the differences in hardware configuration and software environment across nodes, ensuring that the process and results of smart contract execution are identical on all nodes. Furthermore, the sandbox environment prevents smart contract execution from impacting the blockchain platform code, other programs, or the operating system on the host machine. In one scenario for a consortium blockchain, nodes can determine the content and order of transactions in a transaction set through a consensus module, and then output a deterministic transaction set as the consensus result to the execution module. The execution module generates execution results by executing ordinary transfer transactions or transactions involving contracts, and sends them to the storage module. The storage module is responsible for storing the execution results in persistent storage media on the node's local machine.

[0103] like Figure 6 A blockchain node, as shown, physically includes CPU, memory, and disk. The blockchain platform code executed by this node can include a P2P module, a consensus module, an execution module, and a storage module. The P2P, consensus, and execution modules generally require CPU and memory to function. The storage module can include a tree construction module, a block header generation module, a WAL (Write Ahead Log) module, and a state database module. The tree construction module is used to build a tree (e.g., an MPT tree) based on the state key-value pairs passed from the execution module, such as the aforementioned state trie and storage trie, thus obtaining the key-value pairs of the tree nodes; this generally requires CPU and memory. The block header generation module is used to generate block headers based on the root node of the tree constructed by the tree construction module and other data (such as the previous block hash, timestamp, block number, etc.); this generally requires CPU and memory. The WAL module persistently stores the key-value pairs (kv) of the leaf nodes generated by the tree-building module before writing them to the state database module. This prevents data loss due to power outages or other unforeseen circumstances during the writing process and allows for data recovery in such cases. It typically requires the participation of CPU, memory, and disk. The state database module stores the tree node kv pairs (kv) constructed by the tree-building module, as shown in Table 1, on a persistent storage device. Since the tree node data will ultimately be written to persistent storage media (such as the disk in the diagram), the state database module generally requires disk access in addition to CPU and memory.

[0104] From a storage structure perspective, the aforementioned Merkle tree structures, such as Ethereum's MPT and Libra's SMT (Sparse Merkle Tree, similar to MPT), can reside in the tree construction module and be stored in memory, according to the correspondence shown in Table 1. The upper-level Merkle tree is a prefix tree (prefix tree), capable of organizing data and obtaining a unique Merkle root for the organized data. Leaf nodes can store state values, and the root node to intermediate nodes to leaf nodes implement a lexicographical index of the state keys. These tree nodes are encoded as keys according to certain rules, and their contents are encoded as values, ultimately stored in the lower-level database. The database mostly adopts an LSM (Log-Structured Merge-Tree) type structure for NoSQL Key-Value DBs (Database; Key-Value DB is also simply KVDB), located in the state database module, and ultimately stored on disk. Specifically, examples of databases include Ethereum's LevelDB and Libra's RocksDB. Both of these KVDBs are based on the LSM storage engine.

[0105] The LSM storage engine is a tiered, ordered, disk-oriented storage engine that borrows from the append-only (rather than modify) nature of the Log. Its core idea is to fully leverage the fact that sequential, batch writes to disk are far more efficient than random writes, sacrificing some read efficiency for maximum write efficiency. Generally, maximizing disk performance involves reading or writing a fixed-size block of data at a time, minimizing random access operations. LSM's design is based on this disk characteristic and assumes sufficient memory. Instead of writing data to disk every time it's updated, it first keeps the latest data in memory. Once a sufficient amount of data has accumulated, it uses merge sort to combine the data in memory with the data on disk and appends it to disk in batches.

[0106] The following is Figure 7Taking an example, let's further illustrate the storage process of the state data module. After the tree building module generates tree node key-value data and sends it to the storage module, this key-value data is first written to the Write-Ahead Log (WAL) in an append-only manner and stored on the disk. Then, the tree node key-value data is passed to the state database module. As mentioned earlier, writing to the WAL first prevents data loss due to power outages or other events during the writing of the tree node key-value data generated by the tree building module to the state database module, and allows for data recovery in such cases. After receiving the tree node key-value data, the state database module first stores it in memory, specifically in a MemTable within memory. MemTables can provide concurrent read and write operations. Multiple MemTables can exist in memory. When the amount of data in a MemTable reaches a certain threshold, such as 256MB, the data in the MemTable can be flushed to the disk. To avoid write operations to the MemTable blocking the flush process, the MemTable is converted into an immutable Memtable, meaning the Immutable Memtable is set to read-only, and a new MemTable is created to receive the newly passed tree node key-value pairs. This new MemTable can provide concurrent read and write operations (as shown in the New MemTable diagram). The storage engine writes the data in the Immutable MemTable to disk.

[0107] On disk, KVDB stores data in multi-level SST (Sorted String Table) files. SST originates from the Google Bigtable paper. Bigtable is a distributed data storage system designed by Google to handle massive amounts of data; it's a non-relational database. SST can be used to store data files within Bigtable and is an efficient key-value file storage format. Content stored on persistent storage media can also be called a file.

[0108] SST can include multiple layers, such as 3, 4, 5, 6, 7 or more layers. Figure 7The diagram illustrates a three-level scenario: level 0, level 1, and level 2. Generally, the total capacity of the SST in a higher level is significantly smaller than that in a lower level. For example, the total capacity of the SST in level 0 is 1GB, in level 1 it is 10GB, and in level 2 it is 100GB. Assume the MemTable has a capacity of 256MB. Tree nodes (key-value pairs) corresponding to blocks can be written to the tree-building module, and then to the MemTable. After writing the tree key-value pairs corresponding to one or more blocks to the MemTable, the MemTable's space usage may reach 256MB. This MemTable is then converted into an Immutable MemTable, and the data in the Immutable MemTable can be written (flush, referring to the operation of writing data from memory to disk) to disk. Specifically, the data in the MemTable can be flushed to the Level 0 SST on disk. On the other hand, as mentioned earlier, a new MemTable is generated to receive newly incoming tree node key-value pairs and provide concurrent read / write operations.

[0109] As mentioned earlier, each level of disk storage can include multiple SST files. The key-value pairs stored in the SSTs of Level 1 and lower levels are generally stored in key order, and the key values ​​in different SSTs within the same level are also ordered and non-repeating. For example, Level 1 includes three SSTs, the leftmost one... 11 It includes 1000 kV, for example, <k1-v1> <k2-v2> <k3-v3>... <k 1000 -v 1000 And arrange them in ascending order of k, for example, k1=10b43c032a46, k2=1118d46f41e1, k3=1b44942a3d6e, ..., k 1000 =2018df9326a7. It can be seen that the left-hand SST... 11 It contains k1 < k2 < k3 < ... < k 1000 But k1, k2, k3, ... k 1000 They are not necessarily consecutive. Similarly, the intermediate SSTs... 12 For example, it includes 800 kV. <k1-v1> <k2-v2> <k3-v3>... <k 800 -v 800 > and arrange them in ascending order of k, for example, k1=21a514c0a7e1, k2=21b46b994214, k3=21b489571b6d, ..., k 800 =284a5df3fca7. It can be seen that the middle SST... 12 It contains k1 < k2 < k3 < ... < k 800 However, similarly, k1, k2, k3, ... k 800 They are not necessarily consecutive. Similarly, the SST on the right... 13 For example, it includes 1100 kV. <k1-v1> <k2-v2> <k3-v3>... <k 1100 -v 1100 > where k is arranged in ascending order, for example k1=3a5e55ac3fe1, k2=3a5e55ac3fe2, k3=3afb8ed31526, ..., k 1100 =400a51ef1405. It can be seen that the SST on the right... 13 It contains k1 < k2 < k3 < ... < k 1100 However, similarly, k1, k2, k3, ... k 1100 They are not necessarily continuous. Furthermore, overall, the left SST... 11 The minimum value of k is less than the left-hand side SST. 11 The maximum value of k is less than the middle SST. 12 The minimum value of k < the middle SST 12 The maximum value of k is less than the right-hand side SST. 13 The minimum value of k is less than the SST on the right. 13 The maximum value of k. Level 2, Level 3... are similar, that is, within each SST in each level, there is a size order relationship in terms of the value of k, and among multiple SSTs in each level, there is a size relationship in terms of the range of k.

[0110] In Level 0, key-value pairs (kv) within a single SST can be sorted according to the size of their k values. However, the k values ​​across multiple SSTs do not necessarily have a range-based relationship. This is because the MemTable typically stores multiple kv values ​​corresponding to each block in ascending order (either from oldest to newest block or from smallest to largest block number, since newer blocks have larger block numbers and older blocks have smaller block numbers). These k values ​​are the hash values ​​of tree nodes, and changes in the content of tree nodes are highly likely to result in significantly different hash values ​​(i.e., k values). Sorting the kv values ​​within an SST in Level 0 according to their k values ​​is efficient and feasible in memory; however, sorting by k values ​​is not strictly prohibited. For example, when the MemTable's capacity reaches 256MB, it may store multiple kv values ​​corresponding to multiple blocks. This MemTable is then converted into an Immutable MemTable. These kv values ​​in the Immutable MemTable can be sorted by their k values ​​and written to the left-hand SSTs in Level 0. There may be multiple processes of writing different Immutable MemTables to the same SST before the SST on the left side of Level 0 is updated. 01 Once the space is full, it can then be written to the SST on the right side of Level 0 in a similar manner. 02 Although the key-value pairs (kv) written to a Level 0 SST by a single Immutable MemTable are sorted, the sets of kv written to the same SST by different Immutable MemTables in Level 0 are generally not sorted by size. Similarly, the kv ranges between different SSTs (e.g., left and right SSTs) are also not sorted by size. This means that the ranges of k in the left and right SSTs in Level 0 may overlap. Likewise, since the kv written to an SST in Level 0 can be written multiple times after a MemTable is full, and the ranges of kv during these multiple writes generally overlap, the multiple kv stored in each SST in Level 0 generally do not have a specific order, nor do the ranges between different SSTs in Level 0 generally have a specific order. Of course, if an Immutable MemTable writes to an SST in Level 0 in a single operation, then because the Immutable MemTable sorts the kv when writing to that SST, the kv stored in that SST are also sorted by k.

[0111] Furthermore, when the storage capacity of Level 0 reaches or approaches its limit, a process called "compaction" is used to write the data from Level 0 into Level 1. During this compaction process, the key-value pairs (kv) in each SST within Level 0 and some or all of the kv in Level 1 can be transferred to memory, sorted in memory, and then written to the SSTs of Level 1. Because sorting occurs during compaction, within each SST of Level 1, there is a size order relationship in the value of k, and across multiple SSTs in Level 1, there is a size order relationship in the range of k. In other words, within each SST of Level 1, the kv values ​​are ordered according to... <k1-v1> <k2-v2> <k3-v3>... <k n -v n Arranged in the order of >, and k1 < k2 < k3 < ... < k n And k1, k2, k3, ... k n They are not necessarily continuous. Moreover, generally speaking, for two adjacent SSTs, the minimum value of k in the left SST < the maximum value of k in the left SST < the minimum value of k in the right SST < the maximum value of k in the right SST. For example... Figure 8 As shown in the image.

[0112] During compaction, the key-value pairs (kv) in each SST within Level 0 and the key-value pairs in some SSTs within Level 1 can be loaded into memory for sorting. The SSTs within Level 1 can be SSTs whose key-value pairs overlap with those in Level 0; that is, SSTs whose key-value pairs overlap with those in each SST of Level 0. Specifically, for example, in the above example, Level 1 includes 3 SSTs... 11 The key range is 10b43c032a46~2018df9326a7, SST 12 The key range is 21a514c0a7e1~284a5df3fca7, SST 13 The key range is 3a5e55ac3fe1~400a51ef1405. For example, the key range in each SST within Level 0 is 18c49a405e32~24d35f39ab56. It can be seen that the key ranges in Level 1 overlap with those in Level 0 for some SSTs. 11 and SST 12 Thus, during compaction, the key-value pairs (kv) in each SST within Level 0 and the key-value pairs (kv) in each SST within Level 1 are... 11 SST 12 The key-value pairs can be loaded into memory and sorted, and then the sorted results can be written back to the Level 1 SST.

[0113] Similarly, when the storage capacity of Level 1 reaches its limit, a compaction process is used to write the data from Level 1 to Level 2. During this compaction process, the key-value pairs (kv) of each SST in Level 1 and some or all of the kv of some SSTs in Level 2 can be first loaded into memory, sorted in memory, and then written to the SSTs of Level 2. Likewise, if there is a Level 3 below Level 2, when the storage capacity of Level 2 reaches its limit, a compaction process is used to write the data from Level 2 to Level 3. Again, during this compaction process, the key-value pairs of each SST in Level 2 and some or all of the SSTs in Level 3 can be first loaded into memory, sorted in memory, and then written to the SSTs of Level 3. And so on.

[0114] In this way, overall, the data stored in the upper-level SST is newer than that in the lower-level SST. The newest data is stored in memory, the second newest data is stored in Level 0, and so on, with the oldest data stored in the SST within the lowest level. Furthermore, compaction can be used for garbage collection, such as deleting data marked for deletion.

[0115] Sorted key-value pairs can be efficiently retrieved, for example, using binary search. Binary search, also known as half-interval search, has the following algorithm: Define `left` as the leftmost element position of the sequential list, `right` as the rightmost element position, and `mid` = (left + right) / 2, which is the middle position of the sequential list; compare the value to be searched with the value at position `mid`; since the list is ordered, if the value to be searched is smaller than `mid`, only the first half of the list needs to be searched; otherwise, only the second half needs to be searched (if the two values ​​are equal on the first comparison, the current value's position is returned directly). This process continues until the value is found or it is determined that the value to be searched is not in the list (i.e., the search fails).

[0116] Such storage engines suffer from read amplification and write amplification issues when reading and writing data, which will be explained in detail below.

[0117] In a blockchain system employing the aforementioned storage engine, the execution module may need to read an existing state during transaction execution. For example, in a typical transfer transaction, external account A transfers a certain amount (e.g., f) of assets to external account B, requiring adjustments to the account balances. Assuming that before the transaction, account A's balance is a and account B's balance is b, the transaction execution sets account A's balance to (af) and account B's balance to (b+f). Therefore, this transaction needs to read the values ​​of the state variables a and b during execution. Another example is a contract call transaction. External account C initiates a call to contract D. C initiates a transaction pointing to the address of contract account D, specifying the called function and input parameters in the transaction's data field. Assuming the called function in contract D includes judging the value of a global state d within the contract (assuming d is a boolean), and the judgment logic includes executing branch 1 if true and branch 2 if false, this contract call transaction needs to read the value of state d during execution.

[0118] During transaction execution, whether reading the values ​​of state variables a and b, or reading the value of state variable d, the execution module can first check if the value of that state variable exists in its own memory. If it does not exist, a read command is sent to the storage module. This read command can include the address of the state to be read, i.e., the state's key value. Upon receiving the read command, the storage module locates the root node of the state tree in the tree construction module. It then matches the state key value to be searched against the root node's shared nibble(s) field (for Extension Nodes) or slot (for Branch Nodes) from the beginning. Next, it reads the hash of the next-level tree node (which can be an Internal Node or a Leaf Node; we will use an Internal Node as an example) from the matched position. It then first searches for the hash in the tree construction module's memory. If it is not found there, it searches in the state database module's memory. If it is still not found there, it searches in the state database module's file. Specifically, the search can begin with a lookup within the SST at Level 0. If the hash value is not found there, the search continues within an SST at Level 1, and so on, down to the next SST at each lower level, until the next Internal Node pointed to by the hash value is found. After unpacking this Internal Node, the remaining fields of the key value of the state address to be read are matched from front to back. If a match is found, the hash value is read from the match point, and the search jumps to the next level tree node pointed to by that hash value. This process is repeated, unpacking Internal Nodes level by level and matching the remaining fields of the key value of the state address to be read from front to back. The hash value at the match point serves as the basis for the next lookup of intermediate or leaf nodes, until a Leaf node is matched, from which the state value is read. During this process, some key-value pairs of tree nodes at each level may not exist in the memory of the tree building module but are located in the state database module. Therefore, it may be necessary to read them from the state database module into memory for further operations. The key can be searched first in the MemTable or Immutable MemTable of the state database module. If it does not exist, further searching of the various levels of SST files on disk is required. For Internal Nodes and Leaf Nodes existing on disk, they need to be loaded into memory and decoded (deserialized) to obtain their contents. Specifically, for example, the search can begin by sequentially searching the SST files of level 0. If each SST in level 0 is sorted, a binary search can be performed within each SST based on the hash value of the intermediate / leaf node. Once found, the key (v) is loaded into memory and decoded and matched.If the value is not found in the SST at Level 0, a binary search is performed in Level 1 based on the hash value of the intermediate / leaf node. If the value is still not found, a binary search is performed in Level 2. If the value is found, the value corresponding to the k is loaded into memory and decoded. This process continues until a leaf node of the tree structure is matched and its value is read. Since the overall SST at Levels 1, 2, and lower levels is sorted, a binary search can generally be performed at each level.

[0119] From the above process of reading a state key-value pair, it can be seen that this reading process requires binary search in multiple SSTs at different levels based on the hash value of the tree node. This may require reading a large number of files in multiple SSTs and loading them into memory, which leads to read amplification. Assuming the database includes Level 0, Level 1, Level 2, ..., Level M-1, for a total of M levels, then in the worst case, reading the data of a state requires at least M disk accesses (greater than M because in the worst case, N SSTs at Level 0 may require more than 1 but less than or equal to N search operations).

[0120] Furthermore, if the tree-building module is missing a key-value pair (kv) for a particular tree node while constructing the path from the state key-value pair to the root node, it may need to perform a binary search from Level 0, Level 1, Level 2, etc., with a similar principle to the process described above. In the transaction example above, for instance, after the transaction is executed, the value of the execution result (af), the value of (b+f), and the value of the contract state d need to be written to the state database. For the values ​​to be written to the database, the execution module calls the storage interface of the storage module, outputting the key-value pairs of the state to the storage module. The tree-building module in the storage module generates the key-value pairs of the tree nodes from the root to the intermediate and leaf nodes based on the state key-value pairs, writes these key-value pairs to the WAL module, and then writes this series of key-value pairs to the MemTable of the state database module, marking them as dirty data. Dirty data typically refers to data that has been written to the MemTable but has not yet been written to persistent storage (such as SSTable). Dirty data can be written to disk during the aforementioned flush process. The state database module then writes some key-value pairs, including the tree node key-value pairs, from the MemTable to the SST file on disk. Once the MemTable is persisted to the SSTable, the data within it is no longer dirty data, i.e., it becomes "clean" data. It is evident that the above process of persistently storing a state key-value pair is quite complex, consumes significant computational and memory resources, and introduces write amplification issues.

[0121] The complexity of the read and write processes, as well as the read amplification and write amplification issues, pose challenges to the high-performance requirements and large-scale applications of blockchain.

[0122] This application provides an embodiment of a method for reading blockchain state data. This method embodiment can be applied to the storage module of a blockchain node. The storage module constructs a tree-structured world state in memory. The leaf nodes of the tree structure may include the content of the state data or the position index of the state data within a data file in a persistent storage medium.

[0123] In one example, the tree structure as a whole can be as follows: Figure 10 As shown, this is also consistent with Figure 5 There are some similarities. In particular, if the leaf nodes in memory contain state data, then... Figure 5 As shown, for example Figure 5 The leaf node A11 in the data structure contains state data in memory, i.e., Zhang San_A=20. If the leaf node in memory does not contain state data, then the index storing the state data in the data file can be used.

[0124] In this application, separating the actual data and the index helps improve the system's flexibility and performance. The basic concepts involved include data files and index files. The data file stores the actual content; the index file stores an index pointing to the location of the data file. Its working principle is as follows: data content is written to the data file, recording the data's position within the file (such as filename, offset, and length); then, an entry is created in the index file, containing a key (a unique identifier used for lookup) pointing to a reference in the data file (filename, offset, etc.). Thus, during data retrieval, the data location can be quickly located through the index file, and the actual content can be read from the data file based on the location information. The advantages of this approach are: ① Flexibility: data and indexes can be managed and optimized independently; ② Performance: indexes are typically small and can be fully loaded into memory, speeding up queries; ③ Space efficiency: avoiding the storage of large amounts of duplicate data in the index; ④ Update efficiency: when modifying data, only the location information in the index needs to be updated.

[0125] For example Figure 10 In this context, the location index is used to represent this position. Continuing with the A11 node as an example, if there is no state data in memory, the location field can be used to store the position index of the state data within the data file. This position index might be, for example, <2,750,210>. This <2,750,210> indicates that the state data is located in "file 2" within the data file, starting at the 750th KB position of "file 2" and having a length of 210 KB. Figure 10 As shown in the data file in the lower left corner, assuming each file is 1024KB in size and the logical address range of the index is 0KB to 1023KB, the status data of A11 actually occupies the range from 750KB to 959KB in file 2.

[0126] like Figure 9 As shown, this embodiment includes:

[0127] S910: The storage module of the blockchain node receives the instruction to look up the state key and searches for the leaf node corresponding to the state key in the tree structure in memory.

[0128] As mentioned above Figure 6 As shown, the execution module can generate execution results by executing ordinary transfer transactions or transactions involving contracts, and then send them to the storage module. Specifically, for example, during contract execution, it may be necessary to read the value of a state variable. The execution module can first check if the value of the state variable exists in its own memory; if not, it sends a read command to the storage module. This read command can include the address of the state to be read, i.e., the state's key value.

[0129] The storage module includes a tree-building module. This module constructs a tree structure representing the world state in memory. In the case of a cold start of a blockchain node (i.e., before the world state tree structure exists in memory), the individual tree nodes can be loaded from disk and organized into a tree in memory. This process also involves loading leaf nodes. An example is given where the tree-building module contains an incomplete tree structure; the cold start loading process is similar. Since memory capacity is generally limited, the LRU (Least Recently Used) algorithm is typically used to evict tree nodes that haven't been accessed for a long time. Therefore, leaf nodes in the tree structure constructed in memory by the tree-building module may be subject to eviction. For the leaf nodes of the world state tree, some may be in memory while others may not. Furthermore, similar eviction mechanisms can be used for the content within tree nodes, such as the state data in leaf nodes; alternatively, state data may not be maintained in memory.

[0130] If the tree construction module has a corresponding leaf node in memory for the desired state key, it can be found directly in memory. For this case, please refer to... Figure 5 The key is directly located in memory, and the value is read from it. Then, the state data can be read from the value. If the tree construction module does not have the leaf node corresponding to the state key in memory, or if the leaf node exists but does not contain the state data being searched for, a further search is needed in the state database module. For cases where the state database uses an LSM tree, as mentioned earlier, a search can first be performed in the MemTable; if not found, a search can be performed in the files on disk.

[0131] S920: Obtain the position index contained in the leaf node corresponding to the tree node key, where the position index points to the position within the data file in the persistent storage medium.

[0132] Even if the tree construction module has the leaf node to be searched in memory, but it does not contain state data, a further search is needed from the state database module. As mentioned earlier, if there is no state data in memory, the location field can be used, the content of which is, for example... Figure 10 In the leaf node A11, the location is <2, 750, 210>. This <2, 750, 210> is the location index, indicating that the status data is located in file 2 of the data file, starting at position 750KB and with a length of 210KB. Figure 10 As shown in the data file in the lower left corner, assuming each file is 1024MB in size and the logical address range of the index is 0KB to 1023KB, the status data of A11 actually occupies the range from 750KB to 959KB in file 2.

[0133] If the leaf node to be searched for is not in the memory of the tree construction module, it needs to be searched for and loaded from the state database module. Searching for and loading the leaf node from the state database module specifically includes loading the index file and data file of the leaf node. Assume... Figure 10 The underlying database stores the key-value pairs (KV) of all intermediate nodes in the tree structure, as shown in the table below:

[0134] Key Value H(A9) Prev Hash: , Nonce: ,Timestamp: , Block Num: ,State Root: H(A8), Transaction Root: ,Receipt Root: ,… H(A8) prefix:0, shared nibble(s): a7, next node: H(A7) H(A7) 0: ,1: H(A ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ 0: ,,2: ,,3: H(A11),4: ,,5: ,,6: ,,7: H(A12),8: ,,9: ,,a: ,,b: ,,c: ,,d: ,,e: ,,f: H(A13), value: H(A11) prefix:2, Key-end:35b2e4, location:(2,750,210) H(A12) prefix:2, Key-end:c25988, location:(3,350,210) H(A13) prefix:1, shared nibble(s):a, next node: H(A14) H(A14) 0: ,,1: ,,2: ,,3: ,,4: ,,5: ,,6: H(A15),7:,,8: ,,9: H(A16),a: ,,b: ,,c: ,,d: ,,e: ,,f:, value: H(A15) prefix:2, Key-end: be33, location:(5,760,140) H(A16) prefix:2, Key-end: 9365, location:(5,170,210)

[0135] Table 2. Key-value pairs of tree nodes actually stored in the database.

[0136] In Table 2 above, similar to Table 1, H() represents hash calculation. This anchors the hash value of the next tree node to the previous tree node. Through this layer-by-layer hashing, the root hash of the entire state trie tree is obtained and locked to the state root field in the block header. Assume the key-value pairs in this table are stored in the underlying state database module, stored on disk, and using a similar LSM structure. Thus, similar to the above, after receiving a read command, the storage module can find the root node of the state tree in the tree construction module. It then matches the state key value to be searched against the root node's shared nibble(s) field (for Extension Nodes) or slot (for Branch Nodes) from the beginning. It reads the hash of the next level tree node from the matching position, and then first searches for the hash in the memory of the tree construction module. If it is not found there, it searches in the memory of the state database module. If it is still not found there, it searches in the state database module's file. Specifically, the search can begin within the SST at Level 0. If the hash value is not found there, the search continues within an SST at Level 1, and so on, down to the next SST at each lower level, until the next Internal Node pointed to by the hash value is found. After unpacking this Internal Node, the remaining fields of the key value of the state address to be read are matched from front to back. If a match is found, the hash value is read from the match point, and the search jumps to the next level tree node pointed to by that hash value. This process is repeated, unpacking Internal Nodes level by level and matching the remaining fields of the key value of the state address to be read from front to back. The hash value at the match point serves as the basis for the next search of intermediate or leaf nodes, until a Leaf node is matched, from which the state value is read. During this process, some key-value pairs of tree nodes at each level may not exist in the memory of the tree building module but are located in the state database module. Therefore, it may be necessary to read them from the state database module. The key can be searched first in the MemTable or Immutable MemTable of the state database module. If it does not exist, further searching of the various levels of SST files on disk is required. For Internal Nodes and Leaf Nodes existing on disk, they need to be loaded into memory and decoded (deserialized) to obtain their contents. Specifically, for example, the search can begin by sequentially searching the SST files of level 0. If each SST in level 0 is sorted, a binary search can be performed within each SST based on the hash value of the intermediate / leaf node. Once found, the key (v) is loaded into memory and decoded and matched.If the value is not found in the SST at Level 0, a binary search is performed within Level 1 based on the hash value of the intermediate / leaf node. If the value is still not found, a binary search is performed within Level 2. If the value is found, the corresponding value (v) is loaded into memory and decoded. This process continues until a leaf node of the tree structure is matched and its value is read. During the searches at Level 1, Level 2, and lower levels, since the overall SST at these levels is sorted, a binary search can generally be performed within that level.

[0137] In this way, the key-value pairs of the found leaf nodes can be loaded into memory. For example, in A11, the content of the leaf node value, prefix:2, key-end:35b2e4, location: (2,750,210), is loaded into memory. Here, <2,750,210> is the position index of the value content in the file.

[0138] S930: Load the value of the data file location in the persistent storage medium pointed to by the location index into memory and read the status data therein.

[0139] Taking A11 as an example, the position index <2,750,210> points to the location within the data file in the persistent storage medium. Thus, the value at the location in the data file pointed to by the position index <2,750,210> can be loaded into memory and its status data read. Specifically, the 210KB data starting from the 750KB mark in file 2 of the data file can be loaded into memory, and its status data, "Zhang San_A=20", can be read.

[0140] The location index allows direct location within the data file, enabling the loading of the data file and the reading of status data from it.

[0141] If the tree-building module has the leaf node to be searched in memory, but it does not contain state data, it can directly read the data from the corresponding data file based on the location within the leaf node in memory. This avoids storing the key-value pairs of the leaf node together in the persistent storage SST file, which would require multiple binary search operations within the SST.

[0142] If the leaf node to be searched is not in the memory of the tree construction module, and it is necessary to search for and load the leaf node from the state database module, it is actually necessary to read a certain amount of content from the disk into memory before searching. In the implementation corresponding to Table 1, the key-value pairs of the tree node are stored together on disk, and the value of the leaf node includes state data. For example, in Table 1, H(11) corresponds to Zhang San_A=20, H(12) corresponds to Li Si_B=20, H(15) corresponds to storedData=s, and H(16) corresponds to Wang Wu_A=20. Generally speaking, the state data occupies a large space, about 90% or more of the total space of a key-value pair. In the implementation corresponding to Table 2, the index and data are separated. The index stores the location of the data file containing the state data, but not the state data itself. For example, in Table 2, H(11) corresponds to location (2,750,210), H(12) corresponds to (3,350,210), H(15) corresponds to (5,760,140), and H(16) corresponds to location (5,170,210). The actual state is stored only at the corresponding location in the data file. Figure 10 The data files and state data are shown in Table 2. When searching for leaf nodes, only the index files can be searched. This allows more index files to be loaded into memory within a unit of space for searching. Memory search efficiency is significantly higher than disk search efficiency; generally, the content to be searched is loaded into memory before the search. The implementation in Table 2, because it can load more indexes within a unit of memory space, can find leaf nodes faster than the implementation in Table 1. In the implementation in Table 1, for example, if a batch of key-value pairs is read into memory but no leaf node is found, another batch of key-value pairs needs to be read into memory for another search. Furthermore, because it includes state content that occupies a large amount of space, the number of key-value pairs within a unit of memory space is relatively small. Therefore, the number of reads from disk is generally more frequent, and disk read speed is much slower than memory read speed. Thus, the search efficiency of the implementation in Table 1 is lower.

[0143] The above combination Figure 10 Explanation Figure 9 The specific process of the method implementation. Figure 10 The tree structure remains a two-level MPT tree, with each level containing two types of tree nodes: Extension Nodes and Branch Nodes. In one variation, Branch Nodes can be used as both intermediate and root nodes, for example... Figure 11 As shown in the diagram. Thus, the sequential combination of slots in the branch nodes passed through from the root node to the leaf node constitutes part of the state key. The hash value of the next-level node can be stored in the slot of the previous-level node. Figure 11 In this case, a two-level tree structure can still be used. Leaf nodes in the upper-level tree can store account states (including the states of external accounts and contract accounts), while leaf nodes in the lower-level tree store contract states. Position indexes can be used in the leaf nodes storing external account states, contract account states, or contract states. For example, the leaf nodes of the upper-level tree could include the account states in the following four rows: H(M1), H(M2), H(M3), and H(M4) as shown in the table below:

[0144] Key Value H(A0) Prev Hash: ,, Nonce: ,,Timestamp: ,, Block Num: ,,State Root: H(B0), Transaction Root: ,,Receipt Root: ,,… H(B0) 0: ,,1: ,,2: ,,3: ,,4: ,,5: H(C5),6: ,,7: ,,8: ,,9: ,,a: ,,b: ,,c: ,,d: H(C13),e: ,,f: H(C5) 0: ,,1:H(C5D1),2: ,,3: ,,4: ,,5: ,,6: ,,7: ,,8: ,,9: H(C5D9),a: ,,b: ,,c: ,,d: ,,e: H(C5D14),f: H(C13) 0: ,,1: ,,2: H(C13D2),3: ,,4: ,,5: ,,6: ,,7: ,,8: ,,9: ,,a: H(C13D10),b: ,,c: ,,d: ,,e: ,,f: ... ... H(M1) location:(2,100,180) H(M2) location:(5,760,140) H(M3) location:(2,750,210) H(M4) location:(3,350,210) H(N0) 0: ,,1: ,,2:H(P2),3: ,,4: ,,5: ,,6: ,,7: ,,8: ,,9: ,,a:,,b: ,,c: ,,d: ,,e: ,,f:H(P15) H(P2) 0:H(P2Q0),1: ,2: ,3: ,4: H(P2Q4),5: ,6: ,7: ,8: H(P2Q8),9: ,a:,b: ,c: ,d: ,e: ,f:H(P2Q15) H(P15) 0: ,1: ,2: ,3:H(P15Q3),4: ,5: ,6: ,7: ,8: ,9:H(P15Q9),a:,b: ,c: ,d: ,e: ,f: H(Z1) 0:H(P2Q0),1: ,2: ,3: ,4: H(P2Q4),5: ,6: ,7: ,8: H(P2Q8),9: ,a:,b: ,c: ,d: ,e: ,f:H(P2Q15) ... ... H(Z1) location: (5,170,210) H(Z2) location: (3,805,150) H(Z3) location: (1,400,128) H(Z4) location: (5,600,100)

[0145] Table 3. Key-value pairs of tree nodes actually stored in the database.

[0146] The location index allows direct access to the data file, enabling the loading of the data file and the reading of state data. Furthermore, the leaf nodes of the next-level tree contain the contract states as shown in rows H(Z1), H(Z2), H(Z3), and H(Z4) in the table above.

[0147] Data files, for example Figure 11 As shown, the contents of the data file are as follows:

[0148] M1: Nonce: n1, balance: 45.0 ETH

[0149] M2: Nonce: n2, balance: 1.00WEI

[0150] M3: Nonce: n3, balance: 1.1 ETH

[0151] M4:Nonce:n1,balance:0.12ETH,codehash:c1,storage:s1

[0152] Z1: Zhang San_A=20

[0153] Z2: Li Si_B=50

[0154] Z3: Wang Wu_A=35

[0155] Z4: storedData=s

[0156] Regardless of whether it's the parent or child level of the tree, the location in the data file can be quickly located through the `location` property in the leaf node. This avoids the need for multiple binary search operations in the SST file based on the leaf node's key (hash value of the content) when storing the key-value pairs of the leaf nodes together. Figure 11 In the example, according to Figure 9 The blockchain state data is read in the manner described above. The location index directly pinpoints the position in the data file, allowing the content at the corresponding location in the data file to be loaded directly into memory. This avoids the read amplification problem caused by reading and loading large amounts of files into memory across multiple levels of the SST. Similarly, A4, as the leaf node of the parent tree, can be... Figure 10 Stored as shown, or as... Figure 11 Stored in the manner described in the text.

[0157] External accounts and contract accounts typically use fixed-length strings as keys, while contract status keys can also be strings of the same length. Specifically, for example, the key for an external account or contract account could be an account address, while the key for the contract status could be a string of the same length. Another example is that the key for an external account or contract account could be the account address hashed using a specific algorithm, such as SHA3; while the key for the contract status could be SHA3(contract name + the location of the status variable declaration). These external accounts, contract accounts, and contract statuses are all strings of the same length and format, collectively referred to as the status key. For example, the length of the status key might be 4 bytes, or 32 bits. Thus, assuming the root node (B0) and intermediate nodes (..., C5, ..., C13, ..., C5D1, ..., C5D9, ..., C5D14, ..., C13D2, ..., C13D10, ...) are each 16-ary trees, then on the one hand, each slot in the intermediate node (such as slots 0, 1, 2, ..., d, e, f in B0, a total of 16 slots) can be filled with the hash value of the next tree node; on the other hand, the position of this slot in the root / intermediate node can represent a 4-bit key. 4 bits constitute a half-byte, so the root node and intermediate nodes, a total of 8 levels, can store 32 bits, totaling 8 bytes, which is the entire state key. The 32 bits of the state key can be stored from the top-level intermediate node to the bottom-level intermediate node and down to the leaf node, with each level storing one half-byte of the key. Thus, in the case where the intermediate nodes are fixed and expanded, the leaf node can store the last 4 bits of the key. In the case of fixed and expanded intermediate nodes... Figure 11 From C* to C13D*, all the way down to the lowest level M*, there are a total of 8 levels. In another case, a compressed prefix and / or infix and / or suffix method can be used, in which case one or more leaf nodes plus the intermediate nodes above them can be less than 8 levels.

[0158] Alternatively, a single-layer tree structure can be used to store account and contract states, for example... Figure 12 As shown in the diagram. Because the key of the contract state is a hash value, and due to the discrete nature of hash algorithms, the state keys of different contract states may be paths from the root node to different leaf nodes in this tree structure. Thus, different states of the same contract may have values ​​residing in different leaf nodes at the bottom layer of the tree structure, rather than clustered under their respective contract accounts. In fact, using a single-layer tree structure, both account states and contract states are distributed across the bottom-layer leaf nodes.

[0159] In addition, Figure 12 On the basis of, such as Figure 13 In this context, prefix and / or infix compression can be performed. For example, in the case of infix compression, if the key of tree node M1 is 0x52d1479e (0x represents each digit in hexadecimal), and the key of tree node Z1 is 0x52d9ab36, then M1 and Z1 share a common infix 2d. Therefore, in tree node C5, besides the 1 and 9 separated by the hexadecimal tree, C5 can also contain compressed infix 2d, such as... Figure 13 The `shared nibbles` field is shown in the example. In the case of suffix compression, for example using key-end representation, the key-end of tree node M1 would be 479e, and the key-end of tree node Z1 would be 36. Using prefix and / or infix compression can reduce the number of tree levels.

[0160] Regardless of compression, to find a state key, one can start from the root node of the tree structure and match the path of the state key segment by segment until the leaf node of the tree structure corresponding to the state key is found. In one approach, the root node and intermediate nodes are stored in key-value format, where the key is the hash value of the value, similar to the structure in Table 3. In this way, one can start from the upper-level tree node, sequentially match the hash of the path of the state key, and use the hash to find the lower-level tree node until the leaf node of the tree structure corresponding to the state key is found.

[0161] Furthermore, the key in the actual tree node key-value pair stored in the database may not be the hash value of the value, but rather a partial value along the state key path, such as the partial key value from the root node to the current tree node (in combination with...). Figure 12 (without compressed prefix / infix, as shown in Table 4), or the value of a partial key after the previous tree node (combined with...) Figure 13 (There are compressed prefixes / infixes, as shown in Table 5).

[0162] Key Value H(A0), Prev Hash: , Nonce: , Timestamp: , BlockNum: , State Root: H(B0), Transaction Root: , Receipt Root: ,… 0x H(B0)0: ,1: ,2: ,3: ,4: ,5: H(C5),6: ,7: ,8: ,9: ,a: ,b: ,c: ,d: H(C13),e: ,f: 0x5 H(C5)0: ,1:H(C5D1),2: ,3: ,4: ,5: ,6: ,7: ,8: ,9: H(C5D9),a: ,b: ,c: ,d: ,e: H(C5D14),f: 0xd H(C13)0: ,1: ,2: H(C13D2),3: ,4: ,5: ,6: ,7: ,8:,9: ,a: H(C13D10),b: ,c: ,d: ,e: ,f: 0x1 H(C5D1)0: ,1: ,2: ,3: ,4: ,5: ,6: ,7: ,8: ,9: ,a:,b: ,c: ,d: ,e: ,f: 0x9 H(C5D9)0: ,1: ,2:,3: ,4: ,5: ,6: ,7: ,8: ,9: ,a:,b: ,c: ,d: ,e: ,f: 0xe H(C5D14)0: ,1: ,2:,3: ,4: ,5: ,6: ,7: ,8: ,9: ,a: ,b: ,c: ,d: ,e: ,f: 0x2 H(C13D2)0: ,1: ,2:,3: ,4: ,5: ,6: ,7: ,8: ,9: ,a: ,b: ,c: ,d: ,e: ,f: 0xa H(C13D10)0: ,1: ,2:,3: ,4: ,5: ,6: ,7: ,8: ,9: ,a: ,b: ,c: ,d: ,e: ,f: ... ... 0xe H(M1) location: (2, 100, 180) 0x6 H(Z1) location: (5, 170, 210) ... ...

[0163] Table 4. Tree node key-value pairs actually stored in the database

[0164] According to Table 4, combined with Figure 12 For example, if the state key is 0x59...36 (leaf node Z1), starting from the root node of the tree structure, we can match the first digit (5) of the state key to the tree node in the database with the key 0x5 (the h(C5) in the value of the tree node with key 0x5 can be used to verify with the hash value in slot 5 of the root node; if they are the same, it means that the tree node with 0x5 is a child node in slot 5 of the 0x tree node); then, we can match the second digit (9) of the state key to the tree node in the database with the key 0x9 (the h(C5D9) in the value of the tree node with key 0x9 can be used to verify with the hash value in slot 9 of the parent node; if they are the same, it means that the tree node with 0x9 is a child node of the 0x5 tree node); and so on. Finally, the last digit 6 of the status key can be used to match the tree node in the database with the key 0x6 (the h(Z1) in the value of the tree node with the key 0x6 can be used to verify with the hash value on slot 6 in the parent node; if they are the same, it means that the tree node with the key 0x6 is a child node of the parent node).

[0165] Key Value H(A0), Prev Hash: , Nonce: , Timestamp: , Block Num: , State Root: H(B0), Transaction Root: , Receipt Root: ,… 0x H(B0)0: ,1: ,2: ,3: ,4: ,5: H(C5) ,6: ,7: ,8: ,9: ,a: ,b: ,c: ,d: H(C13) ,e: ,f: 0x52d H(C5)0: ,1:H(C5D1),2: ,3: ,4: ,5: ,6: ,7: ,8: ,9: H(C5D9),a: ,b: ,c: ,d: ,e: H(C5D14),f: 0xd H(C13)0: ,1: ,2: H(C13D2),3: ,4: ,5: ,6: ,7: ,8: ,9: ,a: H(C13D10),b: ,c: ,d: ,e: ,f: 0x52d1 H(C5D1)0: ,1: ,2: ,3: ,4: ,5: ,6: ,7: ,8: ,9: ,a:,b: ,c: ,d: ,e: ,f: 0x52d9 H(C5D9)0: ,1: ,2:,3: ,4: ,5: ,6: ,7: ,8: ,9: ,a: ,b: ,c: ,d: ,e: ,f: 0x52de H(C5D14)0: ,1: ,2:,3: ,4: ,5: ,6: ,7: ,8: ,9: ,a: ,b: ,c: ,d: ,e: ,f: 0xd2 H(C13D2)0: ,1: ,2:,3: ,4: ,5: ,6: ,7: ,8: ,9: ,a: ,b: ,c: ,d: ,e: ,f: 0xda H(C13D10)0: ,1: ,2:,3: ,4: ,5: ,6: ,7: ,8: ,9: ,a: ,b: ,c: ,d: ,e: ,f: ... ... 0x52d1 key - end: 479e, H(M1), location: (2, 100, 180) 0x52d9ab key-end:36, H(Z1), location: (5,170,210) ... ...

[0166] Table 5. Tree node key-value pairs actually stored in the database

[0167] According to Table 5, for example, if the search query for the state key is 0x52d9...36 (leaf node Z1), starting from the root node of the tree structure, the system can match the first digit (5) of the state key in the database. If no matching key is found, or if the hash value in the value of the tree node matching the key is inconsistent with h(C5) in the root node, the system will again match the first two digits (52) of the state key in the database. This process is repeated until a match is found. When the system matches the first three digits (52d) of the state key in the database and finds a tree node with the key 0x52d, and the hash value H(C5) in its value is the same as the hash value in slot 5 of the root node, then a match has been found. Then, the system can match the first four characters (52d9) of the status key in the database. If no matching key is found, or if the hash value of the value in the tree node containing the matched key is inconsistent with h(C5) in the root node, the system can re-match the first two characters (52) of the status key in the database. If a match is found, and the H(C5D9) in the value of the matched tree node is the same as the hash value in slot 9 of the parent node, then a match has been found. Further, the system matches the first five characters (1-5) of the status key in the database, the first six characters (1-6) of the status key in the database, and so on, until a leaf node is matched.

[0168] In another implementation, the complete state key or a corresponding complete state key can be stored in the leaf nodes. For example, storing the complete state key in the leaf nodes... Figure 14 As shown, the key-full field of a leaf node can store the complete key of the corresponding state. The key-value pair of a leaf node stored in the database contains the complete key of the corresponding state. Thus, when searching for a state key, it's possible to directly match that key with the key of a leaf node in the database, without needing to match the keys of intermediate nodes. Clearly, this search method is extremely efficient for query operations. In fact, the above... Figure 10-13 In this context, the complete state key can also be used as the key for the leaf node.

[0169] The above Figure 9-14 In this embodiment, the leaf node stores a location index, which allows for quick location of the leaf node's value within the data file after the leaf node is found. This allows the content at the corresponding location in the data file to be directly loaded into memory, avoiding the read amplification problem caused by reading and loading large amounts of files from multiple levels of the SST. It also avoids the need for multiple binary search operations within the SST based on the leaf node's key (the hash value of the value) when storing both the leaf node's key and value in the persistent SST file. Furthermore, similarly, if the leaf node to be searched is not present in the memory of the tree-building module, the above embodiment can search only the index file. This allows more index files to be loaded into memory within a unit of space for searching, thus finding the leaf node faster.

[0170] As mentioned earlier, the state root in the block header stores the hash value of the root of the lower-level MPT tree it is anchored to. This hash value is actually obtained by calculating the hash value layer by layer upwards from the leaf nodes, as described above. Generally, the storage module of a blockchain node constructs the world state of a tree structure in memory through the tree construction module. Specifically, in addition to the aforementioned... Figures 12-14 In addition to the leaf nodes, the nodes also include intermediate nodes and the root node, as shown in Tables 2 to 5 above.

[0171] Furthermore, the chain-like data structure of blockchain is implemented by anchoring the hash of the subsequent block to the PrevHash of the previous block, such as... Figure 3 , 4 As shown, the blockchain contains blocks identified by different block numbers. These block numbers are also called versions. Under different versions of blocks, the corresponding tree structure may change.

[0172] Those skilled in the art know that the essence of a blockchain is a chain-like structure composed of a series of data blocks (blocks) linked by hashes. Each block has a corresponding world state, but each block does not necessarily contain the complete world state; rather, it usually contains a reference to a previous world state. This will be explained below:

[0173] In Ethereum's block structure, when the value in a key-value pair changes, the content of the leaf node in its corresponding MPT tree changes. Correspondingly, the hash values ​​stored in a series of intermediate nodes above that leaf node, as well as the root node, will also change. In the structure shown in Table 1, the changed leaf nodes, intermediate nodes, and root node will be appended to the end of Table 1. Meanwhile, it's possible that many state variables in a contract's storage may not have changed their values.

[0174] like Figure 15 The Ethereum block structure diagram shown is... Figure 15 and Figure 3 The difference lies in the addition of references to state variables that remained unchanged in block N by the root and intermediate nodes of the two-level Merkle tree under the State Root in block N+1. For example, in the contract storage of a contract, if the value of the same state variable changes from 29 in block N to 45 in block N+1, assuming other state variables remain unchanged, then in block N+1, besides the leaf node storing the changed value of 45 and its associated intermediate nodes, all other unchanged leaf and intermediate nodes directly reference the same leaf and intermediate nodes from block N. This is illustrated with two adjacent blocks, N and N+1. It can be understood that for the block structure of multiple consecutive blocks on the blockchain, leaf and intermediate nodes in block N+1 that have not changed relative to previous blocks all reference the same leaf and intermediate nodes that were last updated to that value. The last leaf node and intermediate node updated to this value, for example, the same leaf node and related intermediate node updated to this value in block N-1, the same leaf node and related intermediate node updated to this value in block 5, and so on. These different blocks can also be called different versions, and the block number can be the version number. This referencing is implemented by the upper-level node recording the hash value of the lower-level node. The advantage of this is obvious: it avoids repeatedly storing unchanged leaf nodes and intermediate nodes in the underlying database.

[0175] To illustrate this simply, let's consider a change in the state of the same contract in version N+1 compared to version N. For example, if the content of a tree node changes, its hash will change accordingly. MPT uses the hash as an index in the database, ensuring that each value has a unique record in the database. MPT associates parent and child nodes based on their hashes. Therefore, whenever the content of a node changes, only the hash index value changes for the parent node; the parent node's content also changes, creating a new, higher-level parent node, and this effect is recursively propagated to the root node. Ultimately, each change creates a new path from the modified node to the root node, while the old node can still be accessed via the old path from the old root node.

[0176] like Figure 15 As shown, when the content of a node in the MPT changes from 29 in version N to 45 in version N+1, assuming that the other states in the contract state have not changed between the two versions, the changed 45 corresponds to the creation of a new path to the contract's storage root in the world state of version N+1. Furthermore, the other unchanged leaf nodes and intermediate nodes reuse the leaf nodes and / or intermediate nodes from the previous version (i.e., the version with block number N) using hash pointers, thereby constructing a new MPT tree for the contract's storage in version N+1, while still retaining its old paths. Figure 18 In the same contract storage, leaf nodes / intermediate nodes whose values ​​in version N+1 have not changed compared to version N include V, U, T, S, etc. Therefore, in the storage of this contract in version N+1, besides creating a new path from 45 to the Storage root, the Storage root of version N+1 is indexed by hash to V, U, T, and S in version N, but does not include the leaf node with a value of 29 and its related intermediate nodes. Assuming the contract is deployed in version N, the CodeHash works similarly. The contract code corresponding to the CodeHash exists in the StateDB corresponding to version N, and the CodeHash of version N+1 also points to the contract code in version N.

[0177] Besides contract storage, similar methods can be used for storing other accounts (including external accounts and contract accounts), such as... Figure 15 In version N+1, for accounts that have not changed in version N, the State Root in the N+1 block header points to the storage of external accounts or contract accounts such as L, M, N, P, Q, and R in version N. Only the leaf nodes and related intermediate nodes that have changed are stored in the account storage corresponding to version N+1. These details will not be elaborated further.

[0178] The current state contains many states that were likely updated in a previous block and have remained unchanged until now. This is similar to Ethereum, and is known as the current state, stored in the currentDB. The currentDB stores the latest "current state" data, such as the latest account state, contract code, and contract storage. Moreover, the data in the currentDB can be continuously modified as the number of blocks grows.

[0179] As mentioned above Figure 3 and above Figure 15 Building a global MPT tree for all states for each block would be highly redundant. Using leaf nodes and intermediate nodes from previous blocks that were last updated to the same value is a more efficient data storage method. Furthermore, the state changes in each block are likely part of the global state. This is similar to Ethereum, where the state is also called history state and stored in historyDB. historyDB stores historical state data, providing a complete historical view of the entire chain.

[0180] This application provides a method for constructing a tree-based world state, including:

[0181] S170: Receive status key-value.

[0182] S172: According to the tree structure construction rules, generate leaf nodes of the tree structure corresponding to the state key-value; calculate the hash value of the leaf node according to the content in the leaf node, and generate or update the upper-level tree nodes according to the hash value of the leaf node and the state key, until the root node of the tree.

[0183] The leaf nodes can be in the form of the aforementioned data file or the aforementioned KVDB. If the aforementioned data file format is used, the leaf node can generate a value including the position index of the state value within the data file in the persistent storage medium and the hash value of the state value content.

[0184] S174: Generate corresponding memory pages for the generated / updated tree nodes according to the divided logical page structure. The memory pages are used to represent the contents of all tree nodes in the logical pages.

[0185] In this application, the entire Merkle tree structure can be divided into multiple LogicalPages. This can be achieved by aggregating several adjacent tree nodes into a single LogicalPage based on the node relationships within the tree structure, such as a 2-level, 16-branch trie with 256 child nodes. There are multiple levels of LogicalPages from the root node to the leaf node of the Merkle tree, with parent-child and sibling relationships between them, thus forming a complete Merkle tree. In this way, the tree structure can be divided into multiple LogicalPages, each containing at least one tree node. Different LogicalPages contain different tree nodes, and each LogicalPage maintains the latest version of the corresponding tree node's content.

[0186] Within each LogicalPage, a MemoryPage can be maintained to represent the content of all tree nodes corresponding to the current latest version of the LogicalPage. Further, the content of the tree nodes maintained by the LogicalPage can be used to generate base pages and incremental pages based on continuous version updates and generation / modification behavior. Specifically, BasePage and DeltaPage are generated according to generation / modification behavior. For example, for continuous state changes, such as version N including state variables a=5, b=8, c=3, a=5, b=8, c=3 can be used as the content of the base page BasePage. For a=6 in version N+1 and a=8 in version N+2, assuming b and c remain unchanged, a=6 in version N+1 and a=8 in version N+2 can be used as a DeltaPage based on this BasePage, such as DeltaPage1. Cases where b and c remain unchanged are not included in DeltaPage1. If a=11 in version N+3 and a=15 in version N+4, then a=11 in version N+3 and a=15 in version N+4 can be used as DeltaPages based on this BasePage, such as DeltaPage2. Similarly, assuming b and c remain unchanged, b and c are not included in DeltaPage2, and so on. BasePage and DeltaPage can serve as the smallest unit of the tree's memory structure. Furthermore, BasePage can serve as the smallest unit of the tree's disk persistence. Based on this, DeltaPage can also serve as the smallest unit of the tree's disk persistence.

[0187] It's important to note that the BasePage here refers to a checkpoint of the entire LogicalPage content. It can contain the full content of the LogicalPage at that particular moment, such as all included tree node information. A checkpoint is generally a snapshot of a specific state saved in a computer system, allowing recovery and continuation of execution in the event of system failure or malfunction. In many cases, checkpoints are used for long-running computational tasks, safety-critical systems, distributed systems, and database systems.

[0188] For BasePage, the state can be modified and a BasePage can be generated once every predetermined number of times (e.g., m times). Figure 16 As shown in the red box at the bottom right of the middle, `basepage2`. In the previous example, in version N, the state variable `a` is 5. This `a`=5 can be used as the content of the base page `BasePage1`. In version N+1, `a` is 6, and in version N+2, `a` is 8. Therefore, `a`=6 in version N+1 and `a`=8 in version N+2 are used as `DeltaPage1` based on this `BasePage`. In version N+3, `a` is 11, and in version N+4, `a` is 15. Therefore, `a`=11 in version N+3 and `a`=15 in version N+4 are used as `DeltaPage2` based on this `BasePage`. In version N+5, `a` is 20. Assuming the predetermined number of modifications reaches 5, the values ​​`a`=20, `b`=8, and `c`=3 in version N+5 can be used as the content of this `BasePage2`.

[0189] Similarly, a DeltaPage describes several version modifications of a LogicalPage, aggregating multiple modifications into a set. For example, a DeltaPage is generated every M modifications, and a new DeltaPage is created to collect subsequent version modification operations. In the previous example, if a=6 in version N+1 and a=8 in version N+2, then a=6 in version N+1 and a=8 in version N+2 are used as DeltaPage1 based on this BasePage. If a=11 in version N+3 and a=15 in version N+4, then a=11 in version N+3 and a=15 in version N+4 are used as DeltaPage2 based on this BasePage. It can be seen that each DeltaPage is configured to create an incremental page for two version modification operations.

[0190] For each modification to BasePage and DeltaPage, corresponding dirty data is generated in memory. When the memory usage of BasePage and DeltaPage reaches a predetermined level, they can be batch-persisted to disk, thus avoiding the need to persist all dirty data with every modification, which continuously consumes memory and CPU resources. The memory generation and disk persistence of BasePage and DeltaPage can be performed in the background.

[0191] When the storage module persists the world state of the tree structure built in memory through logical pages, it can cache the state data based on its hot / cold characteristics, using logical pages as the granularity and a predetermined strategy, such as the Least Recently Used (LRU) strategy. In this way, if a MemoryPage is evicted, the corresponding BasePage and DeltaPage are read, and the MemoryPage is replayed.

[0192] The scheme described in this application proposes a method for partitioning the world state of a tree structure according to Pages. The tree structure is divided into LogicalPages, each of which manages MemoryPage, BasePage, and DeltaPage. Each state tree modification is optimized into multiple version modifications at the LogicalPage level, reducing overall write amplification. The current version can be directly obtained from the memory page, while historical versions can be obtained by replaying the BasePage and several associated DeltaPages. The entire MemoryPage is cached in memory, without affecting contract execution performance.

[0193] In the above scheme, a LogicalPage internally manages MemoryPage / BasePage / DeltaPage. As mentioned earlier, it can be aggregated into a LogicalPage by following the node association relationships in a tree structure, such as aggregating 256 child nodes (2 levels, 16 branches) of a trie into a LogicalPage. There are multiple levels of LogicalPages from the root node to the leaf node of the Merkle tree, with parent-child and sibling relationships between them, thus forming a complete Merkle tree. In this way, the tree structure can be divided into multiple logical pages, each containing at least one tree node. Different logical pages contain different tree nodes, and each logical page maintains the latest version of the corresponding tree node's content.

[0194] Therefore, when constructing a tree-based world state, in addition to generating leaf nodes of the tree based on the state key-value pair, changes also occur from the generated leaf nodes to the intermediate nodes to the root node, as described in S172 above regarding the hash value. Furthermore, the state key needs to be designed, especially for the LogicalPage and its corresponding MemoryPage / BasePage / DeltaPage.

[0195] Therefore, this application also proposes the following methods for constructing world states based on tree structures, including:

[0196] S180: Receive status key-value.

[0197] S182: According to the tree structure construction rules, generate leaf nodes of the tree structure corresponding to the state key-value; calculate the hash value of the leaf node according to the content in the leaf node, and generate or update the upper-level tree nodes according to the hash value of the leaf node and the state key, until the root node of the tree.

[0198] The leaf nodes can be in the form of the aforementioned data file or the aforementioned KVDB. If the aforementioned data file format is used, the leaf node can generate a value including the position index of the state value within the data file in the persistent storage medium and the hash value of the state value content.

[0199] For details regarding the process of S182, please refer to the aforementioned content. Here it is briefly summarized again as follows:

[0200] Similar to Ethereum, when the storage module receives a key-value pair (kv) request to write state, it first hashes the key (k) (e.g., using Keccak-256). Alternatively, the state key in S182 could be the same as the state key received in S180, meaning it could be used without hashing. Next, this key is used to perform a lookup in the MPT. This lookup process starts from the root node of the MPT and traverses and matches downwards along the tree path in lexicographical order. During this process, the key is typically compared bit-by-bit (or nibble, typically a single hexadecimal digit) with the path stored in the node. During traversal and matching, three types of nodes may be encountered: branch nodes (if the path forks at some point), extension nodes (if there is a shared prefix), and leaf nodes (which store the final value). Branch nodes are used to branch in the tree, extension nodes are used to optimize storage (through path compression), and leaf nodes store the actual value. If a complete lexicographical path to the matching key already exists during the lookup, a leaf node is reached. At this point, the value (v) stored in this leaf node can be updated. If the search and matching process finds that only part of the path is matched, it may be necessary to create new nodes (which may be branch nodes, extension nodes, or leaf nodes) to complete the remaining path and eventually reach the leaf node, where the value is stored or updated.

[0201] Once a leaf node is updated or created, an upward backtracking process begins. This process starts by recalculating the hash value of the modified leaf node. Then, it moves upwards to the parent node, updating the relevant references in the parent node (which may be the direct content of the child node or the hash value of the child node's content, depending on the size of the child node), and recalculating the hash value of the parent node. This process continues until the root node of the MPT is reached.

[0202] Finally, when the backtracking process reaches the root node, the root hash of the entire MPT is updated. This new root hash represents the new state of the entire state tree and will be included in the block header of the next block as the new state root. In this way, each block not only contains transaction information but also stores the hash value of the global state after these transactions are executed through the state root.

[0203] S184: Update the version of the generated / updated tree node in the corresponding memory page according to the divided logical page structure. The memory page is used to represent the content of all tree nodes in the logical page. The logical page contains a page identifier, which includes the lexicographical content and version of the upper-level tree node in the logical page.

[0204] It should be noted that the process of S184 can occur after S182 or during S182.

[0205] Figure 18 This is a complete illustration of another embodiment of this application. Figure 18 and Figure 13 The overall structure is similar, with the main difference being that, for example, the intermediate node labeled C5 and its subordinate intermediate nodes labeled C5D1, C5D9, and C5D14 together constitute a LogicalPage. Furthermore, the leaf nodes M1, M2, M3, and M4 store key-end data instead of key-full data, and in addition to the position index, each leaf node also contains the hash value of the corresponding state value. Of course, in this embodiment, as mentioned earlier, the leaf nodes M1, M2, M3, and M4 can also be key-full data.

[0206] The leaf node may also include the hash value (valuehash) of the state value content and a key-end field. The calculation of the hash value of the leaf node based on the content of the leaf node includes the calculation based on the hash value of the state value content in the leaf node and the key-end field, but does not include the position index of the state value in the data file in the persistent storage medium.

[0207] The leaf node may also include the hash value of the state value content and a key-full field. Calculating the hash value of the leaf node based on its content includes calculating it based on the hash value of the state value content and the key-full field, but does not include the location index of the state value within the data file in the persistent storage medium. Figure 18 The valuehash in the leaf nodes has been omitted. Furthermore, Figure 18 The data structure of tree nodes is used instead Figure 14 A graphical description in the text.

[0208] In step S182 above, tree nodes were generated / updated. These updated tree nodes are integrated into the corresponding memory pages according to the aforementioned logical page structure, representing the world state tree structure under the current block number. In this application, a version number can be set for the logical page. This version number is typically the block number. Besides the block number, the version number can also be data that uniquely identifies a block, such as block hash, timestamp, state root, transaction root, receipt root, consensus round number, etc. For simplicity, the following explanation uses the block number.

[0209] The version number of a logical page can be used as content in the page identifier of the logical page. In addition to the version number, the page identifier of a logical page can also include the lexicographical order of the contained tree nodes. Specifically, the page identifier can include the lexicographical order of the parent tree nodes in the logical page. For example... Figure 18 As shown, in a LogicalPage comprised of the intermediate node C5 and its subordinate intermediate nodes C5D1, C5D9, and C5D14, the upper-level tree nodes have a NodeID, for example, 0xd2345 (0x represents hexadecimal). The intermediate nodes C5D1, C5D9, and C5D14 also each have a NodeID. The PageID of this LogicalPage can be set to the NodeID of the upper-level tree nodes. These PageIDs represent the lexicographical order of the content from the root node to the upper-level tree nodes within this LogicalPage (i.e., a memory page), that is, the key of the lexicographical order distribution from the root node through the intermediate nodes to the upper-level tree nodes within this LogicalPage. Similarly, the NodeID represents the lexicographical order of the content from the root node to the tree node, that is, the key of the lexicographical order distribution from the root node through the intermediate nodes to the tree node.

[0210] As mentioned above, during the generation / updating of the current version of the tree nodes, the changed tree nodes constitute dirty data. Furthermore, as previously stated, base pages and incremental pages can be generated based on changes in logical pages across consecutive versions. Based on this, either base pages or incremental pages can be used as the smallest unit for disk persistence of the tree. A base page can be generated after a predetermined number of state modifications, or an incremental page can be generated after a predetermined number of state modifications. When the memory occupied by base pages and incremental pages reaches a certain amount, the base pages and incremental pages are batch-persisted to disk.

[0211] The base page and incremental page are persistent objects of the memory pages corresponding to logical pages, while memory pages are in-memory objects of logical pages. A base page generally corresponds to a memory page, contains global state variables, and can have the same page ID as the corresponding memory page. A memory page has the same page ID as the corresponding logical page. An incremental page can also correspond to a memory page, containing tree nodes from one or more consecutive versions of memory pages that have changed relative to the previous adjacent base / increment page. This includes changed state variables, which are generally not global state variables. The structure of the tree nodes in an incremental page generally does not change, so the page ID of the corresponding memory page can be the same as the NodeID of its parent tree node.

[0212] Furthermore, base pages and incremental pages can have versions. After the operation in S184 above, the generation of base pages and incremental pages based on changes in consecutive versions of memory pages can be the generation of corresponding versions of base pages and / or incremental pages based on changes in consecutive versions of memory pages. Specifically, a base page generally corresponds to a memory page and contains all tree nodes in that memory page, which also includes global state variables, and therefore can have the same version as the corresponding memory page. An incremental page can correspond to one or more memory pages and contains tree nodes in one or more consecutive versions of memory pages that have changed relative to the previous adjacent versions of base pages / incremental pages, which also includes changed state variables, but generally not global state variables. Therefore, the version of an incremental page can be the lowest or highest version among the one or more memory pages it corresponds to.

[0213] For example, a base page of version 4 contains state variables a=1, b=2, c=3, and the corresponding intermediate and root nodes. Subsequent incremental pages may include version 5's a=2, its corresponding intermediate and root nodes, version 6's a=1, and version 7's b=4. While version 6's a=1 is the same as the state variable a=1 in the base page, it differs from the adjacent version 5's a=2; therefore, version 6's a=1 and its corresponding intermediate and root nodes are also included in the incremental page. Furthermore, for subsequent incremental pages, such as those containing tree nodes of versions 7, 8, and 9, the tree nodes are actually relative to the immediately preceding incremental page and their versions. The tree nodes of versions 5, 6, and 7 correspond to memory pages of versions 5, 6, and 7, respectively. This incremental page containing tree nodes of versions 5, 6, and 7 can itself be version 5 or 7, meaning it can be the lowest or highest version among the corresponding memory pages.

[0214] Furthermore, a page type can be set in the base page and the incremental page to distinguish between the base page and the incremental page.

[0215] The above scheme, a multi-version page partitioning scheme for Merkle state data dictionary trees, switches the tree to LogicalPage. Both the tree and LogicalPage maintain versions (such as block numbers). Internally, it manages MemoryPage / BasePage / DeltaPage. BasePage / DeltaPage maintains the memory structure and file persistence according to the version. While reducing overall write amplification through page aggregation, it utilizes the ordered nature of versions to avoid compaction after page writes to disk, thus reducing write amplification. Furthermore, through version-based replay, it supports reading state data from any historical version and SPV functionality. In addition, combined with the aforementioned... Figures 9-14 The content can be stored in the data file of the persistent storage medium. The leaf node includes the position index of the state value in the data file of the persistent storage medium, which can further reduce the write amplification problem.

[0216] Corresponding to the world state constructed in the above manner, this application also provides a reading method, including:

[0217] S190: Receive the read status key and version.

[0218] S192: Based on the state key and version, match the version and page ID in the page identifier of the memory page in lexicographical order. If the memory page contains at least two levels of tree nodes, continue to match the version and page ID of the tree nodes below the top-level tree node in lexicographical order until a leaf node is found.

[0219] For the received status key and version, the version and page ID in the page identifier of the memory page can be matched in lexicographical order. For example, for Figure 18 The intermediate node with label C5 and the intermediate nodes with labels C5D1, C5D9, and C5D14 below it together constitute a LogicalPage. The corresponding memory page can be found first by version and page ID, and then the received status key can be used to further match the lower-level tree nodes in the memory page.

[0220] For example, given a received status key of 0xd2345167890ab and version 20, the version + page ID of a memory page is 20 + 0xd2345. Figure 18 The intermediate node labeled C5 and its subordinate intermediate nodes C5D1, C5D9, and C5D14 together form a LogicalPage that can be matched (the first 5 bits of 0xd2345167890ab, i.e., 0xd2345). Furthermore, in the lower-level tree nodes of this memory page, assuming a match is found with the tree node C5D1, meaning a match with NodeID 0xd23451 within C5D1, the matching process can continue to the next lower-level memory page. For example... Figure 19 As shown, the matching continues to the lower-level memory pages. Based on 0xd2345167890ab, a memory page with PageID 0xd234516 and the same version is found. This memory page includes two levels of tree nodes E5 and E5F2, E5F7, and E5F8. Then, within the lower-level tree nodes of this memory page, assuming a match is found with tree node E5F7, that is, a match is found with NodeID 0xd2345167 within tree node E5F7. This process is repeated, matching the version and page ID in the page identifier of the memory pages in lexicographical order, until the final memory page and its leaf nodes are found, completing the search.

[0221] As mentioned earlier, a memory page is a memory-based object of a logical page. However, based on the cache eviction policy in memory, there may not be a currently matching memory page. Also, as mentioned earlier, base pages and incremental pages can be generated based on changes to consecutive versions of logical pages, and these base pages and incremental pages are persistent objects of the memory pages corresponding to the logical pages. Therefore, if the memory page does not exist in memory, the corresponding base page and incremental page can be loaded from the persistent storage medium into memory based on the page identifier, and the loaded base page and incremental page can be replayed to obtain the memory page.

[0222] Specifically, for example, if no memory page with the same version and matching remaining lexicographical content is found in memory, the corresponding base page and incremental page matching the remaining lexicographical content can be found in persistent storage based on the page identifier. As mentioned earlier, since base pages and incremental pages also have versions, and base pages generally have the same version as their corresponding memory pages, while the version of an incremental page can be the lowest among one or more memory pages corresponding to it, the following two scenarios exist:

[0223] 1. In the case where a base page with the same version is found in the persistent storage medium, the corresponding base page can be loaded from the persistent storage medium into memory according to the page identifier, and then the loaded base page can be restored as a memory page.

[0224] 2. If no base page matching the version is found in the persistent storage medium, load the corresponding base page and incremental page from the persistent storage medium into memory according to the page identifier; replay the loaded base page and incremental page to obtain the memory page.

[0225] The page identifiers of the base page and the incremental page may also include the page type.

[0226] Thus, loading the corresponding base page from the persistent storage medium into memory based on the page identifier can mean loading a base page from the persistent storage medium that is no greater than the maximum version of the read version, has the same page ID, and is a base page of type base page. For scenario 1 above, where a base page with the same version is found in the persistent storage medium, this base page with the same version, page ID, and type base page can be loaded into memory. For example, if the version to be searched is 20, but there is no memory page with version 20 in memory, and a base page with the same version 20 is found in the persistent storage medium, this base page with the same version 20, page ID, and type base page can be loaded into memory. For scenario 2 above, where no base page with the same version is found in the persistent storage medium, a base page with the same version, page ID, and type base page of type base page can be loaded from the persistent storage medium. For example, if the version to be searched is 20, but there is no memory page with version 20 in memory, then of course no base page with the same version 20 will be found in the persistent storage medium. In fact, the persistent storage medium may contain, for example, a BasePage1 with version 17, a DeltaPage1 with version 18, a DeltaPage2 with version 20, and a BasePage2 with version 22. The DeltaPage1 with version 18 can include tree nodes with version 18 and tree nodes with version 19, and the DeltaPage2 with version 20 can include tree nodes with version 20 and tree nodes with version 21. Therefore, the BasePage1 with version no greater than 20, the same page ID, and the page type of base page can be loaded into memory. That is, the version of this base page that meets the conditions is 17.

[0227] For scenario 1 above, where a base page with the same version is found in persistent storage, the base page with the same version, page ID, and page type as the base page can be loaded into memory, and then the memory page with the same version can be restored. For example, if the version to be searched is 20, but there is no memory page with version 20 in memory, but a base page with the same version 20 is found in persistent storage, the base page with the same version 20, page ID, and page type as the base page can be loaded into memory, and then the loaded base page with version 20 can be restored to a memory page with the same version 20.

[0228] In scenario 2 above, where no base page matching the version is found in the persistent storage medium, a base page with the same page ID and type as the base page (not greater than the read version) can be loaded from the persistent storage medium into memory. The loaded base page and incremental pages can then be replayed to obtain memory pages. Specifically, this can involve loading a base page with the same page ID and type as the base page (not greater than the read version) from the persistent storage medium into memory, and loading incremental pages from the version of the base page up to the minimum version (not less than the read version) with the same page ID and type as the incremental page into memory. For example, if the version being searched is 20, but a memory page with version 20 does not exist in memory, then naturally no base page with version 20 will be found in the persistent storage medium. In fact, the persistent storage medium may contain, for example, a BasePage1 with version 17, a DeltaPage1 with version 18, a DeltaPage2 with version 20, and a BasePage2 with version 22. DeltaPage1 with version 18 can include tree nodes with version 18 and tree nodes with version 19, and DeltaPage2 with version 20 can include... Tree nodes of version 20 and version 21 can load BasePage1 (version no greater than 20, with the same page ID and page type of the largest version of the base page being 17) into memory. That is, the version of the base page that meets the conditions here is 17. Then, DeltaPage1 (version 17) and DeltaPage2 (version 20) (version 18, with the same page ID and page type of incremental page) are loaded into memory, and the loaded base page and incremental page are replayed to obtain the memory page.

[0229] For scenario 2 above, specifically, the loaded base page and incremental pages can be replayed in order of page type and version to obtain the memory pages. Continuing with the example above, if the loaded base page is BasePage1 (version 17) and the loaded incremental pages include DeltaPage1 (version 18) and DeltaPage2 (version 20), then the incremental pages can be replayed in version order, that is, based on BasePage1 (version 17), in the order of DeltaPage1 (version 18) → DeltaPage2 (version 20), to obtain the memory pages. Since DeltaPage2 of version 20 includes tree nodes of version 20 and tree nodes of version 21, after sequentially replaying the pages up to the incremental page of the largest version not greater than the read version (i.e., replaying to the loaded version 18 DeltaPage1), when sequentially replaying to the loaded maximum version 20 DeltaPage2, not all tree nodes in DeltaPage2 are replayed. Instead, the tree nodes in the incremental page of the loaded maximum version are replayed sequentially until they are the same as the read version (i.e., replaying the tree nodes of version 20 in DeltaPage2), thus obtaining the memory page.

[0230] In another example, suppose an incremental page contains a version of a tree node, that is, the version of the incremental page is the same as the version of the tree node it contains. Then, based on the base page, the incremental pages can be replayed in version order until an incremental page equal to the version read is obtained, thus obtaining a memory page.

[0231] The reason for rewinding from the base page to the incremental page to obtain the memory page is due to the trustless nature of blockchain. It requires not only providing data but also verifiable data. Specifically, based on the leaf nodes of the global state in the base page and all relevant intermediate nodes, the incremental page is rewinded sequentially. That is, the leaf nodes, intermediate nodes, and root node in the base page are updated according to the version order based on the leaf nodes, intermediate nodes, and root node contained in the incremental page. Only then can all tree nodes in the recovered memory page maintain the hash anchoring relationship from the leaf node through the intermediate node to the root node. For example, the correct hash value of the lower-level tree node is stored in the branch node slot, thus achieving data verifiability.

[0232] As mentioned earlier, the version of the incremental page can be the lowest or highest version among one or more memory pages it corresponds to. The example above illustrates the case where the incremental page version is the lowest version among its multiple memory pages. The following describes the case where the incremental page version is the highest version among its multiple memory pages.

[0233] For scenario 2 above, where no base page matching the version is found in the persistent storage medium, a base page with the same page ID and a base page type not greater than the read version can be loaded from the persistent storage medium into memory. Alternatively, incremental pages from the persistent storage medium, ranging from the version of the base page to the minimum version not less than the read version, with the same page ID and an incremental page type, can be loaded into memory. For example, if the version to be found is 20, and there is no memory page with version 20 in memory, then no base page with version 20 will be found in the persistent storage medium. However, the persistent storage medium may contain, for example, a BasePage1 with version 17, a DeltaPage1 with version 19, a DeltaPage2 with version 21, and a BasePage2 with version 22. The DeltaPage1 with version 19 may include tree nodes with version 18 and version 19, and the DeltaPage2 with version 21 may include... Tree nodes of version 20 and version 21 can load BasePage1 (version no greater than 20, with the same page ID and page type of the largest version of the base page being 17) into memory. That is, the version of the base page that meets the conditions here is 17. Then, load DeltaPage1 (version 17) and DeltaPage2 (version 21) (version no less than the smallest version 21 of the read version 20, with the same page ID and page type of incremental page being 19) into memory. Then, replay the loaded base page and incremental page to obtain the memory page.

[0234] For scenario 2 above, specifically, the loaded base page and incremental pages can be replayed in order of page type and version to obtain the memory pages. Continuing with the example above, if the loaded base page is BasePage1 (version 17) and the loaded incremental pages include DeltaPage1 (version 19) and DeltaPage2 (version 21), then the incremental pages can be replayed in version order, that is, based on the version 17 BasePage1, in the order of version 19 DeltaPage1 → version 21 DeltaPage2, to obtain the memory pages. Since DeltaPage2 of version 21 includes tree nodes of version 20 and tree nodes of version 21, after sequentially replaying the pages up to the incremental page of the largest version less than the read version (i.e., replaying to the loaded DeltaPage1 of version 19), when sequentially replaying DeltaPage2 of the largest loaded version 21, not all tree nodes in DeltaPage2 are replayed. Instead, the tree nodes in the incremental page of the largest loaded version are replayed sequentially until they are the same as the read version (i.e., replaying the tree nodes of version 20 in DeltaPage2), thus obtaining the memory page.

[0235] S194: Read the state of the leaf node.

[0236] As mentioned earlier, the leaf node can be in the form of a data file or a KVDB. For the data file format, the leaf node can include the position index of the state value within the data file in the persistent storage medium and the hash value of the state value. Therefore, the position index contained in the leaf node can be obtained, pointing to a position within the data file in the persistent storage medium. This allows the value at the specified position in the persistent storage medium to be loaded into memory and the state data to be read. For the KVDB format, the hash value of the leaf node can be used to search the cache. If the value is not found in the cache, it can be retrieved from the cache as described above. Figure 7 The search in the state database module shown may involve binary search in the sst of each level, as mentioned above and will not be repeated here.

[0237] As mentioned earlier, the essence of a blockchain is a chain-like structure composed of a series of data blocks (blocks) linked by hashes. A memory page can contain all the states in the current version. In fact, many of these states may have been updated in a previous block and have remained unchanged until the current block. This is similar to Ethereum, and this is also called the current state. The currentDB is used to store the latest "current state" data, such as the latest account state, contract code, and contract storage. Moreover, as the blocks grow, the data in the currentDB can be continuously modified. In a blockchain, building a global MPT tree of all states for each block is highly redundant. Referencing the same leaf node and intermediate node that was last updated to that value in a previous block is a more efficient data storage method. Furthermore, the changed state in each block is likely a part of the global state. This is also similar to Ethereum, and is also called the history state.

[0238] In some current blockchain implementations, the current state and history state are stored separately in `currentDB` and `historyDB`, which are typically independent entities. In some implementations, both databases undergo independent persistence. However, this dual-database architecture has significant drawbacks: First, it leads to redundant storage of state data, increasing storage overhead. For example, if `currentDB` occupies 10GB of disk space and `historyDB` occupies 100GB, the total storage requirement reaches 110GB. Second, this architecture increases system complexity. The typical workflow involves updating `currentDB`, generating a binary log (Binlog), synchronizing the Binlog to `historyDB`, and finally, `historyDB` executing the Binlog to generate the corresponding version of the state record. This mechanism of maintaining synchronization between the two databases not only increases system complexity but may also introduce potential risks to data consistency.

[0239] On the other hand, some blockchain implementations adopt a scheme that only retains the currentDB and does not maintain the historyDB. While this approach significantly reduces storage requirements (e.g., only consuming 10GB of disk space), it also introduces new problems. When it is necessary to restore to a certain historical version's state, if the read-write set is saved, the system needs to replay the read-write set from the genesis block in version order until the desired historical version state is reached; if the read-write set is not saved, it needs to replay all transactions from the genesis block until the target state is reached. This method is extremely inefficient, time-consuming, and computationally intensive when restoring historical states, especially when dealing with long-running blockchain systems, where this problem becomes even more pronounced.

[0240] This application is as described above. Figures 9-19 Based on the proposed solution, a method for storing the world state of a tree structure is provided, including:

[0241] S200: The generated / updated tree nodes are used to generate corresponding memory pages according to the divided logical page structure. The memory pages are used to represent the contents of all the corresponding tree nodes in the logical pages. The logical page is the result of aggregating several adjacent tree nodes according to the node association relationship of the tree structure. A logical page contains at least one tree node, and different logical pages contain different tree nodes.

[0242] S202: Generate a base page and an incremental page based on the changes in the content of all tree nodes in the logical pages of consecutive versions;

[0243] S200 and S202 are similar to those mentioned above and will not be described again.

[0244] S204: Persist the base page and incremental page in a database without distinguishing between currentDB and historyDB.

[0245] In this application, a single database is set up. When data is written to disk, the distinction between historyDB and currentDB is no longer made; instead, the base page and incremental page are written to this single database. This avoids the use of two separate databases (currentDB and historyDB) as in existing technologies, thus reducing data redundancy and storage overhead. Furthermore, unlike existing technologies that only maintain the currentDB without maintaining the historyDB, restoring any version of the state becomes faster and more efficient.

[0246] Furthermore, as mentioned earlier, a base page can be generated once for every predetermined number of state modifications, and an incremental page can be generated once for every predetermined number of state modifications.

[0247] The base page and incremental page may contain a page identifier, which includes a version, a page ID, and a page type; the logical page and memory page contain a page identifier, which includes a version and a page ID.

[0248] Furthermore, the state value can be stored in a data file of the persistent storage medium, and the leaf nodes include the position index of the state value within the data file of the persistent storage medium.

[0249] Based on the schemes in Figures S200 to S202 above, this application also provides a method for restoring the world state of any version, including:

[0250] S210: Read the version that needs to be restored;

[0251] S212: Read the base page of the same version as the restored version from the database;

[0252] S214: If a base page of the same version as the recovery version is read from the database, then the base page of the recovery version is loaded from the database into memory to obtain a memory page;

[0253] S216: If no base page of the same version as the recovery version is read in the database, load the base page of the largest version not greater than the recovery version and whose page type is base page from the database into memory; load the incremental page of the smallest version not less than the recovery version and whose page type is incremental page from the database into memory; replay the loaded base page and incremental page in the order of page type and version to obtain the memory page of the recovery version;

[0254] S218: For a memory page containing a leaf node, read the state in the leaf node into memory.

[0255] To restore the world state of any version, such as the current version or any historical version, the above restoration process can be executed according to the version to be restored. Of course, for memory pages existing in memory, as mentioned earlier, based on the eviction mechanism in the cache, some MemoryPages may be evicted. If a MemoryPage to be restored is evicted, the corresponding BasePage and DeltaPage can be read and replayed. As mentioned earlier, changes to logical pages based on consecutive versions can generate base pages and incremental pages, which are persistent objects of the memory pages corresponding to the logical pages. Therefore, if the memory page does not exist in memory, the corresponding base page and incremental page can be loaded from the persistent storage medium into memory, and the loaded base page and incremental page can be replayed to obtain the memory page.

[0256] Furthermore, in the case of a cold start of a blockchain node, there are generally no memory pages in memory. In this case, the solution proposed in this application can be used to load the base page and incremental page corresponding to the latest version of the block from the persistent storage medium into memory, and then replay the loaded base page and incremental page to obtain the memory page, thereby obtaining the current state.

[0257] In existing technologies, for restoring any historical version, besides the aforementioned scheme of replaying all transactions from the genesis block until the target state is reached, another approach is to start from the root node of the MPT tree locked by the state root of a specified historical version and search for tree nodes in the database. This process involves decoding and then continuing to search for the next level of tree nodes according to slot relationships, and also involves searching layer by layer in LevelDB, including traversal and a large number of binary search operations. As mentioned earlier, this is computationally intensive and suffers from read amplification. In fact, the same problem exists for restoring the current version.

[0258] The reading scheme provided in this application uses a method of marking base pages and incremental pages based on versions. When searching for base pages and incremental pages in the database, which are generally distributed in version order, a fast search can be performed, thereby improving recovery efficiency.

[0259] The method may further include: verifying the hash locking relationship between adjacent tree nodes from the leaf node to the root node, and verifying the consistency between the root node's hash value and the state root in the latest version block. This is because the world state of the tree structure in the blockchain is anchored by the hash value of the next-level tree node from the previous level, thus achieving verifiable storage as a whole. Therefore, after recovering a certain version of the world state through the above method, further verification of the anchored hash can ensure the correctness of the world state.

[0260] As mentioned earlier, the state value can be stored in a data file of the persistent storage medium, and the leaf node includes the position index of the state value within the data file of the persistent storage medium. Accordingly, reading the state in the leaf node can involve obtaining the position index contained in the leaf node, where the position index points to a position within the data file of the persistent storage medium, and then loading the value at the position in the data file of the persistent storage medium pointed to by the position index into memory and reading the state data therein.

[0261] In the example described above, the leaf node may include the hash value of the state value content (valuehash). Calculating the hash value of the leaf node based on its content includes calculating the hash value of the state value content within the leaf node, but does not include the location index of the state value within the data file in the persistent storage medium. Here, based on the inclusion of the valuehash field in the leaf node, this scheme can also verify that the hash value of the data file in the persistent storage medium pointed to by the location index is consistent with the valuehash in the leaf node.

[0262] The process of replaying the loaded base page and incremental page in order of page type and version to obtain the memory page of the restored version can be similar to the previous one. It can be based on the base page, replaying the incremental page in version order up to the incremental page of the largest version smaller than the restored version, and continuing to replay the tree nodes in the incremental page of the largest version loaded in order until it is the same as the restored version, thus obtaining the memory page.

[0263] For example, if the version to be restored is 20, but no base page with the same version 20 is found in the database, as in the previous example, BasePage1, whose version is no greater than 20 and whose page type is the largest version of the base page (17), can be loaded into memory. That is, the version of this matching base page is 17. Then, DeltaPage1 (version 17 onwards) up to the smallest version 21 (not less than the read version 20), DeltaPage1 (version 19) with the same page ID and whose page type is incremental page, and DeltaPage2 (version 21) can be loaded into memory. The loaded base page and incremental page can then be replayed to obtain the memory page. Specifically, the loaded base page and incremental page can be replayed in order of page type and version to obtain the memory page. Continuing with the example above, the loaded base page is BasePage1, version 17. The loaded incremental pages include DeltaPage1, version 19, and DeltaPage2, version 21. The incremental pages can be replayed in version order, i.e., based on BasePage1 (version 17), in the order of DeltaPage1 (version 19) → DeltaPage2 (version 21), to obtain the memory pages. Since DeltaPage2 (version 21) includes tree nodes of version 20 and version 21, after replaying the pages sequentially up to the largest version of the incremental page less than the read version (i.e., replaying to the loaded DeltaPage1, version 19), when replaying the largest version of DeltaPage2 (version 21), not all tree nodes in DeltaPage2 are replayed. Instead, the tree nodes in the largest version of the incremental page are replayed sequentially until they match the read version (i.e., replaying the tree nodes of version 20 in DeltaPage2), thus obtaining the memory pages.

[0264] It should be noted that, for multiple logical pages, although both generate a base page and an incremental page every predetermined number of state modifications (generally set to the same number), different logical pages contain different tree nodes. Therefore, for a tree structure containing multiple logical pages, the tree nodes within those pages may not be modified synchronously. This could lead to issues such as... Figure 20 In this scenario, the tree node containing version 17 is located in the DeltaPage (version 17) within the left LogicalPage, while it is located in the BasePage (version 17) within the right LogicalPage. This means the version numbers of the BasePage and DeltaPage are not synchronized across different logical pages. When restoring the world state to a specified version, the aforementioned S214 and S216 operations may be performed concurrently, without any specific order.

[0265] In Ethereum's MPT tree, there are root nodes, intermediate nodes, and leaf nodes. For example... Figure 4 , 5 As shown, and as Figure 10 As illustrated in the embodiments provided in this application, the root node of this MPT tree is generally an extension node or a branch node, and the hash value of this root node is generally stored in `state_root`. The root node can be connected to one or more extension nodes / branch nodes below it. These multi-level tree nodes can be collectively referred to as internal nodes. Whether it is an external account or a contract account, its account information is generally located in a single leaf node. From the extension node / branch node of the root node to the leaf node of each account, it may pass through several branch nodes and extension nodes. For a contract account in the state trie, its `storage_Root` points to another tree that is also of the MPT form.

[0266] An Extension Node typically has one child node, which can be either a Branch Node or a Leaf Node. An Extension Node stores a common prefix / infix to represent one or more consecutive digits of the state key. For example... Figure 5 Nodes like A8, A6, and A13 in the tree can store the hash values ​​of linked next-level tree nodes. Next-level tree nodes may include Branch Nodes.

[0267] For a Branch Node, typically a 16-ary tree, it can expand to a maximum of 16 branches using 16 slots. It can also be a 2-ary, 8-ary, 32-ary, 64-ary, or 256-ary tree. Taking a 16-ary tree as an example, it can have a maximum of 16 child nodes. Each child node uses one slot to store the hash value of the next-level tree node it is linked to. The next-level tree nodes may include Branch Nodes, Extension Nodes, and Leaf Nodes. Generally, a Branch Node uses these 16 slots to represent a hexadecimal number, thus representing one bit of the state key.

[0268] In addition, leaf nodes can store one or more consecutive digits of the state key.

[0269] In this way, a state key is distributed sequentially along the path from the root node through several intermediate nodes to the leaf node.

[0270] In fact, an Extension Node can be expanded into several interconnected Branch Nodes. For example, for Figure 10 Node A6 in the diagram can be expanded into two interconnected Branch Nodes: the upper Branch Node occupies slot d, and the lower Branch Node occupies slot 3. The upper Branch Node locks the hash value of the lower Branch Node in slot d, while the lower Branch Node locks the hash value of the original A5 node in slot 3.

[0271] In other words, an MPT containing Branch Node, Extension Node, and Leaf Node can be extended to an MPT containing only Branch Node and Leaf Node. This allows for... Figure 11 As shown, Branch Nodes are used as the intermediate and root nodes of the tree. Figure 11 In this case, a two-level tree structure can still be used. The leaf nodes in the upper-level tree can store account states (including the states of external accounts and contract accounts), and the leaf nodes in the lower-level tree store the contract states. Alternatively, a single-level tree structure can be used to store both account and contract states, for example... Figure 12 As shown, both account status and contract status are distributed across the underlying leaf nodes. Furthermore, in... Figure 12 On the basis of, such as Figure 13 In this context, prefix and / or infix compression can be performed, as shown in the figure where tree node C5 can have compressed infix 2d.

[0272] As mentioned above, the entire Merkle tree structure can be divided into multiple Logical Pages. This can be achieved by aggregating several adjacent tree nodes into a single Logical Page based on the node relationships within the tree structure. For example, a logical page can be formed by aggregating 256 child nodes (level 2, 16 branches) of a trie. From the root node to the leaf node of the Merkle tree, there are multiple levels of Logical Pages, with parent-child and sibling relationships between them, thus forming a complete Merkle tree. In this way, the tree structure can be divided into multiple logical pages, each containing at least one tree node. Different logical pages contain different tree nodes, and each logical page maintains the latest version of the corresponding tree node's content.

[0273] In the embodiments provided in this application, the LogicalPage can be designed in the following ways:

[0274] A LogicalPage is divided into InternalPages and LeafPages. An InternalPage contains one root node and multiple child nodes of that root. For example, an InternalPage contains one root InternalNode and at most 16 child InternalNodes. A LeafPage contains one leaf node, or a subtree consisting of at least two leaf nodes and at least one internal node. To form a complete tree structure, at least one slot in any of the aforementioned InternalNodes must be non-empty. A typical example is attached. Figure 18 The internal node C5 and its three lower-level internal nodes C5D1, C5D9, and C5D14 form an internal page. C5, C5D1, C5D9, and C5D14 form a subtree. In this case, all three slots of the internal node C5 are not empty: slot 1 stores the hash value of internal node C5D1, slot 9 stores the hash value of internal node C5D9, and slot 1 stores the hash value of internal node C5D14. Each of the internal nodes C5D1, C5D9, and C5D14 has at least one non-empty slot because, as an internal node, it must be connected to lower-level internal nodes. The specific number and type of non-empty slots depend on the number and position of the lower-level internal nodes it is connected to.

[0275] When the subtree structure within a LeafPage changes, the LeafPage may become too large or too small. To better manage InternalPages and LeafPages, LeafPages can be scaled.

[0276] Based on this, this application proposes a method for stretching a LeafPage, comprising:

[0277] S220: Tree nodes generated / updated according to the tree structure construction rules.

[0278] As mentioned earlier, a write status key-value pair is typically received first. Based on the tree structure construction rules, leaf nodes of the tree structure corresponding to the status key-value pair can be generated first. The hash value of the leaf node is calculated based on its content, and upper-level tree nodes are generated or updated based on the hash value of the leaf node and the status key, until the root node of the tree is reached.

[0279] The leaf nodes can be in the form of the aforementioned data file or the aforementioned KVDB. If the aforementioned data file format is used, the leaf node can generate a value including the position index of the state value within the data file in the persistent storage medium and the hash value of the state value content.

[0280] Specifically, when the storage module receives a write status key-value pair (kv) request, it first hashes the key (k) (e.g., using Keccak-256). Alternatively, the status key received here may not be hashed. Next, a top-down search is performed using this key in the tree. This search starts from the root node and traverses and matches the path down the tree according to the lexicographical order of the keys. During this process, the key is typically compared bit-by-bit (or nibble, typically a single hexadecimal digit) with the path stored in the node. When a leaf node is reached, the value (v) stored in that leaf node is updated. If an existing leaf node cannot be reached (i.e., only part of the key's path is matched), a new leaf node may need to be created to complete the remaining path, and the value is stored in that leaf node.

[0281] Once a leaf node is updated or created, an upward backtracking process begins. This process starts with the modified leaf node and recalculates its hash value. Then, it moves upwards to the parent node, updates the relevant references in the parent node (such as the hash values ​​of the child node's content), and recalculates the parent node's hash value. This process continues from the bottom up until the root node of the tree is reached to complete the update.

[0282] According to the original logical page structure, the subtree structure within a LeafPage may change, which could lead to the LeafPage becoming too large. Therefore, proceed to step S222:

[0283] S222: For a LeafPage where a subtree morphology occurs, the LeafPage is expanded when any of the following conditions are met:

[0284] (1) The number of LeafNodes in the LeafPage has reached the high watermark threshold;

[0285] (2) Any InternalNode in the first or middle level of the LeafPage's subtree is full-crossed.

[0286] For condition 1, specifically, for example, if the high watermark threshold is set to 24, then when the number of LeafNodes in a LeafPage reaches this threshold, in order to reduce the number of tree nodes managed in a LeafPage, the LeafPage can be stretched.

[0287] The stretching process can involve generating new InternalPages and LeafPages, or generating multiple new LeafPages to replace the existing LeafPages. Specifically, for example... Figure 21 As shown, if a new LeafNode is generated in the bottom left corner of the original LeafPage, and some new LeafNodes are also generated in the other two InternalNodes, causing the total number of LeafNodes in the LeafPage to exceed 24, then the LeafPage can be expanded into one InternalPage and three LeafPages. In this way, the number of LeafNodes in any of the expanded LeafPages will not exceed 24. For example... Figure 22 As shown, if some new LeafNodes are generated in the original LeafPage above, causing the total number of LeafNodes in the LeafPage to exceed 24, then the LeafPage can be expanded into 2 LeafPages. In this way, the number of LeafNodes in either of the expanded LeafPages will not exceed 24.

[0288] Furthermore, each LeafPage can record the number of LeafNodes it contains, making it easier to determine whether condition 1 is met. For example... Figure 21 As shown, the LeafPage before the top extension has 27 LeafNodes, exceeding 24. The LeafPages after the bottom extension have 6, 9, and 12 LeafNodes respectively, none exceeding 24. Additionally, for a LeafPage, the total number of LeafNodes it contains and the total number of LeafNodes in its connected lower-level LeafPages can also be recorded, such as... Figure 22 The 27th leaf page in the upper-level leaf page after the middle extension. Recording the total number of leaf nodes facilitates leaf node management, such as determining whether loading is complete during loading or whether traversal is complete during traversal. Similarly, the total number of lower-level leaf pages connected to the leaf page can also be recorded.

[0289] In addition, for InternalPage, the total number of its connected lower-level LeafNodes can also be recorded, such as Figure 21 The 27th InternalPage after expansion. By recording the total number of connected lower-level LeafNodes, it is easier to manage LeafNodes, such as determining whether loading is complete during loading or whether traversal is complete during traversal. Furthermore, for InternalPages, it is also possible to record the total number of connected lower-level LeafPages, or vice versa.

[0290] Regarding condition 2 above, it can be as follows: Figure 23 As shown, if some new LeafNodes are generated in the original LeafPage above, the number of InternalNodes in the second layer will increase, thus causing the InternalNodes in the first layer to be fully branched (filled with the maximum number of slots, also known as full branching). Then the LeafPage can be expanded into 1 InternalPage and 1 LeafPage.

[0291] In the case where the intermediate node contains a compressed infix, the compressed infix may split during the stretching process.

[0292] In the case where the leaf node contains a compressed suffix, the compressed suffix may split during the stretching process.

[0293] Furthermore, this application proposes a method for shrinking LeafPage, comprising:

[0294] S230: Tree nodes generated / updated according to the tree structure construction rules.

[0295] S232: For a LeafPage where a subtree shape occurs, the LeafPage shall be shrunk if any of the following conditions are met:

[0296] (1) The number of LeafNodes in the LeafPage is below the low water level threshold;

[0297] (2) The number of slots occupied by the InternalNode at any level in the subtree of LeafPage is less than the threshold.

[0298] For condition 1, specifically, for example, if the low watermark threshold is set to 4, then when the number of LeafNodes in a LeafPage is lower than this threshold, in order to increase the number of tree nodes managed in a LeafPage, the LeafPage can be shrunk.

[0299] One way to shrink a LeafPage is to merge it with its parent InternalPage to form a new LeafPage. Specifically, for example... Figure 24 As shown, if the number of LeafNodes in the LeafPage at the bottom right becomes 3, which is lower than the low watermark threshold of 4, then this LeafPage can be merged with the InternalPage above to form a LeafPage.

[0300] Another way to shrink a LeafPage is to merge it with its parent LeafPage to form a new LeafPage. Specifically, for example... Figure 25 As shown, if the number of LeafNodes in the original LeafPage above, such as the LeafPage in the lower right corner, becomes 3, which is lower than the low watermark threshold of 4, then this LeafPage can be merged with the LeafPage above to form a new LeafPage.

[0301] Furthermore, each LeafPage can record the number of LeafNodes it contains, making it easier to determine whether condition 1 is satisfied. Similarly, for a LeafPage, the total number of LeafNodes it contains and the total number of LeafNodes in its connected lower-level LeafPages can also be recorded. For an InternalPage, the total number of its connected lower-level LeafNodes, or the total number of its connected lower-level InternalPages, can also be recorded.

[0302] Regarding condition 2 above, it can be as follows: Figure 26 As shown, if some new LeafNodes are deleted from the original InternalPage above, such as a LeafPage in the lower right corner, so that the number of branches of the InternalNodes in a certain layer of the original InternalPage is lower than the threshold, then the LeafPage can be shrunk into the upper-level InternalPage it connects to.

[0303] In the case where the intermediate node contains a compressed infix, the compressed infix can be merged during the shrinking process.

[0304] In the case where the leaf node contains a compressed suffix, the compressed suffix can be merged during the shrinking process.

[0305] Similarly, changes in the subtree structure within an InternalPage may cause the InternalPage to become too large or too small. To better manage InternalPages, they can be scaled.

[0306] Here, this application also provides a method for stretching intermediate pages, including:

[0307] S240: Tree nodes are generated / updated according to the tree structure construction rules; the tree nodes correspond to memory pages according to the divided logical page structure, and the memory pages are used to represent the contents of all tree nodes in the logical page; the logical page is the result of aggregating several adjacent tree nodes according to the node association relationship of the tree structure, and a logical page contains at least one tree node, and different logical pages contain different tree nodes; the logical page is divided into intermediate pages and leaf pages, wherein one intermediate page contains one intermediate node as the root of this logical page and multiple intermediate nodes as child nodes of this root; one leaf page contains one leaf node, or contains at least two leaf nodes and at least one intermediate node to form a subtree;

[0308] S242: For intermediate pages whose subtree structure has changed, the intermediate page shall be expanded if any of the following conditions are met:

[0309] (1) The number of intermediate nodes in the intermediate page has reached the high watermark threshold;

[0310] (2) Any intermediate node of the intermediate page is full cross.

[0311] The contraction can be as follows: Figure 27 As shown in 28, this includes: decomposing the intermediate page into two layers of intermediate pages, upper and lower.

[0312] Similarly, the number of leaf nodes contained in the leaf page can be recorded.

[0313] Similarly, the total number of lower-level leaf pages connected to the leaf page can be recorded in the leaf page.

[0314] Similarly, the leaf page can record the total number of leaf nodes it contains and the total number of leaf nodes in the lower-level leaf pages it is connected to.

[0315] Similarly, the intermediate page can record the total number of lower-level LeafNodes it is connected to.

[0316] Similarly, the intermediate page can record the total number of its connected lower intermediate pages.

[0317] Similarly, the intermediate page can record the total number of the lower-level leaf pages it is connected to.

[0318] In the case where the intermediate node contains a compressed infix, the compressed infix can split during the stretching and contracting process.

[0319] In the case where the leaf node contains a compressed suffix, the compressed suffix may split during the stretching process.

[0320] Here, this application also provides a method for shrinking intermediate pages, including:

[0321] S250: Tree nodes generated / updated according to the tree structure construction rules; the tree nodes correspond to memory pages according to the divided logical page structure, and the memory pages are used to represent the content of all tree nodes in the logical page; the logical page is the result of aggregating several adjacent tree nodes according to the node association relationship of the tree structure, and a logical page contains at least one tree node, and different logical pages contain different tree nodes; the logical page is divided into intermediate pages and leaf pages, wherein one intermediate page contains one intermediate node as the root of this logical page and multiple intermediate nodes as child nodes of this root; one leaf page contains one leaf node, or contains at least two leaf nodes and at least one intermediate node to form a subtree;

[0322] S252: For intermediate pages whose subtree structure has changed, the intermediate page shall be shrunk if any of the following conditions are met:

[0323] (1) The number of intermediate nodes in the intermediate page is lower than the low water level threshold;

[0324] (2) The number of slots occupied by any intermediate node in any layer of the intermediate page is less than the threshold.

[0325] The shrinking includes merging the intermediate page with its upper / lower intermediate page. The shrinking can be viewed as... Figure 27 Or the reverse process shown in 28. For example, if the number of intermediate nodes in the intermediate page is lower than the low watermark threshold, or if the number of slots occupied by intermediate nodes in any layer of the intermediate page is lower than the threshold, the intermediate page can be merged with the intermediate page above it, or the intermediate page can be merged with the intermediate page below it.

[0326] Similarly, the number of leaf nodes contained in the leaf page can be recorded.

[0327] Similarly, the total number of lower-level leaf pages connected to the leaf page can be recorded in the leaf page.

[0328] Similarly, the leaf page can record the total number of leaf nodes it contains and the total number of leaf nodes in the lower-level leaf pages it is connected to.

[0329] Similarly, the intermediate page can record the total number of lower-level LeafNodes it is connected to.

[0330] Similarly, the intermediate page can record the total number of its connected lower intermediate pages.

[0331] Similarly, the intermediate page can record the total number of the lower-level leaf pages it is connected to.

[0332] In the case where the intermediate node contains a compressed infix, the compressed infix can be merged during the shrinking process.

[0333] In the case where the leaf node contains a compressed suffix, the compressed suffix can be merged during the shrinking process.

[0334] This application also provides a computer device, including:

[0335] processor;

[0336] And a memory containing a program, wherein, when the processor executes the program, any of the above-described methods are performed.

[0337] In the 1990s, improvements to a technology could be clearly distinguished as either hardware improvements (e.g., improvements to the circuit structure of diodes, transistors, switches, etc.) or software improvements (improvements to methodology). However, with technological advancements, many methodological improvements today can be considered direct improvements to hardware circuit structures. Designers almost always obtain the corresponding hardware circuit structure by programming the improved methodology into the hardware circuit. Therefore, it cannot be said that a methodological improvement cannot be implemented using hardware physical modules. For example, a Programmable Logic Device (PLD) (such as a Field Programmable Gate Array (FPGA)) is such an integrated circuit whose logic function is determined by the user programming the device. Designers can program and "integrate" a digital system onto a PLD themselves, without needing chip manufacturers to design and manufacture dedicated integrated circuit chips. Furthermore, nowadays, instead of manually manufacturing integrated circuit chips, this programming is mostly implemented using "logic compiler" software. Similar to the software compiler used in program development, the original code before compilation must be written in a specific programming language, called a Hardware Description Language (HDL). There are many HDLs, such as ABEL (Advanced Boolean Expression Language), AHDL (Altera Hardware Description Language), Confluence, CUPL (Cornell University Programming Language), HDCal, JHDL (Java Hardware Description Language), Lava, Lola, MyHDL, PALASM, and RHDL (Ruby Hardware Description Language). Currently, the most commonly used are VHDL (Very-High-Speed ​​Integrated Circuit Hardware Description Language) and Verilog. Those skilled in the art should also understand that by simply performing some logic programming on the method flow using one of these hardware description languages ​​and programming it into an integrated circuit, the hardware circuit implementing the logical method flow can be easily obtained.

[0338] The controller can be implemented in any suitable manner. For example, it can take the form of a microprocessor or processor and a computer-readable medium storing computer-readable program code (e.g., software or firmware) executable by the (micro)processor, logic gates, switches, application-specific integrated circuits (ASICs), programmable logic controllers, and embedded microcontrollers. Examples of controllers include, but are not limited to, the following microcontrollers: ARC 625D, Atmel AT91SAM, Microchip PIC18F26K20, and Silicon Labs C8051F320. A memory controller can also be implemented as part of the control logic of the memory. Those skilled in the art will also recognize that, in addition to implementing the controller in purely computer-readable program code form, the same functionality can be achieved by logically programming the method steps to make the controller take the form of logic gates, switches, application-specific integrated circuits, programmable logic controllers, and embedded microcontrollers. Therefore, such a controller can be considered a hardware component, and the means included therein for implementing various functions can also be considered as structures within the hardware component. Alternatively, the means for implementing various functions can be considered as both software modules implementing the method and structures within the hardware component.

[0339] The systems, devices, modules, or units described in the above embodiments can be implemented by computer chips or physical entities, or by products with certain functions. A typical implementation device is a server system. Of course, this application does not exclude the possibility that, with the future development of computer technology, the computer implementing the functions of the above embodiments can be, for example, a personal computer, a laptop computer, an in-vehicle human-machine interaction device, a cellular phone, a camera phone, a smartphone, a personal digital assistant, a media player, a navigation device, an email device, a game console, a tablet computer, a wearable device, or any combination of these devices.

[0340] While one or more embodiments of this specification provide the operational steps of the methods described in the embodiments or flowcharts, more or fewer operational steps may be included based on conventional or non-inventive means. The order of steps listed in the embodiments is merely one possible order of execution among many steps and does not represent the only possible order. In actual device or end product execution, the methods shown in the embodiments or drawings may be executed sequentially or in parallel (e.g., in a parallel processor or multi-threaded processing environment, or even a distributed data processing environment). The terms "comprising," "including," or any other variations thereof are intended to cover non-exclusive inclusion, such that a process, method, product, or apparatus that comprises a list of elements includes not only those elements but also other elements not expressly listed, or elements inherent to such a process, method, product, or apparatus. Without further limitations, the presence of other identical or equivalent elements in the process, method, product, or apparatus that includes said elements is not excluded. For example, the use of terms such as "first," "second," etc., is to denote names and does not indicate any particular order.

[0341] For ease of description, the above devices are described in terms of function, divided into various modules. Of course, when implementing one or more of these specifications, the functions of each module can be implemented in one or more software and / or hardware components, or a module that performs the same function can be implemented by a combination of multiple sub-modules or sub-units. The device embodiments described above are merely illustrative. For example, the division of units is only a logical functional division; in actual implementation, there may be other division methods. For example, multiple units or components may be combined or integrated into another system, or some features may be ignored or not executed. Furthermore, the coupling or direct coupling or communication connection shown or discussed may be through some interfaces, indirect coupling or communication connection between devices or units, and may be electrical, mechanical, or other forms.

[0342] This invention is described with reference to flowchart illustrations and / or block diagrams of methods, apparatus (systems), and computer program products according to embodiments of the invention. It will be understood that each block of the flowchart illustrations and / or block diagrams, and combinations of blocks in the flowchart illustrations and / or block diagrams, can be implemented by computer program instructions. These computer program instructions can be provided to a processor of a general-purpose computer, special-purpose computer, embedded processor, or other programmable data processing apparatus to produce a machine, such that the instructions, which execute via the processor of the computer or other programmable data processing apparatus, generate instructions for implementing the flowchart illustrations and / or block diagrams. Figure 1 One or more processes and / or boxes Figure 1 A device that provides the functions specified in one or more boxes.

[0343] These computer program instructions may also be stored in a computer-readable storage medium that can direct a computer or other programmable data processing device to function in a particular manner, such that the instructions stored in the computer-readable storage medium produce an article of manufacture including instruction means, which are implemented in a process Figure 1 One or more processes and / or boxes Figure 1 The function specified in one or more boxes.

[0344] These computer program instructions may also be loaded onto a computer or other programmable data processing equipment to cause a series of operational steps to be performed on the computer or other programmable equipment to produce a computer-implemented process, thereby providing instructions that execute on the computer or other programmable equipment for implementing the process. Figure 1 One or more processes and / or boxes Figure 1 The steps of the function specified in one or more boxes.

[0345] In a typical configuration, a computing device includes one or more processors (CPU), input / output interfaces, network interfaces, and memory.

[0346] Memory may include non-persistent storage in computer-readable media, such as random access memory (RAM) and / or non-volatile memory, such as read-only memory (ROM) or flash RAM. Memory is an example of computer-readable media.

[0347] Computer-readable media, including both permanent and non-permanent, removable and non-removable media, can store information using any method or technology. Information can be computer-readable instructions, data structures, program modules, or other data. Examples of computer storage media include, but are not limited to, phase-change memory (PRAM), static random access memory (SRAM), dynamic random access memory (DRAM), other types of random access memory (RAM), read-only memory (ROM), electrically erasable programmable read-only memory (EEPROM), flash memory or other memory technologies, CD-ROM, digital versatile optical disc (DVD) or other optical storage, magnetic tape, magnetic magnetic disk storage, graphene storage or other magnetic storage devices, or any other non-transferable medium that can be used to store information accessible by a computing device. As defined herein, computer-readable media does not include transient computer-readable media, such as modulated data signals and carrier waves.

[0348] Those skilled in the art will understand that one or more embodiments of this specification can be provided as a method, system, or computer program product. Therefore, one or more embodiments of this specification may take the form of a completely hardware embodiment, a completely software embodiment, or an embodiment combining software and hardware aspects. Furthermore, one or more embodiments of this specification may take the form of a computer program product implemented on one or more computer-usable storage media (including, but not limited to, disk storage, CD-ROM, optical storage, etc.) containing computer-usable program code.

[0349] One or more embodiments of this specification can be described in the general context of computer-executable instructions, such as program modules, that are executed by a computer. Generally, program modules include routines, programs, objects, components, data structures, etc., that perform a particular task or implement a particular abstract data type. One or more embodiments of this specification can also be practiced in distributed computing environments where tasks are performed by remote processing devices connected via a communication network. In a distributed computing environment, program modules can reside in local and remote computer storage media, including storage devices.

[0350] The various embodiments in this specification are described in a progressive manner. Similar or identical parts between embodiments can be referred to mutually. Each embodiment focuses on describing the differences from other embodiments. In particular, system embodiments are basically similar to method embodiments, so the description is relatively simple; relevant parts can be referred to the descriptions in the method embodiments. In the description of this specification, the terms "one embodiment," "some embodiments," "example," "specific example," or "some examples," etc., refer to specific features, structures, materials, or characteristics described in connection with that embodiment or example, which are included in at least one embodiment or example of this specification. In this specification, the illustrative expressions of the above terms do not necessarily refer to the same embodiment or example. Furthermore, the specific features, structures, materials, or characteristics described can be combined in any suitable manner in one or more embodiments or examples. Moreover, without contradiction, those skilled in the art can combine and integrate the different embodiments or examples described in this specification and the features of different embodiments or examples.

[0351] The above description is merely an embodiment of one or more embodiments of this specification and is not intended to limit the scope of this specification. Various modifications and variations can be made to the one or more embodiments of this specification by those skilled in the art. Any modifications, equivalent substitutions, improvements, etc., made within the spirit and principles of this specification should be included within the scope of the claims. < / k2-v2> < / k1-v1> < / k2-v2> < / k1-v1> < / k2-v2> < / k1-v1> < / k2-v2> < / k1-v1>

Claims

1. A method for extending leaf pages, comprising: Tree nodes are generated / updated according to the tree structure construction rules; The tree node corresponds to a memory page according to the divided logical page structure, and the memory page is used to represent the contents of all the corresponding tree nodes in the logical page; The logical page is the result of aggregating several adjacent tree nodes according to the node association relationship of the tree structure. A logical page contains at least one tree node, and different logical pages contain different tree nodes. The logical page is divided into intermediate pages and leaf pages. An intermediate page contains one intermediate node as the root of the logical page and multiple intermediate nodes as children of the root. A leaf page contains one leaf node, or contains at least two leaf nodes and at least one intermediate node to form a subtree. For a leaf page whose subtree shape has changed, the leaf page shall be expanded if any of the following conditions are met: (1) The number of leaf nodes in this leaf page has reached the high water level threshold; (2) Any intermediate node in the subtree of this leaf page is full cross.

2. The method of claim 1, wherein the extension comprises: Generate new intermediate pages and leaf pages, or generate multiple new leaf pages to replace the leaf pages before expansion.

3. A method for shrinking leaf pages, comprising: Tree nodes are generated / updated according to the tree structure construction rules; The tree node corresponds to a memory page according to the divided logical page structure, and the memory page is used to represent the contents of all the corresponding tree nodes in the logical page; The logical page is the result of aggregating several adjacent tree nodes according to the node association relationship of the tree structure. A logical page contains at least one tree node, and different logical pages contain different tree nodes. The logical page is divided into intermediate pages and leaf pages. An intermediate page contains one intermediate node as the root of the logical page and multiple intermediate nodes as children of the root. A leaf page contains one leaf node, or contains at least two leaf nodes and at least one intermediate node to form a subtree. For a leaf page whose subtree shape has changed, the leaf page shall be shrunk if any of the following conditions are met: (1) The number of leaf nodes in this leaf page is lower than the low water level threshold; (2) The number of slots occupied by any intermediate node in the subtree of this leaf page is less than the threshold.

4. The method of claim 3, wherein the contraction comprises: Merge this leaf page with the leaf page above it; or, Merge this leaf page with the middle page above it to form a new leaf page.

5. A method for stretching a middle page, comprising: Tree nodes are generated / updated according to the tree structure construction rules; The tree node corresponds to a memory page according to the divided logical page structure, and the memory page is used to represent the contents of all the corresponding tree nodes in the logical page; The logical page is the result of aggregating several adjacent tree nodes according to the node association relationship of the tree structure. A logical page contains at least one tree node, and different logical pages contain different tree nodes. The logical page is divided into intermediate pages and leaf pages. An intermediate page contains one intermediate node as the root of the logical page and multiple intermediate nodes as children of the root. A leaf page contains one leaf node, or contains at least two leaf nodes and at least one intermediate node to form a subtree. For intermediate pages whose subtree structure has changed, the intermediate page should be expanded if any of the following conditions are met: (1) The number of intermediate nodes in the intermediate page has reached the high watermark threshold; (2) Any intermediate node of the intermediate page is full cross.

6. The method of claim 5, wherein the extension comprises: The intermediate page is broken down into two layers: an upper and a lower intermediate page.

7. A method for shrinking middle pages, comprising: Tree nodes are generated / updated according to the tree structure construction rules; The tree node corresponds to a memory page according to the divided logical page structure, and the memory page is used to represent the contents of all the corresponding tree nodes in the logical page; The logical page is the result of aggregating several adjacent tree nodes according to the node association relationship of the tree structure. A logical page contains at least one tree node, and different logical pages contain different tree nodes. The logical page is divided into intermediate pages and leaf pages. An intermediate page contains one intermediate node as the root of the logical page and multiple intermediate nodes as children of the root. A leaf page contains one leaf node, or contains at least two leaf nodes and at least one intermediate node to form a subtree. For intermediate pages whose subtree structure changes, the intermediate page should be shrunk if any of the following conditions are met: (1) The number of intermediate nodes in the intermediate page is lower than the low water level threshold; (2) The number of slots occupied by any intermediate node in any layer of the intermediate page is less than the threshold.

8. The method of claim 7, wherein the contraction comprises: Merge the intermediate page with its parent / lower intermediate page.

9. The method according to any one of claims 1 to 8, wherein the number of leaf nodes contained in the leaf page is recorded.

10. The method according to any one of claims 1 to 8, wherein the leaf page records the total number of lower-level leaf pages to which it is connected.

11. The method according to any one of claims 1 to 8, wherein the leaf page records the total number of leaf nodes contained therein and the total number of leaf nodes in the lower-level leaf pages to which it is connected.

12. The method as described in any one of claims 1 to 8, wherein the intermediate page records the total number of lower-level LeafNodes to which it is connected.

13. The method according to any one of claims 1 to 8, wherein the intermediate page records the total number of the lower intermediate pages to which it is connected.

14. The method according to any one of claims 1 to 8, wherein the intermediate page records the total number of the lower-level leaf pages to which it is connected.

15. The method of any one of claims 1 to 8, wherein, in the case where the intermediate node includes a compressed infix, the compressed infix splits and merges during the stretching / shrinking process.

16. The method of any one of claims 1 to 8, wherein, in the case where the leaf node contains a compressed suffix, the compressed suffix splits and merges during the expansion / contraction process.

17. A computer device, comprising: processor; And a memory containing a program, wherein, when the processor executes the program, the method of any one of claims 1-14 is performed.