tests for eip-158 account removal and storage value deletions; there is one edge case left to test where we remove 1 account when only two exist such that the remaining account is moved up and replaces the root branch node

This commit is contained in:
Ian Norden 2020-05-17 23:04:31 -05:00
parent e37ce73971
commit e3b6d3df1c
4 changed files with 703 additions and 256 deletions

View File

@ -77,9 +77,9 @@ func (sdb *builder) buildStateDiffWithIntermediateStateNodes(args Args, params P
return StateDiff{}, fmt.Errorf("error collecting createdAndUpdatedNodes: %v", err)
}
// collect a slice of all the intermediate nodes that existed at A but don't at B
// collect a slice of all the nodes that existed at a path in A that doesn't exist in B
// a map of their leafkey to all the accounts that were touched and exist at A
deletedIntermediateNodes, diffAccountsAtA, err := sdb.deletedOrUpdatedState(oldTrie.NodeIterator([]byte{}), newTrie.NodeIterator([]byte{}), diffPathsAtB)
deletedNodes, diffAccountsAtA, err := sdb.deletedOrUpdatedState(oldTrie.NodeIterator([]byte{}), newTrie.NodeIterator([]byte{}), diffPathsAtB)
if err != nil {
return StateDiff{}, fmt.Errorf("error collecting deletedOrUpdatedNodes: %v", err)
}
@ -104,17 +104,12 @@ func (sdb *builder) buildStateDiffWithIntermediateStateNodes(args Args, params P
if err != nil {
return StateDiff{}, fmt.Errorf("error building diff for created accounts: %v", err)
}
// build the diff nodes for deleted accounts
deletedAccounts, err := sdb.buildAccountDeletions(diffAccountsAtA)
if err != nil {
return StateDiff{}, fmt.Errorf("error building diff for deleted accounts: %v", err)
}
// assemble all of the nodes into the statediff object, including the intermediate nodes
return StateDiff{
BlockNumber: args.BlockNumber,
BlockHash: args.BlockHash,
Nodes: append(append(append(append(updatedAccounts, createdAccounts...), deletedAccounts...), createdOrUpdatedIntermediateNodes...), deletedIntermediateNodes...),
Nodes: append(append(append(updatedAccounts, createdAccounts...), createdOrUpdatedIntermediateNodes...), deletedNodes...),
}, nil
}
@ -298,10 +293,10 @@ func (sdb *builder) createdAndUpdatedState(a, b trie.NodeIterator) ([]StateNode,
return createdOrUpdatedIntermediateNodes, diffAcountsAtB, diffPathsAtB, nil
}
// deletedOrUpdatedState returns a slice of all the intermediate nodes that exist at A but not at B
// a mapping of their leafkeys to all the accounts that exist in a different state at A than B
// deletedOrUpdatedState returns a slice of all the nodes that exist at A but not at B
// and a mapping of their leafkeys to all the accounts that exist in a different state at A than B
func (sdb *builder) deletedOrUpdatedState(a, b trie.NodeIterator, diffPathsAtB map[string]bool) ([]StateNode, AccountMap, error) {
deletedIntermediateNodes := make([]StateNode, 0)
deletedNodes := make([]StateNode, 0)
diffAccountAtA := make(AccountMap)
it, _ := trie.NewDifferenceIterator(b, a)
for it.Next(true) {
@ -314,6 +309,16 @@ func (sdb *builder) deletedOrUpdatedState(a, b trie.NodeIterator, diffPathsAtB m
}
nodePath := make([]byte, len(it.Path()))
copy(nodePath, it.Path())
// if this nodePath did not show up in diffPathsAtB
// that means the node at this path was deleted (or moved) in B
// emit an empty "removed" diff to signify as such
if _, ok := diffPathsAtB[common.Bytes2Hex(nodePath)]; !ok {
deletedNodes = append(deletedNodes, StateNode{
NodeType: Removed,
Path: nodePath,
NodeValue: []byte{},
})
}
node, err := sdb.stateCache.TrieDB().Node(it.Hash())
if err != nil {
return nil, nil, err
@ -345,21 +350,12 @@ func (sdb *builder) deletedOrUpdatedState(a, b trie.NodeIterator, diffPathsAtB m
Account: &account,
}
case Extension, Branch:
// if this nodePath did not show up in diffPathsAtB
// that means the node at this path was deleted in B
// emit an empty "removed" diff to signify as such
if _, ok := diffPathsAtB[common.Bytes2Hex(nodePath)]; !ok {
deletedIntermediateNodes = append(deletedIntermediateNodes, StateNode{
NodeType: Removed,
Path: nodePath,
NodeValue: []byte{},
})
}
// fall through, we did everything we need to do with these node types
default:
return nil, nil, fmt.Errorf("unexpected node type %s", ty)
}
}
return deletedIntermediateNodes, diffAccountAtA, nil
return deletedNodes, diffAccountAtA, nil
}
// buildAccountUpdates uses the account diffs maps for A => B and B => A and the known intersection of their leafkeys
@ -425,7 +421,6 @@ func (sdb *builder) buildAccountDeletions(accounts AccountMap) ([]StateNode, err
accountDiffs = append(accountDiffs, StateNode{
NodeType: Removed,
Path: val.Path,
LeafKey: val.LeafKey,
NodeValue: []byte{},
})
}
@ -622,7 +617,6 @@ func (sdb *builder) deletedOrUpdatedStorage(a, b trie.NodeIterator, diffPathsAtB
NodeType: Removed,
Path: nodePath,
NodeValue: []byte{},
LeafKey: leafKey,
})
}
case Extension, Branch:

File diff suppressed because it is too large Load Diff

View File

@ -32,8 +32,6 @@ import (
// the returned hash chain is ordered head->parent.
func MakeChain(n int, parent *types.Block) ([]*types.Block, *core.BlockChain) {
config := params.TestChainConfig
config.EIP158Block = big.NewInt(2)
config.ByzantiumBlock = big.NewInt(2)
blocks, _ := core.GenerateChain(config, parent, ethash.NewFaker(), Testdb, n, testChainGen)
chain, _ := core.NewBlockChain(Testdb, nil, params.TestChainConfig, ethash.NewFaker(), vm.Config{}, nil)
return blocks, chain
@ -48,8 +46,8 @@ func testChainGen(i int, block *core.BlockGen) {
block.AddTx(tx)
case 1:
// In block 2, the test bank sends some more ether to account #1.
// account1Addr passes it on to account #2.
// account1Addr creates a test contract.
// Account1Addr passes it on to account #2.
// Account1Addr creates a test contract.
tx1, _ := types.SignTx(types.NewTransaction(block.TxNonce(TestBankAddress), Account1Addr, big.NewInt(1000), params.TxGas, nil, nil), signer, TestBankKey)
nonce := block.TxNonce(Account1Addr)
tx2, _ := types.SignTx(types.NewTransaction(nonce, Account2Addr, big.NewInt(1000), params.TxGas, nil, nil), signer, Account1Key)
@ -60,40 +58,47 @@ func testChainGen(i int, block *core.BlockGen) {
block.AddTx(tx2)
block.AddTx(tx3)
case 2:
// Block 3 has a single tx from the bankAccount to the contract, that transfers no value, that is mined by account2
// Block 3 has a single tx from the bankAccount to the contract, that transfers no value
// Block 3 is mined by Account2Addr
block.SetCoinbase(Account2Addr)
//get function: 60cd2685
//put function: c16431b9
//close function: 43d726d6
data := common.Hex2Bytes("C16431B900000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003")
tx, _ := types.SignTx(types.NewTransaction(block.TxNonce(TestBankAddress), ContractAddr, big.NewInt(0), 100000, nil, data), signer, TestBankKey)
block.AddTx(tx)
case 3:
// Block 4 has two more txs from the bankAccount to the contract, that transfer no value
// Block is mined by new Account3Addr
block.SetCoinbase(Account3Addr)
data1 := common.Hex2Bytes("C16431B900000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000005")
data2 := common.Hex2Bytes("C16431B900000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000002")
// Block 4 has three txs from bankAccount to the contract, that transfer no value
// Two set the two original slot positions to 0 and one sets another position to a new value
// Block 4 is mined by Account2Addr
block.SetCoinbase(Account2Addr)
data1 := common.Hex2Bytes("C16431B900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000")
data2 := common.Hex2Bytes("C16431B900000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000")
data3 := common.Hex2Bytes("C16431B900000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000009")
nonce := block.TxNonce(TestBankAddress)
tx1, _ := types.SignTx(types.NewTransaction(nonce, ContractAddr, big.NewInt(0), 100000, nil, data1), signer, TestBankKey)
nonce++
tx2, _ := types.SignTx(types.NewTransaction(nonce, ContractAddr, big.NewInt(0), 100000, nil, data2), signer, TestBankKey)
block.AddTx(tx1)
block.AddTx(tx2)
case 4:
// Block 5 has two txs from Account3Addr to the contract, that transfer no value and set slot positions to 0
// Account3Addr then creates a new contract
// Block is mined by Account2Addr
block.SetCoinbase(Account2Addr)
data1 := common.Hex2Bytes("C16431B900000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000")
data2 := common.Hex2Bytes("C16431B900000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000")
nonce := block.TxNonce(Account3Addr)
tx1, _ := types.SignTx(types.NewTransaction(nonce, ContractAddr, big.NewInt(0), 100000, nil, data1), signer, Account3Key)
nonce++
tx2, _ := types.SignTx(types.NewTransaction(nonce, ContractAddr, big.NewInt(0), 100000, nil, data2), signer, Account3Key)
tx3, _ := types.SignTx(types.NewTransaction(nonce, ContractAddr, big.NewInt(0), 100000, nil, data3), signer, TestBankKey)
block.AddTx(tx1)
block.AddTx(tx2)
block.AddTx(tx3)
case 4:
// Block 5 has one tx from bankAccount to the contract, that transfers no value
// It sets the remaining storage value to zero
// Block 5 is mined by Account1Addr
block.SetCoinbase(Account1Addr)
data := common.Hex2Bytes("C16431B900000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000")
nonce := block.TxNonce(TestBankAddress)
tx, _ := types.SignTx(types.NewTransaction(nonce, ContractAddr, big.NewInt(0), 100000, nil, data), signer, TestBankKey)
block.AddTx(tx)
case 5:
// Block 6 has a tx which creates a contract with leafkey 2f30668e69d30b6fc1609db5447c101e40dda113ac28be157d20bb61da8e5861
// Block 6 has a tx from Account1Key which self-destructs the contract, it transfers no value
// Block 6 is mined by Account2Addr
block.SetCoinbase(Account2Addr)
data := common.Hex2Bytes("43D726D6")
tx, _ := types.SignTx(types.NewTransaction(block.TxNonce(Account1Addr), ContractAddr, big.NewInt(0), 100000, nil, data), signer, Account1Key)
block.AddTx(tx)
}
}

View File

@ -59,10 +59,8 @@ var (
Account1Key, _ = crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a")
Account2Key, _ = crypto.HexToECDSA("49a7b37aa6f6645917e7b807e9d1c00d4fa71f18343b0d4122a4d2df64dd6fee")
Account3Key, _ = crypto.HexToECDSA("c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470")
Account1Addr = crypto.PubkeyToAddress(Account1Key.PublicKey) //0x703c4b2bD70c169f5717101CaeE543299Fc946C7
Account2Addr = crypto.PubkeyToAddress(Account2Key.PublicKey) //0x0D3ab14BBaD3D99F4203bd7a11aCB94882050E7e
Account3Addr = crypto.PubkeyToAddress(Account3Key.PublicKey) //0x0D3ab14BBaD3D99F4203bd7a11aCB94882050E7e
Account1LeafKey = AddressToLeafKey(Account1Addr)
Account2LeafKey = AddressToLeafKey(Account2Addr)
ContractCode = common.Hex2Bytes("608060405234801561001057600080fd5b50336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506040518060200160405280600160ff16815250600190600161007492919061007a565b506100e4565b82606481019282156100ae579160200282015b828111156100ad578251829060ff1690559160200191906001019061008d565b5b5090506100bb91906100bf565b5090565b6100e191905b808211156100dd5760008160009055506001016100c5565b5090565b90565b6101ca806100f36000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c806343d726d61461003b578063c16431b914610045575b600080fd5b61004361007d565b005b61007b6004803603604081101561005b57600080fd5b81019080803590602001909291908035906020019092919050505061015c565b005b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610122576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260228152602001806101746022913960400191505060405180910390fd5b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16ff5b806001836064811061016a57fe5b0181905550505056fe4f6e6c79206f776e65722063616e2063616c6c20746869732066756e6374696f6e2ea265627a7a72305820e3747183708fb6bff3f6f7a80fb57dcc1c19f83f9cb25457a3ed5c0424bde66864736f6c634300050a0032")
@ -70,8 +68,4 @@ var (
EmptyRootNode, _ = rlp.EncodeToBytes([]byte{})
EmptyContractRoot = crypto.Keccak256Hash(EmptyRootNode)
Nonce0 = uint64(0)
Nonce1 = uint64(1)
Nonce2 = uint64(2)
Nonce3 = uint64(3)
)