3109 lines
99 KiB
Go
3109 lines
99 KiB
Go
|
// Copyright 2019 The go-ethereum Authors
|
||
|
// This file is part of the go-ethereum library.
|
||
|
//
|
||
|
// The go-ethereum library is free software: you can redistribute it and/or modify
|
||
|
// it under the terms of the GNU Lesser General Public License as published by
|
||
|
// the Free Software Foundation, either version 3 of the License, or
|
||
|
// (at your option) any later version.
|
||
|
//
|
||
|
// The go-ethereum library is distributed in the hope that it will be useful,
|
||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
// GNU Lesser General Public License for more details.
|
||
|
//
|
||
|
// You should have received a copy of the GNU Lesser General Public License
|
||
|
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||
|
|
||
|
package statediff_test
|
||
|
|
||
|
import (
|
||
|
"bytes"
|
||
|
"encoding/json"
|
||
|
"fmt"
|
||
|
"math/big"
|
||
|
"os"
|
||
|
"sort"
|
||
|
"testing"
|
||
|
|
||
|
ipld2 "github.com/ethereum/go-ethereum/statediff/indexer/ipld"
|
||
|
"github.com/ethereum/go-ethereum/statediff/indexer/shared"
|
||
|
|
||
|
types2 "github.com/ethereum/go-ethereum/statediff/types"
|
||
|
|
||
|
"github.com/ethereum/go-ethereum/common"
|
||
|
"github.com/ethereum/go-ethereum/core/types"
|
||
|
"github.com/ethereum/go-ethereum/crypto"
|
||
|
"github.com/ethereum/go-ethereum/rlp"
|
||
|
"github.com/ethereum/go-ethereum/statediff"
|
||
|
"github.com/ethereum/go-ethereum/statediff/test_helpers"
|
||
|
)
|
||
|
|
||
|
var (
|
||
|
contractLeafKey []byte
|
||
|
emptyDiffs = make([]types2.StateLeafNode, 0)
|
||
|
emptyStorage = make([]types2.StorageLeafNode, 0)
|
||
|
block0, block1, block2, block3, block4, block5, block6 *types.Block
|
||
|
builder statediff.Builder
|
||
|
minerAddress = common.HexToAddress("0x0")
|
||
|
minerLeafKey = test_helpers.AddressToLeafKey(minerAddress)
|
||
|
|
||
|
slot0 = common.BigToHash(big.NewInt(0))
|
||
|
slot1 = common.BigToHash(big.NewInt(1))
|
||
|
slot2 = common.BigToHash(big.NewInt(2))
|
||
|
slot3 = common.BigToHash(big.NewInt(3))
|
||
|
|
||
|
slot0StorageKey = crypto.Keccak256Hash(slot0[:])
|
||
|
slot1StorageKey = crypto.Keccak256Hash(slot1[:])
|
||
|
slot2StorageKey = crypto.Keccak256Hash(slot2[:])
|
||
|
slot3StorageKey = crypto.Keccak256Hash(slot3[:])
|
||
|
|
||
|
slot0StorageValue = common.Hex2Bytes("94703c4b2bd70c169f5717101caee543299fc946c7") // prefixed AccountAddr1
|
||
|
slot1StorageValue = common.Hex2Bytes("01")
|
||
|
slot2StorageValue = common.Hex2Bytes("09")
|
||
|
slot3StorageValue = common.Hex2Bytes("03")
|
||
|
|
||
|
slot0StorageLeafNode, _ = rlp.EncodeToBytes(&[]interface{}{
|
||
|
common.Hex2Bytes("390decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563"),
|
||
|
slot0StorageValue,
|
||
|
})
|
||
|
slot1StorageLeafNode, _ = rlp.EncodeToBytes(&[]interface{}{
|
||
|
common.Hex2Bytes("310e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6"),
|
||
|
slot1StorageValue,
|
||
|
})
|
||
|
slot2StorageLeafNode, _ = rlp.EncodeToBytes(&[]interface{}{
|
||
|
common.Hex2Bytes("305787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace"),
|
||
|
slot2StorageValue,
|
||
|
})
|
||
|
slot3StorageLeafNode, _ = rlp.EncodeToBytes(&[]interface{}{
|
||
|
common.Hex2Bytes("32575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b"),
|
||
|
slot3StorageValue,
|
||
|
})
|
||
|
contractAccountAtBlock2 = &types.StateAccount{
|
||
|
Nonce: 1,
|
||
|
Balance: big.NewInt(0),
|
||
|
CodeHash: common.HexToHash("0xaaea5efba4fd7b45d7ec03918ac5d8b31aa93b48986af0e6b591f0f087c80127").Bytes(),
|
||
|
Root: crypto.Keccak256Hash(block2StorageBranchRootNode),
|
||
|
}
|
||
|
contractAccountAtBlock2RLP, _ = rlp.EncodeToBytes(contractAccountAtBlock2)
|
||
|
contractAccountAtBlock2LeafNode, _ = rlp.EncodeToBytes(&[]interface{}{
|
||
|
common.Hex2Bytes("3114658a74d9cc9f7acf2c5cd696c3494d7c344d78bfec3add0d91ec4e8d1c45"),
|
||
|
contractAccountAtBlock2RLP,
|
||
|
})
|
||
|
contractAccountAtBlock3 = &types.StateAccount{
|
||
|
Nonce: 1,
|
||
|
Balance: big.NewInt(0),
|
||
|
CodeHash: common.HexToHash("0xaaea5efba4fd7b45d7ec03918ac5d8b31aa93b48986af0e6b591f0f087c80127").Bytes(),
|
||
|
Root: crypto.Keccak256Hash(block3StorageBranchRootNode),
|
||
|
}
|
||
|
contractAccountAtBlock3RLP, _ = rlp.EncodeToBytes(contractAccountAtBlock3)
|
||
|
contractAccountAtBlock3LeafNode, _ = rlp.EncodeToBytes(&[]interface{}{
|
||
|
common.Hex2Bytes("3114658a74d9cc9f7acf2c5cd696c3494d7c344d78bfec3add0d91ec4e8d1c45"),
|
||
|
contractAccountAtBlock3RLP,
|
||
|
})
|
||
|
contractAccountAtBlock4 = &types.StateAccount{
|
||
|
Nonce: 1,
|
||
|
Balance: big.NewInt(0),
|
||
|
CodeHash: common.HexToHash("0xaaea5efba4fd7b45d7ec03918ac5d8b31aa93b48986af0e6b591f0f087c80127").Bytes(),
|
||
|
Root: crypto.Keccak256Hash(block4StorageBranchRootNode),
|
||
|
}
|
||
|
contractAccountAtBlock4RLP, _ = rlp.EncodeToBytes(contractAccountAtBlock4)
|
||
|
contractAccountAtBlock4LeafNode, _ = rlp.EncodeToBytes(&[]interface{}{
|
||
|
common.Hex2Bytes("3114658a74d9cc9f7acf2c5cd696c3494d7c344d78bfec3add0d91ec4e8d1c45"),
|
||
|
contractAccountAtBlock4RLP,
|
||
|
})
|
||
|
contractAccountAtBlock5 = &types.StateAccount{
|
||
|
Nonce: 1,
|
||
|
Balance: big.NewInt(0),
|
||
|
CodeHash: common.HexToHash("0xaaea5efba4fd7b45d7ec03918ac5d8b31aa93b48986af0e6b591f0f087c80127").Bytes(),
|
||
|
Root: crypto.Keccak256Hash(block5StorageBranchRootNode),
|
||
|
}
|
||
|
contractAccountAtBlock5RLP, _ = rlp.EncodeToBytes(contractAccountAtBlock5)
|
||
|
contractAccountAtBlock5LeafNode, _ = rlp.EncodeToBytes(&[]interface{}{
|
||
|
common.Hex2Bytes("3114658a74d9cc9f7acf2c5cd696c3494d7c344d78bfec3add0d91ec4e8d1c45"),
|
||
|
contractAccountAtBlock5RLP,
|
||
|
})
|
||
|
minerAccountAtBlock1 = &types.StateAccount{
|
||
|
Nonce: 0,
|
||
|
Balance: big.NewInt(2000002625000000000),
|
||
|
CodeHash: test_helpers.NullCodeHash.Bytes(),
|
||
|
Root: test_helpers.EmptyContractRoot,
|
||
|
}
|
||
|
minerAccountAtBlock1RLP, _ = rlp.EncodeToBytes(minerAccountAtBlock1)
|
||
|
minerAccountAtBlock1LeafNode, _ = rlp.EncodeToBytes(&[]interface{}{
|
||
|
common.Hex2Bytes("3380c7b7ae81a58eb98d9c78de4a1fd7fd9535fc953ed2be602daaa41767312a"),
|
||
|
minerAccountAtBlock1RLP,
|
||
|
})
|
||
|
minerAccountAtBlock2 = &types.StateAccount{
|
||
|
Nonce: 0,
|
||
|
Balance: big.NewInt(4000111203461610525),
|
||
|
CodeHash: test_helpers.NullCodeHash.Bytes(),
|
||
|
Root: test_helpers.EmptyContractRoot,
|
||
|
}
|
||
|
minerAccountAtBlock2RLP, _ = rlp.EncodeToBytes(minerAccountAtBlock2)
|
||
|
minerAccountAtBlock2LeafNode, _ = rlp.EncodeToBytes(&[]interface{}{
|
||
|
common.Hex2Bytes("3380c7b7ae81a58eb98d9c78de4a1fd7fd9535fc953ed2be602daaa41767312a"),
|
||
|
minerAccountAtBlock2RLP,
|
||
|
})
|
||
|
|
||
|
account1AtBlock1 = &types.StateAccount{
|
||
|
Nonce: 0,
|
||
|
Balance: test_helpers.Block1Account1Balance,
|
||
|
CodeHash: test_helpers.NullCodeHash.Bytes(),
|
||
|
Root: test_helpers.EmptyContractRoot,
|
||
|
}
|
||
|
account1AtBlock1RLP, _ = rlp.EncodeToBytes(account1AtBlock1)
|
||
|
account1AtBlock1LeafNode, _ = rlp.EncodeToBytes(&[]interface{}{
|
||
|
common.Hex2Bytes("3926db69aaced518e9b9f0f434a473e7174109c943548bb8f23be41ca76d9ad2"),
|
||
|
account1AtBlock1RLP,
|
||
|
})
|
||
|
account1AtBlock2 = &types.StateAccount{
|
||
|
Nonce: 2,
|
||
|
Balance: big.NewInt(999555797000009000),
|
||
|
CodeHash: test_helpers.NullCodeHash.Bytes(),
|
||
|
Root: test_helpers.EmptyContractRoot,
|
||
|
}
|
||
|
account1AtBlock2RLP, _ = rlp.EncodeToBytes(account1AtBlock2)
|
||
|
account1AtBlock2LeafNode, _ = rlp.EncodeToBytes(&[]interface{}{
|
||
|
common.Hex2Bytes("3926db69aaced518e9b9f0f434a473e7174109c943548bb8f23be41ca76d9ad2"),
|
||
|
account1AtBlock2RLP,
|
||
|
})
|
||
|
account1AtBlock5 = &types.StateAccount{
|
||
|
Nonce: 2,
|
||
|
Balance: big.NewInt(2999586469962854280),
|
||
|
CodeHash: test_helpers.NullCodeHash.Bytes(),
|
||
|
Root: test_helpers.EmptyContractRoot,
|
||
|
}
|
||
|
account1AtBlock5RLP, _ = rlp.EncodeToBytes(account1AtBlock5)
|
||
|
account1AtBlock5LeafNode, _ = rlp.EncodeToBytes(&[]interface{}{
|
||
|
common.Hex2Bytes("3926db69aaced518e9b9f0f434a473e7174109c943548bb8f23be41ca76d9ad2"),
|
||
|
account1AtBlock5RLP,
|
||
|
})
|
||
|
account1AtBlock6 = &types.StateAccount{
|
||
|
Nonce: 3,
|
||
|
Balance: big.NewInt(2999557977962854280),
|
||
|
CodeHash: test_helpers.NullCodeHash.Bytes(),
|
||
|
Root: test_helpers.EmptyContractRoot,
|
||
|
}
|
||
|
account1AtBlock6RLP, _ = rlp.EncodeToBytes(account1AtBlock6)
|
||
|
account1AtBlock6LeafNode, _ = rlp.EncodeToBytes(&[]interface{}{
|
||
|
common.Hex2Bytes("3926db69aaced518e9b9f0f434a473e7174109c943548bb8f23be41ca76d9ad2"),
|
||
|
account1AtBlock6RLP,
|
||
|
})
|
||
|
account2AtBlock2 = &types.StateAccount{
|
||
|
Nonce: 0,
|
||
|
Balance: big.NewInt(1000),
|
||
|
CodeHash: test_helpers.NullCodeHash.Bytes(),
|
||
|
Root: test_helpers.EmptyContractRoot,
|
||
|
}
|
||
|
account2AtBlock2RLP, _ = rlp.EncodeToBytes(account2AtBlock2)
|
||
|
account2AtBlock2LeafNode, _ = rlp.EncodeToBytes(&[]interface{}{
|
||
|
common.Hex2Bytes("3957f3e2f04a0764c3a0491b175f69926da61efbcc8f61fa1455fd2d2b4cdd45"),
|
||
|
account2AtBlock2RLP,
|
||
|
})
|
||
|
account2AtBlock3 = &types.StateAccount{
|
||
|
Nonce: 0,
|
||
|
Balance: big.NewInt(2000013574009435976),
|
||
|
CodeHash: test_helpers.NullCodeHash.Bytes(),
|
||
|
Root: test_helpers.EmptyContractRoot,
|
||
|
}
|
||
|
account2AtBlock3RLP, _ = rlp.EncodeToBytes(account2AtBlock3)
|
||
|
account2AtBlock3LeafNode, _ = rlp.EncodeToBytes(&[]interface{}{
|
||
|
common.Hex2Bytes("3957f3e2f04a0764c3a0491b175f69926da61efbcc8f61fa1455fd2d2b4cdd45"),
|
||
|
account2AtBlock3RLP,
|
||
|
})
|
||
|
account2AtBlock4 = &types.StateAccount{
|
||
|
Nonce: 0,
|
||
|
Balance: big.NewInt(4000048088163070348),
|
||
|
CodeHash: test_helpers.NullCodeHash.Bytes(),
|
||
|
Root: test_helpers.EmptyContractRoot,
|
||
|
}
|
||
|
account2AtBlock4RLP, _ = rlp.EncodeToBytes(account2AtBlock4)
|
||
|
account2AtBlock4LeafNode, _ = rlp.EncodeToBytes(&[]interface{}{
|
||
|
common.Hex2Bytes("3957f3e2f04a0764c3a0491b175f69926da61efbcc8f61fa1455fd2d2b4cdd45"),
|
||
|
account2AtBlock4RLP,
|
||
|
})
|
||
|
account2AtBlock6 = &types.StateAccount{
|
||
|
Nonce: 0,
|
||
|
Balance: big.NewInt(6000063258066544204),
|
||
|
CodeHash: test_helpers.NullCodeHash.Bytes(),
|
||
|
Root: test_helpers.EmptyContractRoot,
|
||
|
}
|
||
|
account2AtBlock6RLP, _ = rlp.EncodeToBytes(account2AtBlock6)
|
||
|
account2AtBlock6LeafNode, _ = rlp.EncodeToBytes(&[]interface{}{
|
||
|
common.Hex2Bytes("3957f3e2f04a0764c3a0491b175f69926da61efbcc8f61fa1455fd2d2b4cdd45"),
|
||
|
account2AtBlock6RLP,
|
||
|
})
|
||
|
bankAccountAtBlock0 = &types.StateAccount{
|
||
|
Nonce: 0,
|
||
|
Balance: big.NewInt(test_helpers.TestBankFunds.Int64()),
|
||
|
CodeHash: test_helpers.NullCodeHash.Bytes(),
|
||
|
Root: test_helpers.EmptyContractRoot,
|
||
|
}
|
||
|
bankAccountAtBlock0RLP, _ = rlp.EncodeToBytes(bankAccountAtBlock0)
|
||
|
bankAccountAtBlock0LeafNode, _ = rlp.EncodeToBytes(&[]interface{}{
|
||
|
common.Hex2Bytes("2000bf49f440a1cd0527e4d06e2765654c0f56452257516d793a9b8d604dcfdf2a"),
|
||
|
bankAccountAtBlock0RLP,
|
||
|
})
|
||
|
|
||
|
block1BankBalance = big.NewInt(test_helpers.TestBankFunds.Int64() - test_helpers.BalanceChange10000 - test_helpers.GasFees)
|
||
|
bankAccountAtBlock1 = &types.StateAccount{
|
||
|
Nonce: 1,
|
||
|
Balance: block1BankBalance,
|
||
|
CodeHash: test_helpers.NullCodeHash.Bytes(),
|
||
|
Root: test_helpers.EmptyContractRoot,
|
||
|
}
|
||
|
bankAccountAtBlock1RLP, _ = rlp.EncodeToBytes(bankAccountAtBlock1)
|
||
|
bankAccountAtBlock1LeafNode, _ = rlp.EncodeToBytes(&[]interface{}{
|
||
|
common.Hex2Bytes("30bf49f440a1cd0527e4d06e2765654c0f56452257516d793a9b8d604dcfdf2a"),
|
||
|
bankAccountAtBlock1RLP,
|
||
|
})
|
||
|
|
||
|
block2BankBalance = block1BankBalance.Int64() - test_helpers.BalanceChange1Ether - test_helpers.GasFees
|
||
|
bankAccountAtBlock2 = &types.StateAccount{
|
||
|
Nonce: 2,
|
||
|
Balance: big.NewInt(block2BankBalance),
|
||
|
CodeHash: test_helpers.NullCodeHash.Bytes(),
|
||
|
Root: test_helpers.EmptyContractRoot,
|
||
|
}
|
||
|
bankAccountAtBlock2RLP, _ = rlp.EncodeToBytes(bankAccountAtBlock2)
|
||
|
bankAccountAtBlock2LeafNode, _ = rlp.EncodeToBytes(&[]interface{}{
|
||
|
common.Hex2Bytes("30bf49f440a1cd0527e4d06e2765654c0f56452257516d793a9b8d604dcfdf2a"),
|
||
|
bankAccountAtBlock2RLP,
|
||
|
})
|
||
|
bankAccountAtBlock3 = &types.StateAccount{
|
||
|
Nonce: 3,
|
||
|
Balance: big.NewInt(999914255999990000),
|
||
|
CodeHash: test_helpers.NullCodeHash.Bytes(),
|
||
|
Root: test_helpers.EmptyContractRoot,
|
||
|
}
|
||
|
bankAccountAtBlock3RLP, _ = rlp.EncodeToBytes(bankAccountAtBlock3)
|
||
|
bankAccountAtBlock3LeafNode, _ = rlp.EncodeToBytes(&[]interface{}{
|
||
|
common.Hex2Bytes("30bf49f440a1cd0527e4d06e2765654c0f56452257516d793a9b8d604dcfdf2a"),
|
||
|
bankAccountAtBlock3RLP,
|
||
|
})
|
||
|
bankAccountAtBlock4 = &types.StateAccount{
|
||
|
Nonce: 6,
|
||
|
Balance: big.NewInt(999826859999990000),
|
||
|
CodeHash: test_helpers.NullCodeHash.Bytes(),
|
||
|
Root: test_helpers.EmptyContractRoot,
|
||
|
}
|
||
|
bankAccountAtBlock4RLP, _ = rlp.EncodeToBytes(&bankAccountAtBlock4)
|
||
|
bankAccountAtBlock4LeafNode, _ = rlp.EncodeToBytes(&[]interface{}{
|
||
|
common.Hex2Bytes("30bf49f440a1cd0527e4d06e2765654c0f56452257516d793a9b8d604dcfdf2a"),
|
||
|
bankAccountAtBlock4RLP,
|
||
|
})
|
||
|
bankAccountAtBlock5 = &types.StateAccount{
|
||
|
Nonce: 8,
|
||
|
Balance: big.NewInt(999761283999990000),
|
||
|
CodeHash: test_helpers.NullCodeHash.Bytes(),
|
||
|
Root: test_helpers.EmptyContractRoot,
|
||
|
}
|
||
|
bankAccountAtBlock5RLP, _ = rlp.EncodeToBytes(bankAccountAtBlock5)
|
||
|
bankAccountAtBlock5LeafNode, _ = rlp.EncodeToBytes(&[]interface{}{
|
||
|
common.Hex2Bytes("30bf49f440a1cd0527e4d06e2765654c0f56452257516d793a9b8d604dcfdf2a"),
|
||
|
bankAccountAtBlock5RLP,
|
||
|
})
|
||
|
|
||
|
block1BranchRootNode, _ = rlp.EncodeToBytes(&[]interface{}{
|
||
|
crypto.Keccak256(bankAccountAtBlock1LeafNode),
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
crypto.Keccak256(minerAccountAtBlock1LeafNode),
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
crypto.Keccak256(account1AtBlock1LeafNode),
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
})
|
||
|
block2BranchRootNode, _ = rlp.EncodeToBytes(&[]interface{}{
|
||
|
crypto.Keccak256(bankAccountAtBlock2LeafNode),
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
crypto.Keccak256(minerAccountAtBlock2LeafNode),
|
||
|
crypto.Keccak256(contractAccountAtBlock2LeafNode),
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
crypto.Keccak256(account2AtBlock2LeafNode),
|
||
|
[]byte{},
|
||
|
crypto.Keccak256(account1AtBlock2LeafNode),
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
})
|
||
|
block3BranchRootNode, _ = rlp.EncodeToBytes(&[]interface{}{
|
||
|
crypto.Keccak256(bankAccountAtBlock3LeafNode),
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
crypto.Keccak256(minerAccountAtBlock2LeafNode),
|
||
|
crypto.Keccak256(contractAccountAtBlock3LeafNode),
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
crypto.Keccak256(account2AtBlock3LeafNode),
|
||
|
[]byte{},
|
||
|
crypto.Keccak256(account1AtBlock2LeafNode),
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
})
|
||
|
block4BranchRootNode, _ = rlp.EncodeToBytes(&[]interface{}{
|
||
|
crypto.Keccak256(bankAccountAtBlock4LeafNode),
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
crypto.Keccak256(minerAccountAtBlock2LeafNode),
|
||
|
crypto.Keccak256(contractAccountAtBlock4LeafNode),
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
crypto.Keccak256(account2AtBlock4LeafNode),
|
||
|
[]byte{},
|
||
|
crypto.Keccak256(account1AtBlock2LeafNode),
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
})
|
||
|
block5BranchRootNode, _ = rlp.EncodeToBytes(&[]interface{}{
|
||
|
crypto.Keccak256(bankAccountAtBlock5LeafNode),
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
crypto.Keccak256(minerAccountAtBlock2LeafNode),
|
||
|
crypto.Keccak256(contractAccountAtBlock5LeafNode),
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
crypto.Keccak256(account2AtBlock4LeafNode),
|
||
|
[]byte{},
|
||
|
crypto.Keccak256(account1AtBlock5LeafNode),
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
})
|
||
|
block6BranchRootNode, _ = rlp.EncodeToBytes(&[]interface{}{
|
||
|
crypto.Keccak256(bankAccountAtBlock5LeafNode),
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
crypto.Keccak256(minerAccountAtBlock2LeafNode),
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
crypto.Keccak256(account2AtBlock6LeafNode),
|
||
|
[]byte{},
|
||
|
crypto.Keccak256(account1AtBlock6LeafNode),
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
})
|
||
|
|
||
|
block2StorageBranchRootNode, _ = rlp.EncodeToBytes(&[]interface{}{
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
crypto.Keccak256(slot0StorageLeafNode),
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
crypto.Keccak256(slot1StorageLeafNode),
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
})
|
||
|
block3StorageBranchRootNode, _ = rlp.EncodeToBytes(&[]interface{}{
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
crypto.Keccak256(slot0StorageLeafNode),
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
crypto.Keccak256(slot1StorageLeafNode),
|
||
|
crypto.Keccak256(slot3StorageLeafNode),
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
})
|
||
|
block4StorageBranchRootNode, _ = rlp.EncodeToBytes(&[]interface{}{
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
crypto.Keccak256(slot0StorageLeafNode),
|
||
|
[]byte{},
|
||
|
crypto.Keccak256(slot2StorageLeafNode),
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
})
|
||
|
block5StorageBranchRootNode, _ = rlp.EncodeToBytes(&[]interface{}{
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
crypto.Keccak256(slot0StorageLeafNode),
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
crypto.Keccak256(slot3StorageLeafNode),
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
})
|
||
|
)
|
||
|
|
||
|
func init() {
|
||
|
if os.Getenv("MODE") != "statediff" {
|
||
|
fmt.Println("Skipping statediff test")
|
||
|
os.Exit(0)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func TestBuilder(t *testing.T) {
|
||
|
blocks, chain := test_helpers.MakeChain(3, test_helpers.Genesis, test_helpers.TestChainGen)
|
||
|
contractLeafKey = test_helpers.AddressToLeafKey(test_helpers.ContractAddr)
|
||
|
defer chain.Stop()
|
||
|
block0 = test_helpers.Genesis
|
||
|
block1 = blocks[0]
|
||
|
block2 = blocks[1]
|
||
|
block3 = blocks[2]
|
||
|
params := statediff.Params{}
|
||
|
builder = statediff.NewBuilder(chain.StateCache())
|
||
|
|
||
|
var tests = []struct {
|
||
|
name string
|
||
|
startingArguments statediff.Args
|
||
|
expected *types2.StateObject
|
||
|
}{
|
||
|
{
|
||
|
"testEmptyDiff",
|
||
|
statediff.Args{
|
||
|
OldStateRoot: block0.Root(),
|
||
|
NewStateRoot: block0.Root(),
|
||
|
BlockNumber: block0.Number(),
|
||
|
BlockHash: block0.Hash(),
|
||
|
},
|
||
|
&types2.StateObject{
|
||
|
BlockNumber: block0.Number(),
|
||
|
BlockHash: block0.Hash(),
|
||
|
Nodes: emptyDiffs,
|
||
|
},
|
||
|
},
|
||
|
{
|
||
|
"testBlock0",
|
||
|
//10000 transferred from testBankAddress to account1Addr
|
||
|
statediff.Args{
|
||
|
OldStateRoot: test_helpers.NullHash,
|
||
|
NewStateRoot: block0.Root(),
|
||
|
BlockNumber: block0.Number(),
|
||
|
BlockHash: block0.Hash(),
|
||
|
},
|
||
|
&types2.StateObject{
|
||
|
BlockNumber: block0.Number(),
|
||
|
BlockHash: block0.Hash(),
|
||
|
Nodes: []types2.StateLeafNode{
|
||
|
{
|
||
|
Removed: false,
|
||
|
AccountWrapper: struct {
|
||
|
Account *types.StateAccount
|
||
|
LeafKey []byte
|
||
|
CID string
|
||
|
}{
|
||
|
Account: bankAccountAtBlock0,
|
||
|
LeafKey: test_helpers.BankLeafKey,
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStateTrie, crypto.Keccak256(bankAccountAtBlock0LeafNode)).String()},
|
||
|
StorageDiff: emptyStorage,
|
||
|
},
|
||
|
},
|
||
|
IPLDs: []types2.IPLD{
|
||
|
{
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStateTrie, crypto.Keccak256(bankAccountAtBlock0LeafNode)).String(),
|
||
|
Content: bankAccountAtBlock0LeafNode,
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
{
|
||
|
"testBlock1",
|
||
|
//10000 transferred from testBankAddress to account1Addr
|
||
|
statediff.Args{
|
||
|
OldStateRoot: block0.Root(),
|
||
|
NewStateRoot: block1.Root(),
|
||
|
BlockNumber: block1.Number(),
|
||
|
BlockHash: block1.Hash(),
|
||
|
},
|
||
|
&types2.StateObject{
|
||
|
BlockNumber: block1.Number(),
|
||
|
BlockHash: block1.Hash(),
|
||
|
Nodes: []types2.StateLeafNode{
|
||
|
{
|
||
|
Removed: false,
|
||
|
AccountWrapper: struct {
|
||
|
Account *types.StateAccount
|
||
|
LeafKey []byte
|
||
|
CID string
|
||
|
}{
|
||
|
Account: bankAccountAtBlock1,
|
||
|
LeafKey: test_helpers.BankLeafKey,
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStateTrie, crypto.Keccak256(bankAccountAtBlock1LeafNode)).String()},
|
||
|
StorageDiff: emptyStorage,
|
||
|
},
|
||
|
{
|
||
|
Removed: false,
|
||
|
AccountWrapper: struct {
|
||
|
Account *types.StateAccount
|
||
|
LeafKey []byte
|
||
|
CID string
|
||
|
}{
|
||
|
Account: minerAccountAtBlock1,
|
||
|
LeafKey: minerLeafKey,
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStateTrie, crypto.Keccak256(minerAccountAtBlock1LeafNode)).String()},
|
||
|
StorageDiff: emptyStorage,
|
||
|
},
|
||
|
{
|
||
|
Removed: false,
|
||
|
AccountWrapper: struct {
|
||
|
Account *types.StateAccount
|
||
|
LeafKey []byte
|
||
|
CID string
|
||
|
}{
|
||
|
Account: account1AtBlock1,
|
||
|
LeafKey: test_helpers.Account1LeafKey,
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStateTrie, crypto.Keccak256(account1AtBlock1LeafNode)).String()},
|
||
|
StorageDiff: emptyStorage,
|
||
|
},
|
||
|
},
|
||
|
IPLDs: []types2.IPLD{
|
||
|
{
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStateTrie, crypto.Keccak256(block1BranchRootNode)).String(),
|
||
|
Content: block1BranchRootNode,
|
||
|
},
|
||
|
{
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStateTrie, crypto.Keccak256(bankAccountAtBlock1LeafNode)).String(),
|
||
|
Content: bankAccountAtBlock1LeafNode,
|
||
|
},
|
||
|
{
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStateTrie, crypto.Keccak256(minerAccountAtBlock1LeafNode)).String(),
|
||
|
Content: minerAccountAtBlock1LeafNode,
|
||
|
},
|
||
|
{
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStateTrie, crypto.Keccak256(account1AtBlock1LeafNode)).String(),
|
||
|
Content: account1AtBlock1LeafNode,
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
{
|
||
|
"testBlock2",
|
||
|
// 1000 transferred from testBankAddress to account1Addr
|
||
|
// 1000 transferred from account1Addr to account2Addr
|
||
|
// account1addr creates a new contract
|
||
|
statediff.Args{
|
||
|
OldStateRoot: block1.Root(),
|
||
|
NewStateRoot: block2.Root(),
|
||
|
BlockNumber: block2.Number(),
|
||
|
BlockHash: block2.Hash(),
|
||
|
},
|
||
|
&types2.StateObject{
|
||
|
BlockNumber: block2.Number(),
|
||
|
BlockHash: block2.Hash(),
|
||
|
Nodes: []types2.StateLeafNode{
|
||
|
{
|
||
|
Removed: false,
|
||
|
AccountWrapper: struct {
|
||
|
Account *types.StateAccount
|
||
|
LeafKey []byte
|
||
|
CID string
|
||
|
}{
|
||
|
Account: bankAccountAtBlock2,
|
||
|
LeafKey: test_helpers.BankLeafKey,
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStateTrie, crypto.Keccak256(bankAccountAtBlock2LeafNode)).String()},
|
||
|
StorageDiff: emptyStorage,
|
||
|
},
|
||
|
{
|
||
|
Removed: false,
|
||
|
AccountWrapper: struct {
|
||
|
Account *types.StateAccount
|
||
|
LeafKey []byte
|
||
|
CID string
|
||
|
}{
|
||
|
Account: minerAccountAtBlock2,
|
||
|
LeafKey: minerLeafKey,
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStateTrie, crypto.Keccak256(minerAccountAtBlock2LeafNode)).String()},
|
||
|
StorageDiff: emptyStorage,
|
||
|
},
|
||
|
{
|
||
|
Removed: false,
|
||
|
AccountWrapper: struct {
|
||
|
Account *types.StateAccount
|
||
|
LeafKey []byte
|
||
|
CID string
|
||
|
}{
|
||
|
Account: account1AtBlock2,
|
||
|
LeafKey: test_helpers.Account1LeafKey,
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStateTrie, crypto.Keccak256(account1AtBlock2LeafNode)).String()},
|
||
|
StorageDiff: emptyStorage,
|
||
|
},
|
||
|
{
|
||
|
Removed: false,
|
||
|
AccountWrapper: struct {
|
||
|
Account *types.StateAccount
|
||
|
LeafKey []byte
|
||
|
CID string
|
||
|
}{
|
||
|
Account: contractAccountAtBlock2,
|
||
|
LeafKey: contractLeafKey,
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStateTrie, crypto.Keccak256(contractAccountAtBlock2LeafNode)).String()},
|
||
|
StorageDiff: []types2.StorageLeafNode{
|
||
|
{
|
||
|
Removed: false,
|
||
|
Value: slot0StorageValue,
|
||
|
LeafKey: slot0StorageKey.Bytes(),
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStorageTrie, crypto.Keccak256(slot0StorageLeafNode)).String(),
|
||
|
},
|
||
|
{
|
||
|
Removed: false,
|
||
|
Value: slot1StorageValue,
|
||
|
LeafKey: slot1StorageKey.Bytes(),
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStorageTrie, crypto.Keccak256(slot1StorageLeafNode)).String(),
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
{
|
||
|
Removed: false,
|
||
|
AccountWrapper: struct {
|
||
|
Account *types.StateAccount
|
||
|
LeafKey []byte
|
||
|
CID string
|
||
|
}{
|
||
|
Account: account2AtBlock2,
|
||
|
LeafKey: test_helpers.Account2LeafKey,
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStateTrie, crypto.Keccak256(account2AtBlock2LeafNode)).String()},
|
||
|
StorageDiff: emptyStorage,
|
||
|
},
|
||
|
},
|
||
|
IPLDs: []types2.IPLD{
|
||
|
{
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.RawBinary, test_helpers.CodeHash.Bytes()).String(),
|
||
|
Content: test_helpers.ByteCodeAfterDeployment,
|
||
|
},
|
||
|
{
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStateTrie, crypto.Keccak256(block2BranchRootNode)).String(),
|
||
|
Content: block2BranchRootNode,
|
||
|
},
|
||
|
{
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStateTrie, crypto.Keccak256(bankAccountAtBlock2LeafNode)).String(),
|
||
|
Content: bankAccountAtBlock2LeafNode,
|
||
|
},
|
||
|
{
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStateTrie, crypto.Keccak256(minerAccountAtBlock2LeafNode)).String(),
|
||
|
Content: minerAccountAtBlock2LeafNode,
|
||
|
},
|
||
|
{
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStateTrie, crypto.Keccak256(account1AtBlock2LeafNode)).String(),
|
||
|
Content: account1AtBlock2LeafNode,
|
||
|
},
|
||
|
{
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStateTrie, crypto.Keccak256(contractAccountAtBlock2LeafNode)).String(),
|
||
|
Content: contractAccountAtBlock2LeafNode,
|
||
|
},
|
||
|
{
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStorageTrie, crypto.Keccak256(block2StorageBranchRootNode)).String(),
|
||
|
Content: block2StorageBranchRootNode,
|
||
|
},
|
||
|
{
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStorageTrie, crypto.Keccak256(slot0StorageLeafNode)).String(),
|
||
|
Content: slot0StorageLeafNode,
|
||
|
},
|
||
|
{
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStorageTrie, crypto.Keccak256(slot1StorageLeafNode)).String(),
|
||
|
Content: slot1StorageLeafNode,
|
||
|
},
|
||
|
{
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStateTrie, crypto.Keccak256(account2AtBlock2LeafNode)).String(),
|
||
|
Content: account2AtBlock2LeafNode,
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
{
|
||
|
"testBlock3",
|
||
|
//the contract's storage is changed
|
||
|
//and the block is mined by account 2
|
||
|
statediff.Args{
|
||
|
OldStateRoot: block2.Root(),
|
||
|
NewStateRoot: block3.Root(),
|
||
|
BlockNumber: block3.Number(),
|
||
|
BlockHash: block3.Hash(),
|
||
|
},
|
||
|
&types2.StateObject{
|
||
|
BlockNumber: block3.Number(),
|
||
|
BlockHash: block3.Hash(),
|
||
|
Nodes: []types2.StateLeafNode{
|
||
|
{
|
||
|
Removed: false,
|
||
|
AccountWrapper: struct {
|
||
|
Account *types.StateAccount
|
||
|
LeafKey []byte
|
||
|
CID string
|
||
|
}{
|
||
|
Account: bankAccountAtBlock3,
|
||
|
LeafKey: test_helpers.BankLeafKey,
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStateTrie, crypto.Keccak256(bankAccountAtBlock3LeafNode)).String()},
|
||
|
StorageDiff: emptyStorage,
|
||
|
},
|
||
|
{
|
||
|
Removed: false,
|
||
|
AccountWrapper: struct {
|
||
|
Account *types.StateAccount
|
||
|
LeafKey []byte
|
||
|
CID string
|
||
|
}{
|
||
|
Account: contractAccountAtBlock3,
|
||
|
LeafKey: contractLeafKey,
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStateTrie, crypto.Keccak256(contractAccountAtBlock3LeafNode)).String()},
|
||
|
StorageDiff: []types2.StorageLeafNode{
|
||
|
{
|
||
|
Removed: false,
|
||
|
Value: slot3StorageValue,
|
||
|
LeafKey: slot3StorageKey.Bytes(),
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStorageTrie, crypto.Keccak256(slot3StorageLeafNode)).String(),
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
{
|
||
|
Removed: false,
|
||
|
AccountWrapper: struct {
|
||
|
Account *types.StateAccount
|
||
|
LeafKey []byte
|
||
|
CID string
|
||
|
}{
|
||
|
Account: account2AtBlock3,
|
||
|
LeafKey: test_helpers.Account2LeafKey,
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStateTrie, crypto.Keccak256(account2AtBlock3LeafNode)).String()},
|
||
|
StorageDiff: emptyStorage,
|
||
|
},
|
||
|
},
|
||
|
IPLDs: []types2.IPLD{
|
||
|
{
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStateTrie, crypto.Keccak256(block3BranchRootNode)).String(),
|
||
|
Content: block3BranchRootNode,
|
||
|
},
|
||
|
{
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStateTrie, crypto.Keccak256(bankAccountAtBlock3LeafNode)).String(),
|
||
|
Content: bankAccountAtBlock3LeafNode,
|
||
|
},
|
||
|
{
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStateTrie, crypto.Keccak256(contractAccountAtBlock3LeafNode)).String(),
|
||
|
Content: contractAccountAtBlock3LeafNode,
|
||
|
},
|
||
|
{
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStorageTrie, crypto.Keccak256(block3StorageBranchRootNode)).String(),
|
||
|
Content: block3StorageBranchRootNode,
|
||
|
},
|
||
|
{
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStorageTrie, crypto.Keccak256(slot3StorageLeafNode)).String(),
|
||
|
Content: slot3StorageLeafNode,
|
||
|
},
|
||
|
{
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStateTrie, crypto.Keccak256(account2AtBlock3LeafNode)).String(),
|
||
|
Content: account2AtBlock3LeafNode,
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
}
|
||
|
|
||
|
for _, test := range tests {
|
||
|
diff, err := builder.BuildStateDiffObject(test.startingArguments, params)
|
||
|
if err != nil {
|
||
|
t.Error(err)
|
||
|
}
|
||
|
receivedStateDiffRlp, err := rlp.EncodeToBytes(&diff)
|
||
|
if err != nil {
|
||
|
t.Error(err)
|
||
|
}
|
||
|
expectedStateDiffRlp, err := rlp.EncodeToBytes(test.expected)
|
||
|
if err != nil {
|
||
|
t.Error(err)
|
||
|
}
|
||
|
sort.Slice(receivedStateDiffRlp, func(i, j int) bool { return receivedStateDiffRlp[i] < receivedStateDiffRlp[j] })
|
||
|
sort.Slice(expectedStateDiffRlp, func(i, j int) bool { return expectedStateDiffRlp[i] < expectedStateDiffRlp[j] })
|
||
|
if !bytes.Equal(receivedStateDiffRlp, expectedStateDiffRlp) {
|
||
|
actual, err := json.Marshal(diff)
|
||
|
if err != nil {
|
||
|
t.Error(err)
|
||
|
}
|
||
|
expected, err := json.Marshal(test.expected)
|
||
|
if err != nil {
|
||
|
t.Error(err)
|
||
|
}
|
||
|
t.Logf("Test failed: %s", test.name)
|
||
|
t.Errorf("actual state diff: %s\r\n\r\n\r\nexpected state diff: %s", actual, expected)
|
||
|
}
|
||
|
}
|
||
|
// Let's also confirm that our root state nodes form the state root hash in the headers
|
||
|
if !bytes.Equal(block0.Root().Bytes(), crypto.Keccak256(bankAccountAtBlock0LeafNode)) {
|
||
|
t.Errorf("block0 expected root %x does not match actual root %x", block0.Root().Bytes(), crypto.Keccak256(bankAccountAtBlock0LeafNode))
|
||
|
}
|
||
|
if !bytes.Equal(block1.Root().Bytes(), crypto.Keccak256(block1BranchRootNode)) {
|
||
|
t.Errorf("block1 expected root %x does not match actual root %x", block1.Root().Bytes(), crypto.Keccak256(block1BranchRootNode))
|
||
|
}
|
||
|
if !bytes.Equal(block2.Root().Bytes(), crypto.Keccak256(block2BranchRootNode)) {
|
||
|
t.Errorf("block2 expected root %x does not match actual root %x", block2.Root().Bytes(), crypto.Keccak256(block2BranchRootNode))
|
||
|
}
|
||
|
if !bytes.Equal(block3.Root().Bytes(), crypto.Keccak256(block3BranchRootNode)) {
|
||
|
t.Errorf("block3 expected root %x does not match actual root %x", block3.Root().Bytes(), crypto.Keccak256(block3BranchRootNode))
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func TestBuilderWithWatchedAddressList(t *testing.T) {
|
||
|
blocks, chain := test_helpers.MakeChain(3, test_helpers.Genesis, test_helpers.TestChainGen)
|
||
|
contractLeafKey = test_helpers.AddressToLeafKey(test_helpers.ContractAddr)
|
||
|
defer chain.Stop()
|
||
|
block0 = test_helpers.Genesis
|
||
|
block1 = blocks[0]
|
||
|
block2 = blocks[1]
|
||
|
block3 = blocks[2]
|
||
|
params := statediff.Params{
|
||
|
WatchedAddresses: []common.Address{test_helpers.Account1Addr, test_helpers.ContractAddr},
|
||
|
}
|
||
|
params.ComputeWatchedAddressesLeafPaths()
|
||
|
builder = statediff.NewBuilder(chain.StateCache())
|
||
|
|
||
|
var tests = []struct {
|
||
|
name string
|
||
|
startingArguments statediff.Args
|
||
|
expected *types2.StateObject
|
||
|
}{
|
||
|
{
|
||
|
"testEmptyDiff",
|
||
|
statediff.Args{
|
||
|
OldStateRoot: block0.Root(),
|
||
|
NewStateRoot: block0.Root(),
|
||
|
BlockNumber: block0.Number(),
|
||
|
BlockHash: block0.Hash(),
|
||
|
},
|
||
|
&types2.StateObject{
|
||
|
BlockNumber: block0.Number(),
|
||
|
BlockHash: block0.Hash(),
|
||
|
Nodes: emptyDiffs,
|
||
|
},
|
||
|
},
|
||
|
{
|
||
|
"testBlock0",
|
||
|
//10000 transferred from testBankAddress to account1Addr
|
||
|
statediff.Args{
|
||
|
OldStateRoot: test_helpers.NullHash,
|
||
|
NewStateRoot: block0.Root(),
|
||
|
BlockNumber: block0.Number(),
|
||
|
BlockHash: block0.Hash(),
|
||
|
},
|
||
|
&types2.StateObject{
|
||
|
BlockNumber: block0.Number(),
|
||
|
BlockHash: block0.Hash(),
|
||
|
Nodes: emptyDiffs,
|
||
|
},
|
||
|
},
|
||
|
{
|
||
|
"testBlock1",
|
||
|
//10000 transferred from testBankAddress to account1Addr
|
||
|
statediff.Args{
|
||
|
OldStateRoot: block0.Root(),
|
||
|
NewStateRoot: block1.Root(),
|
||
|
BlockNumber: block1.Number(),
|
||
|
BlockHash: block1.Hash(),
|
||
|
},
|
||
|
&types2.StateObject{
|
||
|
BlockNumber: block1.Number(),
|
||
|
BlockHash: block1.Hash(),
|
||
|
Nodes: []types2.StateLeafNode{
|
||
|
{
|
||
|
Removed: false,
|
||
|
AccountWrapper: struct {
|
||
|
Account *types.StateAccount
|
||
|
LeafKey []byte
|
||
|
CID string
|
||
|
}{
|
||
|
Account: account1AtBlock1,
|
||
|
LeafKey: test_helpers.Account1LeafKey,
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStateTrie, crypto.Keccak256(account1AtBlock1LeafNode)).String()},
|
||
|
StorageDiff: emptyStorage,
|
||
|
},
|
||
|
},
|
||
|
IPLDs: []types2.IPLD{
|
||
|
{
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStateTrie, crypto.Keccak256(block1BranchRootNode)).String(),
|
||
|
Content: block1BranchRootNode,
|
||
|
},
|
||
|
{
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStateTrie, crypto.Keccak256(account1AtBlock1LeafNode)).String(),
|
||
|
Content: account1AtBlock1LeafNode,
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
{
|
||
|
"testBlock2",
|
||
|
//1000 transferred from testBankAddress to account1Addr
|
||
|
//1000 transferred from account1Addr to account2Addr
|
||
|
statediff.Args{
|
||
|
OldStateRoot: block1.Root(),
|
||
|
NewStateRoot: block2.Root(),
|
||
|
BlockNumber: block2.Number(),
|
||
|
BlockHash: block2.Hash(),
|
||
|
},
|
||
|
&types2.StateObject{
|
||
|
BlockNumber: block2.Number(),
|
||
|
BlockHash: block2.Hash(),
|
||
|
Nodes: []types2.StateLeafNode{
|
||
|
{
|
||
|
Removed: false,
|
||
|
AccountWrapper: struct {
|
||
|
Account *types.StateAccount
|
||
|
LeafKey []byte
|
||
|
CID string
|
||
|
}{
|
||
|
Account: contractAccountAtBlock2,
|
||
|
LeafKey: contractLeafKey,
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStateTrie, crypto.Keccak256(contractAccountAtBlock2LeafNode)).String()},
|
||
|
StorageDiff: []types2.StorageLeafNode{
|
||
|
{
|
||
|
Removed: false,
|
||
|
Value: slot0StorageValue,
|
||
|
LeafKey: slot0StorageKey.Bytes(),
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStorageTrie, crypto.Keccak256(slot0StorageLeafNode)).String(),
|
||
|
},
|
||
|
{
|
||
|
Removed: false,
|
||
|
Value: slot1StorageValue,
|
||
|
LeafKey: slot1StorageKey.Bytes(),
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStorageTrie, crypto.Keccak256(slot1StorageLeafNode)).String(),
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
{
|
||
|
Removed: false,
|
||
|
AccountWrapper: struct {
|
||
|
Account *types.StateAccount
|
||
|
LeafKey []byte
|
||
|
CID string
|
||
|
}{
|
||
|
Account: account1AtBlock2,
|
||
|
LeafKey: test_helpers.Account1LeafKey,
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStateTrie, crypto.Keccak256(account1AtBlock2LeafNode)).String()},
|
||
|
StorageDiff: emptyStorage,
|
||
|
},
|
||
|
},
|
||
|
IPLDs: []types2.IPLD{
|
||
|
{
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.RawBinary, test_helpers.CodeHash.Bytes()).String(),
|
||
|
Content: test_helpers.ByteCodeAfterDeployment,
|
||
|
},
|
||
|
{
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStateTrie, crypto.Keccak256(block2BranchRootNode)).String(),
|
||
|
Content: block2BranchRootNode,
|
||
|
},
|
||
|
{
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStateTrie, crypto.Keccak256(contractAccountAtBlock2LeafNode)).String(),
|
||
|
Content: contractAccountAtBlock2LeafNode,
|
||
|
},
|
||
|
{
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStorageTrie, crypto.Keccak256(block2StorageBranchRootNode)).String(),
|
||
|
Content: block2StorageBranchRootNode,
|
||
|
},
|
||
|
{
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStorageTrie, crypto.Keccak256(slot0StorageLeafNode)).String(),
|
||
|
Content: slot0StorageLeafNode,
|
||
|
},
|
||
|
{
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStorageTrie, crypto.Keccak256(slot1StorageLeafNode)).String(),
|
||
|
Content: slot1StorageLeafNode,
|
||
|
},
|
||
|
{
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStateTrie, crypto.Keccak256(account1AtBlock2LeafNode)).String(),
|
||
|
Content: account1AtBlock2LeafNode,
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
{
|
||
|
"testBlock3",
|
||
|
//the contract's storage is changed
|
||
|
//and the block is mined by account 2
|
||
|
statediff.Args{
|
||
|
OldStateRoot: block2.Root(),
|
||
|
NewStateRoot: block3.Root(),
|
||
|
BlockNumber: block3.Number(),
|
||
|
BlockHash: block3.Hash(),
|
||
|
},
|
||
|
&types2.StateObject{
|
||
|
BlockNumber: block3.Number(),
|
||
|
BlockHash: block3.Hash(),
|
||
|
Nodes: []types2.StateLeafNode{
|
||
|
{
|
||
|
Removed: false,
|
||
|
AccountWrapper: struct {
|
||
|
Account *types.StateAccount
|
||
|
LeafKey []byte
|
||
|
CID string
|
||
|
}{
|
||
|
Account: contractAccountAtBlock3,
|
||
|
LeafKey: contractLeafKey,
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStateTrie, crypto.Keccak256(contractAccountAtBlock3LeafNode)).String()},
|
||
|
StorageDiff: []types2.StorageLeafNode{
|
||
|
{
|
||
|
Removed: false,
|
||
|
Value: slot3StorageValue,
|
||
|
LeafKey: slot3StorageKey.Bytes(),
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStorageTrie, crypto.Keccak256(slot3StorageLeafNode)).String(),
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
IPLDs: []types2.IPLD{
|
||
|
{
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStateTrie, crypto.Keccak256(block3BranchRootNode)).String(),
|
||
|
Content: block3BranchRootNode,
|
||
|
},
|
||
|
{
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStateTrie, crypto.Keccak256(contractAccountAtBlock3LeafNode)).String(),
|
||
|
Content: contractAccountAtBlock3LeafNode,
|
||
|
},
|
||
|
{
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStorageTrie, crypto.Keccak256(block3StorageBranchRootNode)).String(),
|
||
|
Content: block3StorageBranchRootNode,
|
||
|
},
|
||
|
{
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStorageTrie, crypto.Keccak256(slot3StorageLeafNode)).String(),
|
||
|
Content: slot3StorageLeafNode,
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
}
|
||
|
|
||
|
for _, test := range tests {
|
||
|
diff, err := builder.BuildStateDiffObject(test.startingArguments, params)
|
||
|
if err != nil {
|
||
|
t.Error(err)
|
||
|
}
|
||
|
receivedStateDiffRlp, err := rlp.EncodeToBytes(&diff)
|
||
|
if err != nil {
|
||
|
t.Error(err)
|
||
|
}
|
||
|
expectedStateDiffRlp, err := rlp.EncodeToBytes(test.expected)
|
||
|
if err != nil {
|
||
|
t.Error(err)
|
||
|
}
|
||
|
sort.Slice(receivedStateDiffRlp, func(i, j int) bool { return receivedStateDiffRlp[i] < receivedStateDiffRlp[j] })
|
||
|
sort.Slice(expectedStateDiffRlp, func(i, j int) bool { return expectedStateDiffRlp[i] < expectedStateDiffRlp[j] })
|
||
|
if !bytes.Equal(receivedStateDiffRlp, expectedStateDiffRlp) {
|
||
|
actual, err := json.Marshal(diff)
|
||
|
if err != nil {
|
||
|
t.Error(err)
|
||
|
}
|
||
|
expected, err := json.Marshal(test.expected)
|
||
|
if err != nil {
|
||
|
t.Error(err)
|
||
|
}
|
||
|
t.Logf("Test failed: %s", test.name)
|
||
|
t.Errorf("actual state diff: %s\r\n\r\n\r\nexpected state diff: %s", actual, expected)
|
||
|
}
|
||
|
}
|
||
|
// Let's also confirm that our root state nodes form the state root hash in the headers
|
||
|
if !bytes.Equal(block0.Root().Bytes(), crypto.Keccak256(bankAccountAtBlock0LeafNode)) {
|
||
|
t.Errorf("block0 expected root %x does not match actual root %x", block0.Root().Bytes(), crypto.Keccak256(bankAccountAtBlock0LeafNode))
|
||
|
}
|
||
|
if !bytes.Equal(block1.Root().Bytes(), crypto.Keccak256(block1BranchRootNode)) {
|
||
|
t.Errorf("block1 expected root %x does not match actual root %x", block1.Root().Bytes(), crypto.Keccak256(block1BranchRootNode))
|
||
|
}
|
||
|
if !bytes.Equal(block2.Root().Bytes(), crypto.Keccak256(block2BranchRootNode)) {
|
||
|
t.Errorf("block2 expected root %x does not match actual root %x", block2.Root().Bytes(), crypto.Keccak256(block2BranchRootNode))
|
||
|
}
|
||
|
if !bytes.Equal(block3.Root().Bytes(), crypto.Keccak256(block3BranchRootNode)) {
|
||
|
t.Errorf("block3 expected root %x does not match actual root %x", block3.Root().Bytes(), crypto.Keccak256(block3BranchRootNode))
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func TestBuilderWithRemovedAccountAndStorage(t *testing.T) {
|
||
|
blocks, chain := test_helpers.MakeChain(6, test_helpers.Genesis, test_helpers.TestChainGen)
|
||
|
contractLeafKey = test_helpers.AddressToLeafKey(test_helpers.ContractAddr)
|
||
|
defer chain.Stop()
|
||
|
block3 = blocks[2]
|
||
|
block4 = blocks[3]
|
||
|
block5 = blocks[4]
|
||
|
block6 = blocks[5]
|
||
|
params := statediff.Params{}
|
||
|
builder = statediff.NewBuilder(chain.StateCache())
|
||
|
|
||
|
var tests = []struct {
|
||
|
name string
|
||
|
startingArguments statediff.Args
|
||
|
expected *types2.StateObject
|
||
|
}{
|
||
|
// blocks 0-3 are the same as in TestBuilderWithIntermediateNodes
|
||
|
{
|
||
|
"testBlock4",
|
||
|
statediff.Args{
|
||
|
OldStateRoot: block3.Root(),
|
||
|
NewStateRoot: block4.Root(),
|
||
|
BlockNumber: block4.Number(),
|
||
|
BlockHash: block4.Hash(),
|
||
|
},
|
||
|
&types2.StateObject{
|
||
|
BlockNumber: block4.Number(),
|
||
|
BlockHash: block4.Hash(),
|
||
|
Nodes: []types2.StateLeafNode{
|
||
|
{
|
||
|
Removed: false,
|
||
|
AccountWrapper: struct {
|
||
|
Account *types.StateAccount
|
||
|
LeafKey []byte
|
||
|
CID string
|
||
|
}{
|
||
|
Account: bankAccountAtBlock4,
|
||
|
LeafKey: test_helpers.BankLeafKey,
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStateTrie, crypto.Keccak256(bankAccountAtBlock4LeafNode)).String()},
|
||
|
StorageDiff: emptyStorage,
|
||
|
},
|
||
|
{
|
||
|
Removed: false,
|
||
|
AccountWrapper: struct {
|
||
|
Account *types.StateAccount
|
||
|
LeafKey []byte
|
||
|
CID string
|
||
|
}{
|
||
|
Account: contractAccountAtBlock4,
|
||
|
LeafKey: contractLeafKey,
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStateTrie, crypto.Keccak256(contractAccountAtBlock4LeafNode)).String()},
|
||
|
StorageDiff: []types2.StorageLeafNode{
|
||
|
{
|
||
|
Removed: false,
|
||
|
Value: slot2StorageValue,
|
||
|
LeafKey: slot2StorageKey.Bytes(),
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStorageTrie, crypto.Keccak256(slot2StorageLeafNode)).String(),
|
||
|
},
|
||
|
{
|
||
|
Removed: true,
|
||
|
LeafKey: slot1StorageKey.Bytes(),
|
||
|
CID: shared.RemovedNodeStorageCID,
|
||
|
Value: []byte{},
|
||
|
},
|
||
|
{
|
||
|
Removed: true,
|
||
|
LeafKey: slot3StorageKey.Bytes(),
|
||
|
CID: shared.RemovedNodeStorageCID,
|
||
|
Value: []byte{},
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
{
|
||
|
Removed: false,
|
||
|
AccountWrapper: struct {
|
||
|
Account *types.StateAccount
|
||
|
LeafKey []byte
|
||
|
CID string
|
||
|
}{
|
||
|
Account: account2AtBlock4,
|
||
|
LeafKey: test_helpers.Account2LeafKey,
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStateTrie, crypto.Keccak256(account2AtBlock4LeafNode)).String()},
|
||
|
StorageDiff: emptyStorage,
|
||
|
},
|
||
|
},
|
||
|
IPLDs: []types2.IPLD{
|
||
|
{
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStateTrie, crypto.Keccak256(block4BranchRootNode)).String(),
|
||
|
Content: block4BranchRootNode,
|
||
|
},
|
||
|
{
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStateTrie, crypto.Keccak256(bankAccountAtBlock4LeafNode)).String(),
|
||
|
Content: bankAccountAtBlock4LeafNode,
|
||
|
},
|
||
|
{
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStateTrie, crypto.Keccak256(contractAccountAtBlock4LeafNode)).String(),
|
||
|
Content: contractAccountAtBlock4LeafNode,
|
||
|
},
|
||
|
{
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStorageTrie, crypto.Keccak256(block4StorageBranchRootNode)).String(),
|
||
|
Content: block4StorageBranchRootNode,
|
||
|
},
|
||
|
{
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStorageTrie, crypto.Keccak256(slot2StorageLeafNode)).String(),
|
||
|
Content: slot2StorageLeafNode,
|
||
|
},
|
||
|
{
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStateTrie, crypto.Keccak256(account2AtBlock4LeafNode)).String(),
|
||
|
Content: account2AtBlock4LeafNode,
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
{
|
||
|
"testBlock5",
|
||
|
statediff.Args{
|
||
|
OldStateRoot: block4.Root(),
|
||
|
NewStateRoot: block5.Root(),
|
||
|
BlockNumber: block5.Number(),
|
||
|
BlockHash: block5.Hash(),
|
||
|
},
|
||
|
&types2.StateObject{
|
||
|
BlockNumber: block5.Number(),
|
||
|
BlockHash: block5.Hash(),
|
||
|
Nodes: []types2.StateLeafNode{
|
||
|
{
|
||
|
Removed: false,
|
||
|
AccountWrapper: struct {
|
||
|
Account *types.StateAccount
|
||
|
LeafKey []byte
|
||
|
CID string
|
||
|
}{
|
||
|
Account: bankAccountAtBlock5,
|
||
|
LeafKey: test_helpers.BankLeafKey,
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStateTrie, crypto.Keccak256(bankAccountAtBlock5LeafNode)).String()},
|
||
|
StorageDiff: emptyStorage,
|
||
|
},
|
||
|
{
|
||
|
Removed: false,
|
||
|
AccountWrapper: struct {
|
||
|
Account *types.StateAccount
|
||
|
LeafKey []byte
|
||
|
CID string
|
||
|
}{
|
||
|
Account: contractAccountAtBlock5,
|
||
|
LeafKey: contractLeafKey,
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStateTrie, crypto.Keccak256(contractAccountAtBlock5LeafNode)).String()},
|
||
|
StorageDiff: []types2.StorageLeafNode{
|
||
|
{
|
||
|
Removed: false,
|
||
|
Value: slot3StorageValue,
|
||
|
LeafKey: slot3StorageKey.Bytes(),
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStorageTrie, crypto.Keccak256(slot3StorageLeafNode)).String(),
|
||
|
},
|
||
|
{
|
||
|
Removed: true,
|
||
|
LeafKey: slot2StorageKey.Bytes(),
|
||
|
CID: shared.RemovedNodeStorageCID,
|
||
|
Value: []byte{},
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
{
|
||
|
Removed: false,
|
||
|
AccountWrapper: struct {
|
||
|
Account *types.StateAccount
|
||
|
LeafKey []byte
|
||
|
CID string
|
||
|
}{
|
||
|
Account: account1AtBlock5,
|
||
|
LeafKey: test_helpers.Account1LeafKey,
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStateTrie, crypto.Keccak256(account1AtBlock5LeafNode)).String()},
|
||
|
StorageDiff: emptyStorage,
|
||
|
},
|
||
|
},
|
||
|
IPLDs: []types2.IPLD{
|
||
|
{
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStateTrie, crypto.Keccak256(block5BranchRootNode)).String(),
|
||
|
Content: block5BranchRootNode,
|
||
|
},
|
||
|
{
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStateTrie, crypto.Keccak256(bankAccountAtBlock5LeafNode)).String(),
|
||
|
Content: bankAccountAtBlock5LeafNode,
|
||
|
},
|
||
|
{
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStateTrie, crypto.Keccak256(contractAccountAtBlock5LeafNode)).String(),
|
||
|
Content: contractAccountAtBlock5LeafNode,
|
||
|
},
|
||
|
{
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStorageTrie, crypto.Keccak256(block5StorageBranchRootNode)).String(),
|
||
|
Content: block5StorageBranchRootNode,
|
||
|
},
|
||
|
{
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStorageTrie, crypto.Keccak256(slot3StorageLeafNode)).String(),
|
||
|
Content: slot3StorageLeafNode,
|
||
|
},
|
||
|
{
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStateTrie, crypto.Keccak256(account1AtBlock5LeafNode)).String(),
|
||
|
Content: account1AtBlock5LeafNode,
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
{
|
||
|
"testBlock6",
|
||
|
statediff.Args{
|
||
|
OldStateRoot: block5.Root(),
|
||
|
NewStateRoot: block6.Root(),
|
||
|
BlockNumber: block6.Number(),
|
||
|
BlockHash: block6.Hash(),
|
||
|
},
|
||
|
&types2.StateObject{
|
||
|
BlockNumber: block6.Number(),
|
||
|
BlockHash: block6.Hash(),
|
||
|
Nodes: []types2.StateLeafNode{
|
||
|
{
|
||
|
Removed: true,
|
||
|
AccountWrapper: struct {
|
||
|
Account *types.StateAccount
|
||
|
LeafKey []byte
|
||
|
CID string
|
||
|
}{
|
||
|
Account: nil,
|
||
|
LeafKey: contractLeafKey,
|
||
|
CID: shared.RemovedNodeStateCID},
|
||
|
StorageDiff: []types2.StorageLeafNode{
|
||
|
{
|
||
|
Removed: true,
|
||
|
LeafKey: slot0StorageKey.Bytes(),
|
||
|
CID: shared.RemovedNodeStorageCID,
|
||
|
Value: []byte{},
|
||
|
},
|
||
|
{
|
||
|
Removed: true,
|
||
|
LeafKey: slot3StorageKey.Bytes(),
|
||
|
CID: shared.RemovedNodeStorageCID,
|
||
|
Value: []byte{},
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
{
|
||
|
Removed: false,
|
||
|
AccountWrapper: struct {
|
||
|
Account *types.StateAccount
|
||
|
LeafKey []byte
|
||
|
CID string
|
||
|
}{
|
||
|
Account: account2AtBlock6,
|
||
|
LeafKey: test_helpers.Account2LeafKey,
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStateTrie, crypto.Keccak256(account2AtBlock6LeafNode)).String()},
|
||
|
StorageDiff: emptyStorage,
|
||
|
},
|
||
|
{
|
||
|
Removed: false,
|
||
|
AccountWrapper: struct {
|
||
|
Account *types.StateAccount
|
||
|
LeafKey []byte
|
||
|
CID string
|
||
|
}{
|
||
|
Account: account1AtBlock6,
|
||
|
LeafKey: test_helpers.Account1LeafKey,
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStateTrie, crypto.Keccak256(account1AtBlock6LeafNode)).String()},
|
||
|
StorageDiff: emptyStorage,
|
||
|
},
|
||
|
},
|
||
|
IPLDs: []types2.IPLD{
|
||
|
{
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStateTrie, crypto.Keccak256(block6BranchRootNode)).String(),
|
||
|
Content: block6BranchRootNode,
|
||
|
},
|
||
|
{
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStateTrie, crypto.Keccak256(account2AtBlock6LeafNode)).String(),
|
||
|
Content: account2AtBlock6LeafNode,
|
||
|
},
|
||
|
{
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStateTrie, crypto.Keccak256(account1AtBlock6LeafNode)).String(),
|
||
|
Content: account1AtBlock6LeafNode,
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
}
|
||
|
|
||
|
for _, test := range tests {
|
||
|
diff, err := builder.BuildStateDiffObject(test.startingArguments, params)
|
||
|
if err != nil {
|
||
|
t.Error(err)
|
||
|
}
|
||
|
receivedStateDiffRlp, err := rlp.EncodeToBytes(&diff)
|
||
|
if err != nil {
|
||
|
t.Error(err)
|
||
|
}
|
||
|
expectedStateDiffRlp, err := rlp.EncodeToBytes(test.expected)
|
||
|
if err != nil {
|
||
|
t.Error(err)
|
||
|
}
|
||
|
sort.Slice(receivedStateDiffRlp, func(i, j int) bool { return receivedStateDiffRlp[i] < receivedStateDiffRlp[j] })
|
||
|
sort.Slice(expectedStateDiffRlp, func(i, j int) bool { return expectedStateDiffRlp[i] < expectedStateDiffRlp[j] })
|
||
|
if !bytes.Equal(receivedStateDiffRlp, expectedStateDiffRlp) {
|
||
|
actual, err := json.Marshal(diff)
|
||
|
if err != nil {
|
||
|
t.Error(err)
|
||
|
}
|
||
|
expected, err := json.Marshal(test.expected)
|
||
|
if err != nil {
|
||
|
t.Error(err)
|
||
|
}
|
||
|
t.Logf("Test failed: %s", test.name)
|
||
|
t.Errorf("actual state diff: %s\r\n\r\n\r\nexpected state diff: %s", actual, expected)
|
||
|
}
|
||
|
}
|
||
|
// Let's also confirm that our root state nodes form the state root hash in the headers
|
||
|
if !bytes.Equal(block4.Root().Bytes(), crypto.Keccak256(block4BranchRootNode)) {
|
||
|
t.Errorf("block4 expected root %x does not match actual root %x", block4.Root().Bytes(), crypto.Keccak256(block4BranchRootNode))
|
||
|
}
|
||
|
if !bytes.Equal(block5.Root().Bytes(), crypto.Keccak256(block5BranchRootNode)) {
|
||
|
t.Errorf("block5 expected root %x does not match actual root %x", block5.Root().Bytes(), crypto.Keccak256(block5BranchRootNode))
|
||
|
}
|
||
|
if !bytes.Equal(block6.Root().Bytes(), crypto.Keccak256(block6BranchRootNode)) {
|
||
|
t.Errorf("block6 expected root %x does not match actual root %x", block6.Root().Bytes(), crypto.Keccak256(block6BranchRootNode))
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func TestBuilderWithRemovedNonWatchedAccount(t *testing.T) {
|
||
|
blocks, chain := test_helpers.MakeChain(6, test_helpers.Genesis, test_helpers.TestChainGen)
|
||
|
contractLeafKey = test_helpers.AddressToLeafKey(test_helpers.ContractAddr)
|
||
|
defer chain.Stop()
|
||
|
block3 = blocks[2]
|
||
|
block4 = blocks[3]
|
||
|
block5 = blocks[4]
|
||
|
block6 = blocks[5]
|
||
|
params := statediff.Params{
|
||
|
WatchedAddresses: []common.Address{test_helpers.Account1Addr, test_helpers.Account2Addr},
|
||
|
}
|
||
|
params.ComputeWatchedAddressesLeafPaths()
|
||
|
builder = statediff.NewBuilder(chain.StateCache())
|
||
|
|
||
|
var tests = []struct {
|
||
|
name string
|
||
|
startingArguments statediff.Args
|
||
|
expected *types2.StateObject
|
||
|
}{
|
||
|
{
|
||
|
"testBlock4",
|
||
|
statediff.Args{
|
||
|
OldStateRoot: block3.Root(),
|
||
|
NewStateRoot: block4.Root(),
|
||
|
BlockNumber: block4.Number(),
|
||
|
BlockHash: block4.Hash(),
|
||
|
},
|
||
|
&types2.StateObject{
|
||
|
BlockNumber: block4.Number(),
|
||
|
BlockHash: block4.Hash(),
|
||
|
Nodes: []types2.StateLeafNode{
|
||
|
{
|
||
|
Removed: false,
|
||
|
AccountWrapper: struct {
|
||
|
Account *types.StateAccount
|
||
|
LeafKey []byte
|
||
|
CID string
|
||
|
}{
|
||
|
Account: account2AtBlock4,
|
||
|
LeafKey: test_helpers.Account2LeafKey,
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStateTrie, crypto.Keccak256(account2AtBlock4LeafNode)).String()},
|
||
|
StorageDiff: emptyStorage,
|
||
|
},
|
||
|
},
|
||
|
IPLDs: []types2.IPLD{
|
||
|
{
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStateTrie, crypto.Keccak256(block4BranchRootNode)).String(),
|
||
|
Content: block4BranchRootNode,
|
||
|
},
|
||
|
{
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStateTrie, crypto.Keccak256(account2AtBlock4LeafNode)).String(),
|
||
|
Content: account2AtBlock4LeafNode,
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
{
|
||
|
"testBlock5",
|
||
|
statediff.Args{
|
||
|
OldStateRoot: block4.Root(),
|
||
|
NewStateRoot: block5.Root(),
|
||
|
BlockNumber: block5.Number(),
|
||
|
BlockHash: block5.Hash(),
|
||
|
},
|
||
|
&types2.StateObject{
|
||
|
BlockNumber: block5.Number(),
|
||
|
BlockHash: block5.Hash(),
|
||
|
Nodes: []types2.StateLeafNode{
|
||
|
{
|
||
|
Removed: false,
|
||
|
AccountWrapper: struct {
|
||
|
Account *types.StateAccount
|
||
|
LeafKey []byte
|
||
|
CID string
|
||
|
}{
|
||
|
Account: account1AtBlock5,
|
||
|
LeafKey: test_helpers.Account1LeafKey,
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStateTrie, crypto.Keccak256(account1AtBlock5LeafNode)).String()},
|
||
|
StorageDiff: emptyStorage,
|
||
|
},
|
||
|
},
|
||
|
IPLDs: []types2.IPLD{
|
||
|
{
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStateTrie, crypto.Keccak256(block5BranchRootNode)).String(),
|
||
|
Content: block5BranchRootNode,
|
||
|
},
|
||
|
{
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStateTrie, crypto.Keccak256(account1AtBlock5LeafNode)).String(),
|
||
|
Content: account1AtBlock5LeafNode,
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
{
|
||
|
"testBlock6",
|
||
|
statediff.Args{
|
||
|
OldStateRoot: block5.Root(),
|
||
|
NewStateRoot: block6.Root(),
|
||
|
BlockNumber: block6.Number(),
|
||
|
BlockHash: block6.Hash(),
|
||
|
},
|
||
|
&types2.StateObject{
|
||
|
BlockNumber: block6.Number(),
|
||
|
BlockHash: block6.Hash(),
|
||
|
Nodes: []types2.StateLeafNode{
|
||
|
{
|
||
|
Removed: false,
|
||
|
AccountWrapper: struct {
|
||
|
Account *types.StateAccount
|
||
|
LeafKey []byte
|
||
|
CID string
|
||
|
}{
|
||
|
Account: account2AtBlock6,
|
||
|
LeafKey: test_helpers.Account2LeafKey,
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStateTrie, crypto.Keccak256(account2AtBlock6LeafNode)).String()},
|
||
|
StorageDiff: emptyStorage,
|
||
|
},
|
||
|
{
|
||
|
Removed: false,
|
||
|
AccountWrapper: struct {
|
||
|
Account *types.StateAccount
|
||
|
LeafKey []byte
|
||
|
CID string
|
||
|
}{
|
||
|
Account: account1AtBlock6,
|
||
|
LeafKey: test_helpers.Account1LeafKey,
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStateTrie, crypto.Keccak256(account1AtBlock6LeafNode)).String()},
|
||
|
StorageDiff: emptyStorage,
|
||
|
},
|
||
|
},
|
||
|
IPLDs: []types2.IPLD{
|
||
|
{
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStateTrie, crypto.Keccak256(block6BranchRootNode)).String(),
|
||
|
Content: block6BranchRootNode,
|
||
|
},
|
||
|
{
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStateTrie, crypto.Keccak256(account2AtBlock6LeafNode)).String(),
|
||
|
Content: account2AtBlock6LeafNode,
|
||
|
},
|
||
|
{
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStateTrie, crypto.Keccak256(account1AtBlock6LeafNode)).String(),
|
||
|
Content: account1AtBlock6LeafNode,
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
}
|
||
|
|
||
|
for _, test := range tests {
|
||
|
diff, err := builder.BuildStateDiffObject(test.startingArguments, params)
|
||
|
if err != nil {
|
||
|
t.Error(err)
|
||
|
}
|
||
|
receivedStateDiffRlp, err := rlp.EncodeToBytes(&diff)
|
||
|
if err != nil {
|
||
|
t.Error(err)
|
||
|
}
|
||
|
|
||
|
expectedStateDiffRlp, err := rlp.EncodeToBytes(test.expected)
|
||
|
if err != nil {
|
||
|
t.Error(err)
|
||
|
}
|
||
|
|
||
|
sort.Slice(receivedStateDiffRlp, func(i, j int) bool { return receivedStateDiffRlp[i] < receivedStateDiffRlp[j] })
|
||
|
sort.Slice(expectedStateDiffRlp, func(i, j int) bool { return expectedStateDiffRlp[i] < expectedStateDiffRlp[j] })
|
||
|
if !bytes.Equal(receivedStateDiffRlp, expectedStateDiffRlp) {
|
||
|
actual, err := json.Marshal(diff)
|
||
|
if err != nil {
|
||
|
t.Error(err)
|
||
|
}
|
||
|
expected, err := json.Marshal(test.expected)
|
||
|
if err != nil {
|
||
|
t.Error(err)
|
||
|
}
|
||
|
t.Logf("Test failed: %s", test.name)
|
||
|
t.Errorf("actual state diff: %s\r\n\r\n\r\nexpected state diff: %s", actual, expected)
|
||
|
}
|
||
|
}
|
||
|
// Let's also confirm that our root state nodes form the state root hash in the headers
|
||
|
if !bytes.Equal(block4.Root().Bytes(), crypto.Keccak256(block4BranchRootNode)) {
|
||
|
t.Errorf("block4 expected root %x does not match actual root %x", block4.Root().Bytes(), crypto.Keccak256(block4BranchRootNode))
|
||
|
}
|
||
|
if !bytes.Equal(block5.Root().Bytes(), crypto.Keccak256(block5BranchRootNode)) {
|
||
|
t.Errorf("block5 expected root %x does not match actual root %x", block5.Root().Bytes(), crypto.Keccak256(block5BranchRootNode))
|
||
|
}
|
||
|
if !bytes.Equal(block6.Root().Bytes(), crypto.Keccak256(block6BranchRootNode)) {
|
||
|
t.Errorf("block6 expected root %x does not match actual root %x", block6.Root().Bytes(), crypto.Keccak256(block6BranchRootNode))
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func TestBuilderWithRemovedWatchedAccount(t *testing.T) {
|
||
|
blocks, chain := test_helpers.MakeChain(6, test_helpers.Genesis, test_helpers.TestChainGen)
|
||
|
contractLeafKey = test_helpers.AddressToLeafKey(test_helpers.ContractAddr)
|
||
|
defer chain.Stop()
|
||
|
block3 = blocks[2]
|
||
|
block4 = blocks[3]
|
||
|
block5 = blocks[4]
|
||
|
block6 = blocks[5]
|
||
|
params := statediff.Params{
|
||
|
WatchedAddresses: []common.Address{test_helpers.Account1Addr, test_helpers.ContractAddr},
|
||
|
}
|
||
|
params.ComputeWatchedAddressesLeafPaths()
|
||
|
builder = statediff.NewBuilder(chain.StateCache())
|
||
|
|
||
|
var tests = []struct {
|
||
|
name string
|
||
|
startingArguments statediff.Args
|
||
|
expected *types2.StateObject
|
||
|
}{
|
||
|
{
|
||
|
"testBlock4",
|
||
|
statediff.Args{
|
||
|
OldStateRoot: block3.Root(),
|
||
|
NewStateRoot: block4.Root(),
|
||
|
BlockNumber: block4.Number(),
|
||
|
BlockHash: block4.Hash(),
|
||
|
},
|
||
|
&types2.StateObject{
|
||
|
BlockNumber: block4.Number(),
|
||
|
BlockHash: block4.Hash(),
|
||
|
Nodes: []types2.StateLeafNode{
|
||
|
{
|
||
|
Removed: false,
|
||
|
AccountWrapper: struct {
|
||
|
Account *types.StateAccount
|
||
|
LeafKey []byte
|
||
|
CID string
|
||
|
}{
|
||
|
Account: contractAccountAtBlock4,
|
||
|
LeafKey: contractLeafKey,
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStateTrie, crypto.Keccak256(contractAccountAtBlock4LeafNode)).String()},
|
||
|
StorageDiff: []types2.StorageLeafNode{
|
||
|
{
|
||
|
Removed: false,
|
||
|
LeafKey: slot2StorageKey.Bytes(),
|
||
|
Value: slot2StorageValue,
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStorageTrie, crypto.Keccak256(slot2StorageLeafNode)).String(),
|
||
|
},
|
||
|
{
|
||
|
Removed: true,
|
||
|
LeafKey: slot1StorageKey.Bytes(),
|
||
|
CID: shared.RemovedNodeStorageCID,
|
||
|
Value: []byte{},
|
||
|
},
|
||
|
{
|
||
|
Removed: true,
|
||
|
LeafKey: slot3StorageKey.Bytes(),
|
||
|
CID: shared.RemovedNodeStorageCID,
|
||
|
Value: []byte{},
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
IPLDs: []types2.IPLD{
|
||
|
{
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStateTrie, crypto.Keccak256(block4BranchRootNode)).String(),
|
||
|
Content: block4BranchRootNode,
|
||
|
},
|
||
|
{
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStateTrie, crypto.Keccak256(contractAccountAtBlock4LeafNode)).String(),
|
||
|
Content: contractAccountAtBlock4LeafNode,
|
||
|
},
|
||
|
{
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStorageTrie, crypto.Keccak256(block4StorageBranchRootNode)).String(),
|
||
|
Content: block4StorageBranchRootNode,
|
||
|
},
|
||
|
{
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStorageTrie, crypto.Keccak256(slot2StorageLeafNode)).String(),
|
||
|
Content: slot2StorageLeafNode,
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
{
|
||
|
"testBlock5",
|
||
|
statediff.Args{
|
||
|
OldStateRoot: block4.Root(),
|
||
|
NewStateRoot: block5.Root(),
|
||
|
BlockNumber: block5.Number(),
|
||
|
BlockHash: block5.Hash(),
|
||
|
},
|
||
|
&types2.StateObject{
|
||
|
BlockNumber: block5.Number(),
|
||
|
BlockHash: block5.Hash(),
|
||
|
Nodes: []types2.StateLeafNode{
|
||
|
{
|
||
|
Removed: false,
|
||
|
AccountWrapper: struct {
|
||
|
Account *types.StateAccount
|
||
|
LeafKey []byte
|
||
|
CID string
|
||
|
}{
|
||
|
Account: contractAccountAtBlock5,
|
||
|
LeafKey: contractLeafKey,
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStateTrie, crypto.Keccak256(contractAccountAtBlock5LeafNode)).String()},
|
||
|
StorageDiff: []types2.StorageLeafNode{
|
||
|
{
|
||
|
Removed: false,
|
||
|
LeafKey: slot3StorageKey.Bytes(),
|
||
|
Value: slot3StorageValue,
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStorageTrie, crypto.Keccak256(slot3StorageLeafNode)).String(),
|
||
|
},
|
||
|
{
|
||
|
Removed: true,
|
||
|
LeafKey: slot2StorageKey.Bytes(),
|
||
|
CID: shared.RemovedNodeStorageCID,
|
||
|
Value: []byte{},
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
{
|
||
|
Removed: false,
|
||
|
AccountWrapper: struct {
|
||
|
Account *types.StateAccount
|
||
|
LeafKey []byte
|
||
|
CID string
|
||
|
}{
|
||
|
Account: account1AtBlock5,
|
||
|
LeafKey: test_helpers.Account1LeafKey,
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStateTrie, crypto.Keccak256(account1AtBlock5LeafNode)).String()},
|
||
|
StorageDiff: emptyStorage,
|
||
|
},
|
||
|
},
|
||
|
IPLDs: []types2.IPLD{
|
||
|
{
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStateTrie, crypto.Keccak256(block5BranchRootNode)).String(),
|
||
|
Content: block5BranchRootNode,
|
||
|
},
|
||
|
{
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStateTrie, crypto.Keccak256(contractAccountAtBlock5LeafNode)).String(),
|
||
|
Content: contractAccountAtBlock5LeafNode,
|
||
|
},
|
||
|
{
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStorageTrie, crypto.Keccak256(block5StorageBranchRootNode)).String(),
|
||
|
Content: block5StorageBranchRootNode,
|
||
|
},
|
||
|
{
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStorageTrie, crypto.Keccak256(slot3StorageLeafNode)).String(),
|
||
|
Content: slot3StorageLeafNode,
|
||
|
},
|
||
|
{
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStateTrie, crypto.Keccak256(account1AtBlock5LeafNode)).String(),
|
||
|
Content: account1AtBlock5LeafNode,
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
{
|
||
|
"testBlock6",
|
||
|
statediff.Args{
|
||
|
OldStateRoot: block5.Root(),
|
||
|
NewStateRoot: block6.Root(),
|
||
|
BlockNumber: block6.Number(),
|
||
|
BlockHash: block6.Hash(),
|
||
|
},
|
||
|
&types2.StateObject{
|
||
|
BlockNumber: block6.Number(),
|
||
|
BlockHash: block6.Hash(),
|
||
|
Nodes: []types2.StateLeafNode{
|
||
|
{
|
||
|
Removed: true,
|
||
|
AccountWrapper: struct {
|
||
|
Account *types.StateAccount
|
||
|
LeafKey []byte
|
||
|
CID string
|
||
|
}{
|
||
|
Account: nil,
|
||
|
LeafKey: contractLeafKey,
|
||
|
CID: shared.RemovedNodeStateCID},
|
||
|
StorageDiff: []types2.StorageLeafNode{
|
||
|
{
|
||
|
Removed: true,
|
||
|
LeafKey: slot0StorageKey.Bytes(),
|
||
|
CID: shared.RemovedNodeStorageCID,
|
||
|
Value: []byte{},
|
||
|
},
|
||
|
{
|
||
|
Removed: true,
|
||
|
LeafKey: slot3StorageKey.Bytes(),
|
||
|
CID: shared.RemovedNodeStorageCID,
|
||
|
Value: []byte{},
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
{
|
||
|
Removed: false,
|
||
|
AccountWrapper: struct {
|
||
|
Account *types.StateAccount
|
||
|
LeafKey []byte
|
||
|
CID string
|
||
|
}{
|
||
|
Account: account1AtBlock6,
|
||
|
LeafKey: test_helpers.Account1LeafKey,
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStateTrie, crypto.Keccak256(account1AtBlock6LeafNode)).String()},
|
||
|
StorageDiff: emptyStorage,
|
||
|
},
|
||
|
},
|
||
|
IPLDs: []types2.IPLD{
|
||
|
{
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStateTrie, crypto.Keccak256(block6BranchRootNode)).String(),
|
||
|
Content: block6BranchRootNode,
|
||
|
},
|
||
|
{
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStateTrie, crypto.Keccak256(account1AtBlock6LeafNode)).String(),
|
||
|
Content: account1AtBlock6LeafNode,
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
}
|
||
|
|
||
|
for _, test := range tests {
|
||
|
diff, err := builder.BuildStateDiffObject(test.startingArguments, params)
|
||
|
if err != nil {
|
||
|
t.Error(err)
|
||
|
}
|
||
|
receivedStateDiffRlp, err := rlp.EncodeToBytes(&diff)
|
||
|
if err != nil {
|
||
|
t.Error(err)
|
||
|
}
|
||
|
|
||
|
expectedStateDiffRlp, err := rlp.EncodeToBytes(test.expected)
|
||
|
if err != nil {
|
||
|
t.Error(err)
|
||
|
}
|
||
|
|
||
|
sort.Slice(receivedStateDiffRlp, func(i, j int) bool { return receivedStateDiffRlp[i] < receivedStateDiffRlp[j] })
|
||
|
sort.Slice(expectedStateDiffRlp, func(i, j int) bool { return expectedStateDiffRlp[i] < expectedStateDiffRlp[j] })
|
||
|
if !bytes.Equal(receivedStateDiffRlp, expectedStateDiffRlp) {
|
||
|
actual, err := json.Marshal(diff)
|
||
|
if err != nil {
|
||
|
t.Error(err)
|
||
|
}
|
||
|
expected, err := json.Marshal(test.expected)
|
||
|
if err != nil {
|
||
|
t.Error(err)
|
||
|
}
|
||
|
t.Logf("Test failed: %s", test.name)
|
||
|
t.Errorf("actual state diff: %s\r\n\r\n\r\nexpected state diff: %s", actual, expected)
|
||
|
}
|
||
|
}
|
||
|
// Let's also confirm that our root state nodes form the state root hash in the headers
|
||
|
if !bytes.Equal(block4.Root().Bytes(), crypto.Keccak256(block4BranchRootNode)) {
|
||
|
t.Errorf("block4 expected root %x does not match actual root %x", block4.Root().Bytes(), crypto.Keccak256(block4BranchRootNode))
|
||
|
}
|
||
|
if !bytes.Equal(block5.Root().Bytes(), crypto.Keccak256(block5BranchRootNode)) {
|
||
|
t.Errorf("block5 expected root %x does not match actual root %x", block5.Root().Bytes(), crypto.Keccak256(block5BranchRootNode))
|
||
|
}
|
||
|
if !bytes.Equal(block6.Root().Bytes(), crypto.Keccak256(block6BranchRootNode)) {
|
||
|
t.Errorf("block6 expected root %x does not match actual root %x", block6.Root().Bytes(), crypto.Keccak256(block6BranchRootNode))
|
||
|
}
|
||
|
}
|
||
|
|
||
|
var (
|
||
|
slot00StorageValue = common.Hex2Bytes("9471562b71999873db5b286df957af199ec94617f7") // prefixed TestBankAddress
|
||
|
|
||
|
slot00StorageLeafNode, _ = rlp.EncodeToBytes(&[]interface{}{
|
||
|
common.Hex2Bytes("390decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563"),
|
||
|
slot00StorageValue,
|
||
|
})
|
||
|
|
||
|
contractAccountAtBlock01 = &types.StateAccount{
|
||
|
Nonce: 1,
|
||
|
Balance: big.NewInt(0),
|
||
|
CodeHash: common.HexToHash("0xaaea5efba4fd7b45d7ec03918ac5d8b31aa93b48986af0e6b591f0f087c80127").Bytes(),
|
||
|
Root: crypto.Keccak256Hash(block01StorageBranchRootNode),
|
||
|
}
|
||
|
contractAccountAtBlock01RLP, _ = rlp.EncodeToBytes(contractAccountAtBlock01)
|
||
|
contractAccountAtBlock01LeafNode, _ = rlp.EncodeToBytes(&[]interface{}{
|
||
|
common.Hex2Bytes("3cb2583748c26e89ef19c2a8529b05a270f735553b4d44b6f2a1894987a71c8b"),
|
||
|
contractAccountAtBlock01RLP,
|
||
|
})
|
||
|
|
||
|
bankAccountAtBlock01 = &types.StateAccount{
|
||
|
Nonce: 1,
|
||
|
Balance: big.NewInt(3999629697375000000),
|
||
|
CodeHash: test_helpers.NullCodeHash.Bytes(),
|
||
|
Root: test_helpers.EmptyContractRoot,
|
||
|
}
|
||
|
bankAccountAtBlock01RLP, _ = rlp.EncodeToBytes(bankAccountAtBlock01)
|
||
|
bankAccountAtBlock01LeafNode, _ = rlp.EncodeToBytes(&[]interface{}{
|
||
|
common.Hex2Bytes("30bf49f440a1cd0527e4d06e2765654c0f56452257516d793a9b8d604dcfdf2a"),
|
||
|
bankAccountAtBlock01RLP,
|
||
|
})
|
||
|
bankAccountAtBlock02 = &types.StateAccount{
|
||
|
Nonce: 2,
|
||
|
Balance: big.NewInt(5999607323457344852),
|
||
|
CodeHash: test_helpers.NullCodeHash.Bytes(),
|
||
|
Root: test_helpers.EmptyContractRoot,
|
||
|
}
|
||
|
bankAccountAtBlock02RLP, _ = rlp.EncodeToBytes(bankAccountAtBlock02)
|
||
|
bankAccountAtBlock02LeafNode, _ = rlp.EncodeToBytes(&[]interface{}{
|
||
|
common.Hex2Bytes("2000bf49f440a1cd0527e4d06e2765654c0f56452257516d793a9b8d604dcfdf2a"),
|
||
|
bankAccountAtBlock02RLP,
|
||
|
})
|
||
|
|
||
|
block01BranchRootNode, _ = rlp.EncodeToBytes(&[]interface{}{
|
||
|
crypto.Keccak256Hash(bankAccountAtBlock01LeafNode),
|
||
|
crypto.Keccak256Hash(contractAccountAtBlock01LeafNode),
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
})
|
||
|
|
||
|
block01StorageBranchRootNode, _ = rlp.EncodeToBytes(&[]interface{}{
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
crypto.Keccak256(slot00StorageLeafNode),
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
crypto.Keccak256(slot1StorageLeafNode),
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
})
|
||
|
)
|
||
|
|
||
|
func TestBuilderWithMovedAccount(t *testing.T) {
|
||
|
blocks, chain := test_helpers.MakeChain(2, test_helpers.Genesis, test_helpers.TestSelfDestructChainGen)
|
||
|
contractLeafKey = test_helpers.AddressToLeafKey(test_helpers.ContractAddr)
|
||
|
defer chain.Stop()
|
||
|
block0 = test_helpers.Genesis
|
||
|
block1 = blocks[0]
|
||
|
block2 = blocks[1]
|
||
|
params := statediff.Params{}
|
||
|
builder = statediff.NewBuilder(chain.StateCache())
|
||
|
|
||
|
var tests = []struct {
|
||
|
name string
|
||
|
startingArguments statediff.Args
|
||
|
expected *types2.StateObject
|
||
|
}{
|
||
|
{
|
||
|
"testBlock1",
|
||
|
statediff.Args{
|
||
|
OldStateRoot: block0.Root(),
|
||
|
NewStateRoot: block1.Root(),
|
||
|
BlockNumber: block1.Number(),
|
||
|
BlockHash: block1.Hash(),
|
||
|
},
|
||
|
&types2.StateObject{
|
||
|
BlockNumber: block1.Number(),
|
||
|
BlockHash: block1.Hash(),
|
||
|
Nodes: []types2.StateLeafNode{
|
||
|
{
|
||
|
Removed: false,
|
||
|
AccountWrapper: struct {
|
||
|
Account *types.StateAccount
|
||
|
LeafKey []byte
|
||
|
CID string
|
||
|
}{
|
||
|
Account: bankAccountAtBlock01,
|
||
|
LeafKey: test_helpers.BankLeafKey,
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStateTrie, crypto.Keccak256(bankAccountAtBlock01LeafNode)).String()},
|
||
|
StorageDiff: emptyStorage,
|
||
|
},
|
||
|
{
|
||
|
Removed: false,
|
||
|
AccountWrapper: struct {
|
||
|
Account *types.StateAccount
|
||
|
LeafKey []byte
|
||
|
CID string
|
||
|
}{
|
||
|
Account: contractAccountAtBlock01,
|
||
|
LeafKey: contractLeafKey,
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStateTrie, crypto.Keccak256(contractAccountAtBlock01LeafNode)).String()},
|
||
|
StorageDiff: []types2.StorageLeafNode{
|
||
|
{
|
||
|
Removed: false,
|
||
|
LeafKey: slot0StorageKey.Bytes(),
|
||
|
Value: slot00StorageValue,
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStorageTrie, crypto.Keccak256(slot00StorageLeafNode)).String(),
|
||
|
},
|
||
|
{
|
||
|
Removed: false,
|
||
|
LeafKey: slot1StorageKey.Bytes(),
|
||
|
Value: slot1StorageValue,
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStorageTrie, crypto.Keccak256(slot1StorageLeafNode)).String(),
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
IPLDs: []types2.IPLD{
|
||
|
{
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.RawBinary, test_helpers.CodeHash.Bytes()).String(),
|
||
|
Content: test_helpers.ByteCodeAfterDeployment,
|
||
|
},
|
||
|
{
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStateTrie, crypto.Keccak256(block01BranchRootNode)).String(),
|
||
|
Content: block01BranchRootNode,
|
||
|
},
|
||
|
{
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStateTrie, crypto.Keccak256(bankAccountAtBlock01LeafNode)).String(),
|
||
|
Content: bankAccountAtBlock01LeafNode,
|
||
|
},
|
||
|
{
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStateTrie, crypto.Keccak256(contractAccountAtBlock01LeafNode)).String(),
|
||
|
Content: contractAccountAtBlock01LeafNode,
|
||
|
},
|
||
|
{
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStorageTrie, crypto.Keccak256(block01StorageBranchRootNode)).String(),
|
||
|
Content: block01StorageBranchRootNode,
|
||
|
},
|
||
|
{
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStorageTrie, crypto.Keccak256(slot00StorageLeafNode)).String(),
|
||
|
Content: slot00StorageLeafNode,
|
||
|
},
|
||
|
{
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStorageTrie, crypto.Keccak256(slot1StorageLeafNode)).String(),
|
||
|
Content: slot1StorageLeafNode,
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
{
|
||
|
"testBlock2",
|
||
|
statediff.Args{
|
||
|
OldStateRoot: block1.Root(),
|
||
|
NewStateRoot: block2.Root(),
|
||
|
BlockNumber: block2.Number(),
|
||
|
BlockHash: block2.Hash(),
|
||
|
},
|
||
|
&types2.StateObject{
|
||
|
BlockNumber: block2.Number(),
|
||
|
BlockHash: block2.Hash(),
|
||
|
Nodes: []types2.StateLeafNode{
|
||
|
{
|
||
|
Removed: false,
|
||
|
AccountWrapper: struct {
|
||
|
Account *types.StateAccount
|
||
|
LeafKey []byte
|
||
|
CID string
|
||
|
}{
|
||
|
Account: bankAccountAtBlock02,
|
||
|
LeafKey: test_helpers.BankLeafKey,
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStateTrie, crypto.Keccak256(bankAccountAtBlock02LeafNode)).String()},
|
||
|
StorageDiff: emptyStorage,
|
||
|
},
|
||
|
{
|
||
|
Removed: true,
|
||
|
AccountWrapper: struct {
|
||
|
Account *types.StateAccount
|
||
|
LeafKey []byte
|
||
|
CID string
|
||
|
}{
|
||
|
Account: nil,
|
||
|
LeafKey: contractLeafKey,
|
||
|
CID: shared.RemovedNodeStateCID},
|
||
|
StorageDiff: []types2.StorageLeafNode{
|
||
|
{
|
||
|
Removed: true,
|
||
|
LeafKey: slot0StorageKey.Bytes(),
|
||
|
CID: shared.RemovedNodeStorageCID,
|
||
|
Value: []byte{},
|
||
|
},
|
||
|
{
|
||
|
Removed: true,
|
||
|
LeafKey: slot1StorageKey.Bytes(),
|
||
|
CID: shared.RemovedNodeStorageCID,
|
||
|
Value: []byte{},
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
IPLDs: []types2.IPLD{
|
||
|
{
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStateTrie, crypto.Keccak256(bankAccountAtBlock02LeafNode)).String(),
|
||
|
Content: bankAccountAtBlock02LeafNode,
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
}
|
||
|
|
||
|
for _, test := range tests {
|
||
|
diff, err := builder.BuildStateDiffObject(test.startingArguments, params)
|
||
|
if err != nil {
|
||
|
t.Error(err)
|
||
|
}
|
||
|
receivedStateDiffRlp, err := rlp.EncodeToBytes(&diff)
|
||
|
if err != nil {
|
||
|
t.Error(err)
|
||
|
}
|
||
|
expectedStateDiffRlp, err := rlp.EncodeToBytes(test.expected)
|
||
|
if err != nil {
|
||
|
t.Error(err)
|
||
|
}
|
||
|
|
||
|
sort.Slice(receivedStateDiffRlp, func(i, j int) bool { return receivedStateDiffRlp[i] < receivedStateDiffRlp[j] })
|
||
|
sort.Slice(expectedStateDiffRlp, func(i, j int) bool { return expectedStateDiffRlp[i] < expectedStateDiffRlp[j] })
|
||
|
if !bytes.Equal(receivedStateDiffRlp, expectedStateDiffRlp) {
|
||
|
actual, err := json.Marshal(diff)
|
||
|
if err != nil {
|
||
|
t.Error(err)
|
||
|
}
|
||
|
expected, err := json.Marshal(test.expected)
|
||
|
if err != nil {
|
||
|
t.Error(err)
|
||
|
}
|
||
|
t.Logf("Test failed: %s", test.name)
|
||
|
t.Errorf("actual state diff: %s\r\n\r\n\r\nexpected state diff: %s", actual, expected)
|
||
|
}
|
||
|
}
|
||
|
// Let's also confirm that our root state nodes form the state root hash in the headers
|
||
|
if !bytes.Equal(block1.Root().Bytes(), crypto.Keccak256(block01BranchRootNode)) {
|
||
|
t.Errorf("block01 expected root %x does not match actual root %x", block1.Root().Bytes(), crypto.Keccak256(block01BranchRootNode))
|
||
|
}
|
||
|
if !bytes.Equal(block2.Root().Bytes(), crypto.Keccak256(bankAccountAtBlock02LeafNode)) {
|
||
|
t.Errorf("block02 expected root %x does not match actual root %x", block2.Root().Bytes(), crypto.Keccak256(bankAccountAtBlock02LeafNode))
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
pragma solidity ^0.5.10;
|
||
|
|
||
|
contract test {
|
||
|
address payable owner;
|
||
|
|
||
|
modifier onlyOwner {
|
||
|
require(
|
||
|
msg.sender == owner,
|
||
|
"Only owner can call this function."
|
||
|
);
|
||
|
_;
|
||
|
}
|
||
|
|
||
|
uint256[100] data;
|
||
|
|
||
|
constructor() public {
|
||
|
owner = msg.sender;
|
||
|
data = [1];
|
||
|
}
|
||
|
|
||
|
function Put(uint256 addr, uint256 value) public {
|
||
|
data[addr] = value;
|
||
|
}
|
||
|
|
||
|
function close() public onlyOwner { //onlyOwner is custom modifier
|
||
|
selfdestruct(owner); // `owner` is the owners address
|
||
|
}
|
||
|
}
|
||
|
*/
|
||
|
|
||
|
var (
|
||
|
b = big.NewInt(0).Sub(test_helpers.TestBIGBankFunds, test_helpers.BalanceChangeBIG)
|
||
|
block1BankBigBalance = big.NewInt(0).Sub(b, big.NewInt(test_helpers.GasFees2))
|
||
|
bankAccountAtBlock1b = &types.StateAccount{
|
||
|
Nonce: 1,
|
||
|
Balance: block1BankBigBalance,
|
||
|
CodeHash: test_helpers.NullCodeHash.Bytes(),
|
||
|
Root: test_helpers.EmptyContractRoot,
|
||
|
}
|
||
|
bankAccountAtBlock1bRLP, _ = rlp.EncodeToBytes(bankAccountAtBlock1b)
|
||
|
bankAccountAtBlock1bLeafNode, _ = rlp.EncodeToBytes(&[]interface{}{
|
||
|
common.Hex2Bytes("30bf49f440a1cd0527e4d06e2765654c0f56452257516d793a9b8d604dcfdf2a"),
|
||
|
bankAccountAtBlock1bRLP,
|
||
|
})
|
||
|
|
||
|
account1AtBlock1b = &types.StateAccount{
|
||
|
Nonce: 0,
|
||
|
Balance: test_helpers.Block1bAccount1Balance,
|
||
|
CodeHash: test_helpers.NullCodeHash.Bytes(),
|
||
|
Root: test_helpers.EmptyContractRoot,
|
||
|
}
|
||
|
account1AtBlock1bRLP, _ = rlp.EncodeToBytes(account1AtBlock1b)
|
||
|
account1AtBlock1bLeafNode, _ = rlp.EncodeToBytes(&[]interface{}{
|
||
|
common.Hex2Bytes("3926db69aaced518e9b9f0f434a473e7174109c943548bb8f23be41ca76d9ad2"),
|
||
|
account1AtBlock1bRLP,
|
||
|
})
|
||
|
|
||
|
account1AtBlock2bBalance, _ = big.NewInt(0).SetString("1999999999999999999999999761539571000000000", 10)
|
||
|
account1AtBlock2b = &types.StateAccount{
|
||
|
Nonce: 1,
|
||
|
Balance: account1AtBlock2bBalance,
|
||
|
CodeHash: test_helpers.NullCodeHash.Bytes(),
|
||
|
Root: test_helpers.EmptyContractRoot,
|
||
|
}
|
||
|
account1AtBlock2bRLP, _ = rlp.EncodeToBytes(account1AtBlock2b)
|
||
|
account1AtBlock2bLeafNode, _ = rlp.EncodeToBytes(&[]interface{}{
|
||
|
common.Hex2Bytes("3926db69aaced518e9b9f0f434a473e7174109c943548bb8f23be41ca76d9ad2"),
|
||
|
account1AtBlock2bRLP,
|
||
|
})
|
||
|
|
||
|
minerAccountAtBlock2b = &types.StateAccount{
|
||
|
Nonce: 0,
|
||
|
Balance: big.NewInt(4055891787808414571),
|
||
|
CodeHash: test_helpers.NullCodeHash.Bytes(),
|
||
|
Root: test_helpers.EmptyContractRoot,
|
||
|
}
|
||
|
minerAccountAtBlock2bRLP, _ = rlp.EncodeToBytes(minerAccountAtBlock2b)
|
||
|
minerAccountAtBlock2bLeafNode, _ = rlp.EncodeToBytes(&[]interface{}{
|
||
|
common.Hex2Bytes("3380c7b7ae81a58eb98d9c78de4a1fd7fd9535fc953ed2be602daaa41767312a"),
|
||
|
minerAccountAtBlock2bRLP,
|
||
|
})
|
||
|
|
||
|
contractAccountAtBlock2b = &types.StateAccount{
|
||
|
Nonce: 1,
|
||
|
Balance: big.NewInt(0),
|
||
|
CodeHash: test_helpers.CodeHashForInternalizedLeafNode.Bytes(),
|
||
|
Root: crypto.Keccak256Hash(block2StorageBranchRootNode),
|
||
|
}
|
||
|
contractAccountAtBlock2bRLP, _ = rlp.EncodeToBytes(contractAccountAtBlock2b)
|
||
|
contractAccountAtBlock2bLeafNode, _ = rlp.EncodeToBytes(&[]interface{}{
|
||
|
common.Hex2Bytes("3d7e14f1723fa19b5d6d9f8b86b49acefbc9c400bf4ed686c10d6b6467fc5b3a"),
|
||
|
contractAccountAtBlock2bRLP,
|
||
|
})
|
||
|
|
||
|
bankAccountAtBlock3bBalance, _ = big.NewInt(0).SetString("18000000000000000000000001999920365757724976", 10)
|
||
|
bankAccountAtBlock3b = &types.StateAccount{
|
||
|
Nonce: 3,
|
||
|
Balance: bankAccountAtBlock3bBalance,
|
||
|
CodeHash: test_helpers.NullCodeHash.Bytes(),
|
||
|
Root: test_helpers.EmptyContractRoot,
|
||
|
}
|
||
|
bankAccountAtBlock3bRLP, _ = rlp.EncodeToBytes(bankAccountAtBlock3b)
|
||
|
bankAccountAtBlock3bLeafNode, _ = rlp.EncodeToBytes(&[]interface{}{
|
||
|
common.Hex2Bytes("30bf49f440a1cd0527e4d06e2765654c0f56452257516d793a9b8d604dcfdf2a"),
|
||
|
bankAccountAtBlock3bRLP,
|
||
|
})
|
||
|
|
||
|
contractAccountAtBlock3b = &types.StateAccount{
|
||
|
Nonce: 1,
|
||
|
Balance: big.NewInt(0),
|
||
|
CodeHash: test_helpers.CodeHashForInternalizedLeafNode.Bytes(),
|
||
|
Root: crypto.Keccak256Hash(block3bStorageBranchRootNode),
|
||
|
}
|
||
|
contractAccountAtBlock3bRLP, _ = rlp.EncodeToBytes(contractAccountAtBlock3b)
|
||
|
contractAccountAtBlock3bLeafNode, _ = rlp.EncodeToBytes(&[]interface{}{
|
||
|
common.Hex2Bytes("3d7e14f1723fa19b5d6d9f8b86b49acefbc9c400bf4ed686c10d6b6467fc5b3a"),
|
||
|
contractAccountAtBlock3bRLP,
|
||
|
})
|
||
|
|
||
|
slot40364 = common.BigToHash(big.NewInt(40364))
|
||
|
slot105566 = common.BigToHash(big.NewInt(105566))
|
||
|
|
||
|
slot40364StorageValue = common.Hex2Bytes("01")
|
||
|
slot105566StorageValue = common.Hex2Bytes("02")
|
||
|
|
||
|
slot40364StorageKey = crypto.Keccak256Hash(slot40364[:])
|
||
|
slot105566StorageKey = crypto.Keccak256Hash(slot105566[:])
|
||
|
|
||
|
slot40364StorageInternalLeafNode = []interface{}{
|
||
|
common.Hex2Bytes("3077bbc951a04529defc15da8c06e427cde0d7a1499c50975bbe8aab"),
|
||
|
slot40364StorageValue,
|
||
|
}
|
||
|
slot105566StorageInternalLeafNode = []interface{}{
|
||
|
common.Hex2Bytes("3c62586c18bf1ecfda161ced374b7a894630e2db426814c24e5d42af"),
|
||
|
slot105566StorageValue,
|
||
|
}
|
||
|
|
||
|
block3bStorageBranchRootNode, _ = rlp.EncodeToBytes(&[]interface{}{
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
crypto.Keccak256(slot0StorageLeafNode),
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
crypto.Keccak256(slot1StorageLeafNode),
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
crypto.Keccak256(block3bStorageExtensionNode),
|
||
|
[]byte{},
|
||
|
})
|
||
|
|
||
|
block3bStorageExtensionNode, _ = rlp.EncodeToBytes(&[]interface{}{
|
||
|
common.Hex2Bytes("1291631c"),
|
||
|
crypto.Keccak256(block3bStorageBranchNodeWithInternalLeaves),
|
||
|
})
|
||
|
|
||
|
block3bStorageBranchNodeWithInternalLeaves, _ = rlp.EncodeToBytes(&[]interface{}{
|
||
|
slot105566StorageInternalLeafNode,
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
slot40364StorageInternalLeafNode,
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
})
|
||
|
|
||
|
block1bBranchRootNode, _ = rlp.EncodeToBytes(&[]interface{}{
|
||
|
crypto.Keccak256(bankAccountAtBlock1bLeafNode),
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
crypto.Keccak256(minerAccountAtBlock1LeafNode),
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
crypto.Keccak256(account1AtBlock1bLeafNode),
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
})
|
||
|
|
||
|
block2bBranchRootNode, _ = rlp.EncodeToBytes(&[]interface{}{
|
||
|
crypto.Keccak256(bankAccountAtBlock1bLeafNode),
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
crypto.Keccak256(minerAccountAtBlock2bLeafNode),
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
crypto.Keccak256(account1AtBlock2bLeafNode),
|
||
|
crypto.Keccak256(contractAccountAtBlock2bLeafNode),
|
||
|
[]byte{},
|
||
|
})
|
||
|
|
||
|
block3bBranchRootNode, _ = rlp.EncodeToBytes(&[]interface{}{
|
||
|
crypto.Keccak256(bankAccountAtBlock3bLeafNode),
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
crypto.Keccak256(minerAccountAtBlock2bLeafNode),
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
[]byte{},
|
||
|
crypto.Keccak256(account1AtBlock2bLeafNode),
|
||
|
crypto.Keccak256(contractAccountAtBlock3bLeafNode),
|
||
|
[]byte{},
|
||
|
})
|
||
|
)
|
||
|
|
||
|
func TestBuilderWithInternalizedLeafNode(t *testing.T) {
|
||
|
blocks, chain := test_helpers.MakeChain(3, test_helpers.GenesisForInternalLeafNodeTest, test_helpers.TestChainGenWithInternalLeafNode)
|
||
|
contractLeafKey = test_helpers.AddressToLeafKey(test_helpers.ContractAddr)
|
||
|
defer chain.Stop()
|
||
|
block0 = test_helpers.Genesis
|
||
|
block1 = blocks[0]
|
||
|
block2 = blocks[1]
|
||
|
block3 = blocks[2]
|
||
|
params := statediff.Params{}
|
||
|
builder = statediff.NewBuilder(chain.StateCache())
|
||
|
|
||
|
var tests = []struct {
|
||
|
name string
|
||
|
startingArguments statediff.Args
|
||
|
expected *types2.StateObject
|
||
|
}{
|
||
|
{
|
||
|
"testEmptyDiff",
|
||
|
statediff.Args{
|
||
|
OldStateRoot: block0.Root(),
|
||
|
NewStateRoot: block0.Root(),
|
||
|
BlockNumber: block0.Number(),
|
||
|
BlockHash: block0.Hash(),
|
||
|
},
|
||
|
&types2.StateObject{
|
||
|
BlockNumber: block0.Number(),
|
||
|
BlockHash: block0.Hash(),
|
||
|
Nodes: emptyDiffs,
|
||
|
},
|
||
|
},
|
||
|
{
|
||
|
"testBlock0",
|
||
|
//10000 transferred from testBankAddress to account1Addr
|
||
|
statediff.Args{
|
||
|
OldStateRoot: test_helpers.NullHash,
|
||
|
NewStateRoot: block0.Root(),
|
||
|
BlockNumber: block0.Number(),
|
||
|
BlockHash: block0.Hash(),
|
||
|
},
|
||
|
&types2.StateObject{
|
||
|
BlockNumber: block0.Number(),
|
||
|
BlockHash: block0.Hash(),
|
||
|
Nodes: []types2.StateLeafNode{
|
||
|
{
|
||
|
Removed: false,
|
||
|
AccountWrapper: struct {
|
||
|
Account *types.StateAccount
|
||
|
LeafKey []byte
|
||
|
CID string
|
||
|
}{
|
||
|
Account: bankAccountAtBlock0,
|
||
|
LeafKey: test_helpers.BankLeafKey,
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStateTrie, crypto.Keccak256(bankAccountAtBlock0LeafNode)).String()},
|
||
|
StorageDiff: emptyStorage,
|
||
|
},
|
||
|
},
|
||
|
IPLDs: []types2.IPLD{
|
||
|
{
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStateTrie, crypto.Keccak256(bankAccountAtBlock0LeafNode)).String(),
|
||
|
Content: bankAccountAtBlock0LeafNode,
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
{
|
||
|
"testBlock1",
|
||
|
//10000 transferred from testBankAddress to account1Addr
|
||
|
statediff.Args{
|
||
|
OldStateRoot: block0.Root(),
|
||
|
NewStateRoot: block1.Root(),
|
||
|
BlockNumber: block1.Number(),
|
||
|
BlockHash: block1.Hash(),
|
||
|
},
|
||
|
&types2.StateObject{
|
||
|
BlockNumber: block1.Number(),
|
||
|
BlockHash: block1.Hash(),
|
||
|
Nodes: []types2.StateLeafNode{
|
||
|
{
|
||
|
Removed: false,
|
||
|
AccountWrapper: struct {
|
||
|
Account *types.StateAccount
|
||
|
LeafKey []byte
|
||
|
CID string
|
||
|
}{
|
||
|
Account: bankAccountAtBlock1b,
|
||
|
LeafKey: test_helpers.BankLeafKey,
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStateTrie, crypto.Keccak256(bankAccountAtBlock1bLeafNode)).String()},
|
||
|
StorageDiff: emptyStorage,
|
||
|
},
|
||
|
{
|
||
|
Removed: false,
|
||
|
AccountWrapper: struct {
|
||
|
Account *types.StateAccount
|
||
|
LeafKey []byte
|
||
|
CID string
|
||
|
}{
|
||
|
Account: minerAccountAtBlock1,
|
||
|
LeafKey: minerLeafKey,
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStateTrie, crypto.Keccak256(minerAccountAtBlock1LeafNode)).String()},
|
||
|
StorageDiff: emptyStorage,
|
||
|
},
|
||
|
{
|
||
|
Removed: false,
|
||
|
AccountWrapper: struct {
|
||
|
Account *types.StateAccount
|
||
|
LeafKey []byte
|
||
|
CID string
|
||
|
}{
|
||
|
Account: account1AtBlock1b,
|
||
|
LeafKey: test_helpers.Account1LeafKey,
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStateTrie, crypto.Keccak256(account1AtBlock1bLeafNode)).String()},
|
||
|
StorageDiff: emptyStorage,
|
||
|
},
|
||
|
},
|
||
|
IPLDs: []types2.IPLD{
|
||
|
{
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStateTrie, crypto.Keccak256(block1bBranchRootNode)).String(),
|
||
|
Content: block1bBranchRootNode,
|
||
|
},
|
||
|
{
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStateTrie, crypto.Keccak256(bankAccountAtBlock1bLeafNode)).String(),
|
||
|
Content: bankAccountAtBlock1bLeafNode,
|
||
|
},
|
||
|
{
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStateTrie, crypto.Keccak256(minerAccountAtBlock1LeafNode)).String(),
|
||
|
Content: minerAccountAtBlock1LeafNode,
|
||
|
},
|
||
|
{
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStateTrie, crypto.Keccak256(account1AtBlock1bLeafNode)).String(),
|
||
|
Content: account1AtBlock1bLeafNode,
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
{
|
||
|
"testBlock2",
|
||
|
// 1000 transferred from testBankAddress to account1Addr
|
||
|
// 1000 transferred from account1Addr to account2Addr
|
||
|
// account1addr creates a new contract
|
||
|
statediff.Args{
|
||
|
OldStateRoot: block1.Root(),
|
||
|
NewStateRoot: block2.Root(),
|
||
|
BlockNumber: block2.Number(),
|
||
|
BlockHash: block2.Hash(),
|
||
|
},
|
||
|
&types2.StateObject{
|
||
|
BlockNumber: block2.Number(),
|
||
|
BlockHash: block2.Hash(),
|
||
|
Nodes: []types2.StateLeafNode{
|
||
|
{
|
||
|
Removed: false,
|
||
|
AccountWrapper: struct {
|
||
|
Account *types.StateAccount
|
||
|
LeafKey []byte
|
||
|
CID string
|
||
|
}{
|
||
|
Account: minerAccountAtBlock2b,
|
||
|
LeafKey: minerLeafKey,
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStateTrie, crypto.Keccak256(minerAccountAtBlock2bLeafNode)).String()},
|
||
|
StorageDiff: emptyStorage,
|
||
|
},
|
||
|
{
|
||
|
Removed: false,
|
||
|
AccountWrapper: struct {
|
||
|
Account *types.StateAccount
|
||
|
LeafKey []byte
|
||
|
CID string
|
||
|
}{
|
||
|
Account: account1AtBlock2b,
|
||
|
LeafKey: test_helpers.Account1LeafKey,
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStateTrie, crypto.Keccak256(account1AtBlock2bLeafNode)).String()},
|
||
|
StorageDiff: emptyStorage,
|
||
|
},
|
||
|
{
|
||
|
Removed: false,
|
||
|
AccountWrapper: struct {
|
||
|
Account *types.StateAccount
|
||
|
LeafKey []byte
|
||
|
CID string
|
||
|
}{
|
||
|
Account: contractAccountAtBlock2b,
|
||
|
LeafKey: contractLeafKey,
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStateTrie, crypto.Keccak256(contractAccountAtBlock2bLeafNode)).String()},
|
||
|
StorageDiff: []types2.StorageLeafNode{
|
||
|
{
|
||
|
Removed: false,
|
||
|
Value: slot0StorageValue,
|
||
|
LeafKey: slot0StorageKey.Bytes(),
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStorageTrie, crypto.Keccak256(slot0StorageLeafNode)).String(),
|
||
|
},
|
||
|
{
|
||
|
Removed: false,
|
||
|
Value: slot1StorageValue,
|
||
|
LeafKey: slot1StorageKey.Bytes(),
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStorageTrie, crypto.Keccak256(slot1StorageLeafNode)).String(),
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
IPLDs: []types2.IPLD{
|
||
|
{
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.RawBinary, test_helpers.CodeHashForInternalizedLeafNode.Bytes()).String(),
|
||
|
Content: test_helpers.ByteCodeAfterDeploymentForInternalLeafNode,
|
||
|
},
|
||
|
{
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStateTrie, crypto.Keccak256(block2bBranchRootNode)).String(),
|
||
|
Content: block2bBranchRootNode,
|
||
|
},
|
||
|
{
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStateTrie, crypto.Keccak256(minerAccountAtBlock2bLeafNode)).String(),
|
||
|
Content: minerAccountAtBlock2bLeafNode,
|
||
|
},
|
||
|
{
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStateTrie, crypto.Keccak256(account1AtBlock2bLeafNode)).String(),
|
||
|
Content: account1AtBlock2bLeafNode,
|
||
|
},
|
||
|
{
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStateTrie, crypto.Keccak256(contractAccountAtBlock2bLeafNode)).String(),
|
||
|
Content: contractAccountAtBlock2bLeafNode,
|
||
|
},
|
||
|
{
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStorageTrie, crypto.Keccak256(block2StorageBranchRootNode)).String(),
|
||
|
Content: block2StorageBranchRootNode,
|
||
|
},
|
||
|
{
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStorageTrie, crypto.Keccak256(slot0StorageLeafNode)).String(),
|
||
|
Content: slot0StorageLeafNode,
|
||
|
},
|
||
|
{
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStorageTrie, crypto.Keccak256(slot1StorageLeafNode)).String(),
|
||
|
Content: slot1StorageLeafNode,
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
{
|
||
|
"testBlock3",
|
||
|
//the contract's storage is changed
|
||
|
//and the block is mined by account 2
|
||
|
statediff.Args{
|
||
|
OldStateRoot: block2.Root(),
|
||
|
NewStateRoot: block3.Root(),
|
||
|
BlockNumber: block3.Number(),
|
||
|
BlockHash: block3.Hash(),
|
||
|
},
|
||
|
&types2.StateObject{
|
||
|
BlockNumber: block3.Number(),
|
||
|
BlockHash: block3.Hash(),
|
||
|
Nodes: []types2.StateLeafNode{
|
||
|
{
|
||
|
Removed: false,
|
||
|
AccountWrapper: struct {
|
||
|
Account *types.StateAccount
|
||
|
LeafKey []byte
|
||
|
CID string
|
||
|
}{
|
||
|
Account: bankAccountAtBlock3b,
|
||
|
LeafKey: test_helpers.BankLeafKey,
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStateTrie, crypto.Keccak256(bankAccountAtBlock3bLeafNode)).String()},
|
||
|
StorageDiff: emptyStorage,
|
||
|
},
|
||
|
{
|
||
|
Removed: false,
|
||
|
AccountWrapper: struct {
|
||
|
Account *types.StateAccount
|
||
|
LeafKey []byte
|
||
|
CID string
|
||
|
}{
|
||
|
Account: contractAccountAtBlock3b,
|
||
|
LeafKey: contractLeafKey,
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStateTrie, crypto.Keccak256(contractAccountAtBlock3bLeafNode)).String()},
|
||
|
StorageDiff: []types2.StorageLeafNode{
|
||
|
{
|
||
|
Removed: false,
|
||
|
Value: slot105566StorageValue,
|
||
|
LeafKey: slot105566StorageKey.Bytes(),
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStorageTrie, crypto.Keccak256(block3bStorageBranchNodeWithInternalLeaves)).String(),
|
||
|
},
|
||
|
{
|
||
|
Removed: false,
|
||
|
Value: slot40364StorageValue,
|
||
|
LeafKey: slot40364StorageKey.Bytes(),
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStorageTrie, crypto.Keccak256(block3bStorageBranchNodeWithInternalLeaves)).String(),
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
IPLDs: []types2.IPLD{
|
||
|
{
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStateTrie, crypto.Keccak256(block3bBranchRootNode)).String(),
|
||
|
Content: block3bBranchRootNode,
|
||
|
},
|
||
|
{
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStateTrie, crypto.Keccak256(bankAccountAtBlock3bLeafNode)).String(),
|
||
|
Content: bankAccountAtBlock3bLeafNode,
|
||
|
},
|
||
|
{
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStateTrie, crypto.Keccak256(contractAccountAtBlock3bLeafNode)).String(),
|
||
|
Content: contractAccountAtBlock3bLeafNode,
|
||
|
},
|
||
|
{
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStorageTrie, crypto.Keccak256(block3bStorageBranchRootNode)).String(),
|
||
|
Content: block3bStorageBranchRootNode,
|
||
|
},
|
||
|
{
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStorageTrie, crypto.Keccak256(block3bStorageExtensionNode)).String(),
|
||
|
Content: block3bStorageExtensionNode,
|
||
|
},
|
||
|
{
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStorageTrie, crypto.Keccak256(block3bStorageBranchNodeWithInternalLeaves)).String(),
|
||
|
Content: block3bStorageBranchNodeWithInternalLeaves,
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
}
|
||
|
|
||
|
for _, test := range tests {
|
||
|
diff, err := builder.BuildStateDiffObject(test.startingArguments, params)
|
||
|
if err != nil {
|
||
|
t.Error(err)
|
||
|
}
|
||
|
receivedStateDiffRlp, err := rlp.EncodeToBytes(&diff)
|
||
|
if err != nil {
|
||
|
t.Error(err)
|
||
|
}
|
||
|
expectedStateDiffRlp, err := rlp.EncodeToBytes(test.expected)
|
||
|
if err != nil {
|
||
|
t.Error(err)
|
||
|
}
|
||
|
sort.Slice(receivedStateDiffRlp, func(i, j int) bool { return receivedStateDiffRlp[i] < receivedStateDiffRlp[j] })
|
||
|
sort.Slice(expectedStateDiffRlp, func(i, j int) bool { return expectedStateDiffRlp[i] < expectedStateDiffRlp[j] })
|
||
|
if !bytes.Equal(receivedStateDiffRlp, expectedStateDiffRlp) {
|
||
|
actual, err := json.Marshal(diff)
|
||
|
if err != nil {
|
||
|
t.Error(err)
|
||
|
}
|
||
|
expected, err := json.Marshal(test.expected)
|
||
|
if err != nil {
|
||
|
t.Error(err)
|
||
|
}
|
||
|
t.Logf("Test failed: %s", test.name)
|
||
|
t.Errorf("actual state diff: %s\r\n\r\n\r\nexpected state diff: %s", actual, expected)
|
||
|
}
|
||
|
}
|
||
|
// Let's also confirm that our root state nodes form the state root hash in the headers
|
||
|
if !bytes.Equal(block1.Root().Bytes(), crypto.Keccak256(block1bBranchRootNode)) {
|
||
|
t.Errorf("block1 expected root %x does not match actual root %x", block1.Root().Bytes(), crypto.Keccak256(block1bBranchRootNode))
|
||
|
}
|
||
|
if !bytes.Equal(block2.Root().Bytes(), crypto.Keccak256(block2bBranchRootNode)) {
|
||
|
t.Errorf("block2 expected root %x does not match actual root %x", block2.Root().Bytes(), crypto.Keccak256(block2bBranchRootNode))
|
||
|
}
|
||
|
if !bytes.Equal(block3.Root().Bytes(), crypto.Keccak256(block3bBranchRootNode)) {
|
||
|
t.Errorf("block3 expected root %x does not match actual root %x", block3.Root().Bytes(), crypto.Keccak256(block3bBranchRootNode))
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func TestBuilderWithInternalizedLeafNodeAndWatchedAddress(t *testing.T) {
|
||
|
blocks, chain := test_helpers.MakeChain(3, test_helpers.GenesisForInternalLeafNodeTest, test_helpers.TestChainGenWithInternalLeafNode)
|
||
|
contractLeafKey = test_helpers.AddressToLeafKey(test_helpers.ContractAddr)
|
||
|
defer chain.Stop()
|
||
|
block0 = test_helpers.Genesis
|
||
|
block1 = blocks[0]
|
||
|
block2 = blocks[1]
|
||
|
block3 = blocks[2]
|
||
|
params := statediff.Params{
|
||
|
WatchedAddresses: []common.Address{
|
||
|
test_helpers.ContractAddr,
|
||
|
},
|
||
|
}
|
||
|
params.ComputeWatchedAddressesLeafPaths()
|
||
|
builder = statediff.NewBuilder(chain.StateCache())
|
||
|
|
||
|
var tests = []struct {
|
||
|
name string
|
||
|
startingArguments statediff.Args
|
||
|
expected *types2.StateObject
|
||
|
}{
|
||
|
{
|
||
|
"testEmptyDiff",
|
||
|
statediff.Args{
|
||
|
OldStateRoot: block0.Root(),
|
||
|
NewStateRoot: block0.Root(),
|
||
|
BlockNumber: block0.Number(),
|
||
|
BlockHash: block0.Hash(),
|
||
|
},
|
||
|
&types2.StateObject{
|
||
|
BlockNumber: block0.Number(),
|
||
|
BlockHash: block0.Hash(),
|
||
|
Nodes: emptyDiffs,
|
||
|
},
|
||
|
},
|
||
|
{
|
||
|
"testBlock0",
|
||
|
//10000 transferred from testBankAddress to account1Addr
|
||
|
statediff.Args{
|
||
|
OldStateRoot: test_helpers.NullHash,
|
||
|
NewStateRoot: block0.Root(),
|
||
|
BlockNumber: block0.Number(),
|
||
|
BlockHash: block0.Hash(),
|
||
|
},
|
||
|
&types2.StateObject{
|
||
|
BlockNumber: block0.Number(),
|
||
|
BlockHash: block0.Hash(),
|
||
|
Nodes: []types2.StateLeafNode{},
|
||
|
IPLDs: []types2.IPLD{}, // there's some kind of weird behavior where if our root node is a leaf node
|
||
|
// even though it is along the path to the watched leaf (necessarily, as it is the root) it doesn't get included
|
||
|
// unconsequential, but kinda odd.
|
||
|
},
|
||
|
},
|
||
|
{
|
||
|
"testBlock1",
|
||
|
//10000 transferred from testBankAddress to account1Addr
|
||
|
statediff.Args{
|
||
|
OldStateRoot: block0.Root(),
|
||
|
NewStateRoot: block1.Root(),
|
||
|
BlockNumber: block1.Number(),
|
||
|
BlockHash: block1.Hash(),
|
||
|
},
|
||
|
&types2.StateObject{
|
||
|
BlockNumber: block1.Number(),
|
||
|
BlockHash: block1.Hash(),
|
||
|
Nodes: []types2.StateLeafNode{},
|
||
|
IPLDs: []types2.IPLD{
|
||
|
{
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStateTrie, crypto.Keccak256(block1bBranchRootNode)).String(),
|
||
|
Content: block1bBranchRootNode,
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
{
|
||
|
"testBlock2",
|
||
|
// 1000 transferred from testBankAddress to account1Addr
|
||
|
// 1000 transferred from account1Addr to account2Addr
|
||
|
// account1addr creates a new contract
|
||
|
statediff.Args{
|
||
|
OldStateRoot: block1.Root(),
|
||
|
NewStateRoot: block2.Root(),
|
||
|
BlockNumber: block2.Number(),
|
||
|
BlockHash: block2.Hash(),
|
||
|
},
|
||
|
&types2.StateObject{
|
||
|
BlockNumber: block2.Number(),
|
||
|
BlockHash: block2.Hash(),
|
||
|
Nodes: []types2.StateLeafNode{
|
||
|
{
|
||
|
Removed: false,
|
||
|
AccountWrapper: struct {
|
||
|
Account *types.StateAccount
|
||
|
LeafKey []byte
|
||
|
CID string
|
||
|
}{
|
||
|
Account: contractAccountAtBlock2b,
|
||
|
LeafKey: contractLeafKey,
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStateTrie, crypto.Keccak256(contractAccountAtBlock2bLeafNode)).String()},
|
||
|
StorageDiff: []types2.StorageLeafNode{
|
||
|
{
|
||
|
Removed: false,
|
||
|
Value: slot0StorageValue,
|
||
|
LeafKey: slot0StorageKey.Bytes(),
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStorageTrie, crypto.Keccak256(slot0StorageLeafNode)).String(),
|
||
|
},
|
||
|
{
|
||
|
Removed: false,
|
||
|
Value: slot1StorageValue,
|
||
|
LeafKey: slot1StorageKey.Bytes(),
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStorageTrie, crypto.Keccak256(slot1StorageLeafNode)).String(),
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
IPLDs: []types2.IPLD{
|
||
|
{
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.RawBinary, test_helpers.CodeHashForInternalizedLeafNode.Bytes()).String(),
|
||
|
Content: test_helpers.ByteCodeAfterDeploymentForInternalLeafNode,
|
||
|
},
|
||
|
{
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStateTrie, crypto.Keccak256(block2bBranchRootNode)).String(),
|
||
|
Content: block2bBranchRootNode,
|
||
|
},
|
||
|
{
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStateTrie, crypto.Keccak256(contractAccountAtBlock2bLeafNode)).String(),
|
||
|
Content: contractAccountAtBlock2bLeafNode,
|
||
|
},
|
||
|
{
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStorageTrie, crypto.Keccak256(block2StorageBranchRootNode)).String(),
|
||
|
Content: block2StorageBranchRootNode,
|
||
|
},
|
||
|
{
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStorageTrie, crypto.Keccak256(slot0StorageLeafNode)).String(),
|
||
|
Content: slot0StorageLeafNode,
|
||
|
},
|
||
|
{
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStorageTrie, crypto.Keccak256(slot1StorageLeafNode)).String(),
|
||
|
Content: slot1StorageLeafNode,
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
{
|
||
|
"testBlock3",
|
||
|
//the contract's storage is changed
|
||
|
//and the block is mined by account 2
|
||
|
statediff.Args{
|
||
|
OldStateRoot: block2.Root(),
|
||
|
NewStateRoot: block3.Root(),
|
||
|
BlockNumber: block3.Number(),
|
||
|
BlockHash: block3.Hash(),
|
||
|
},
|
||
|
&types2.StateObject{
|
||
|
BlockNumber: block3.Number(),
|
||
|
BlockHash: block3.Hash(),
|
||
|
Nodes: []types2.StateLeafNode{
|
||
|
{
|
||
|
Removed: false,
|
||
|
AccountWrapper: struct {
|
||
|
Account *types.StateAccount
|
||
|
LeafKey []byte
|
||
|
CID string
|
||
|
}{
|
||
|
Account: contractAccountAtBlock3b,
|
||
|
LeafKey: contractLeafKey,
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStateTrie, crypto.Keccak256(contractAccountAtBlock3bLeafNode)).String()},
|
||
|
StorageDiff: []types2.StorageLeafNode{
|
||
|
{
|
||
|
Removed: false,
|
||
|
Value: slot105566StorageValue,
|
||
|
LeafKey: slot105566StorageKey.Bytes(),
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStorageTrie, crypto.Keccak256(block3bStorageBranchNodeWithInternalLeaves)).String(),
|
||
|
},
|
||
|
{
|
||
|
Removed: false,
|
||
|
Value: slot40364StorageValue,
|
||
|
LeafKey: slot40364StorageKey.Bytes(),
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStorageTrie, crypto.Keccak256(block3bStorageBranchNodeWithInternalLeaves)).String(),
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
IPLDs: []types2.IPLD{
|
||
|
{
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStateTrie, crypto.Keccak256(block3bBranchRootNode)).String(),
|
||
|
Content: block3bBranchRootNode,
|
||
|
},
|
||
|
{
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStateTrie, crypto.Keccak256(contractAccountAtBlock3bLeafNode)).String(),
|
||
|
Content: contractAccountAtBlock3bLeafNode,
|
||
|
},
|
||
|
{
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStorageTrie, crypto.Keccak256(block3bStorageBranchRootNode)).String(),
|
||
|
Content: block3bStorageBranchRootNode,
|
||
|
},
|
||
|
{
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStorageTrie, crypto.Keccak256(block3bStorageExtensionNode)).String(),
|
||
|
Content: block3bStorageExtensionNode,
|
||
|
},
|
||
|
{
|
||
|
CID: ipld2.Keccak256ToCid(ipld2.MEthStorageTrie, crypto.Keccak256(block3bStorageBranchNodeWithInternalLeaves)).String(),
|
||
|
Content: block3bStorageBranchNodeWithInternalLeaves,
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
}
|
||
|
|
||
|
for _, test := range tests {
|
||
|
diff, err := builder.BuildStateDiffObject(test.startingArguments, params)
|
||
|
if err != nil {
|
||
|
t.Error(err)
|
||
|
}
|
||
|
receivedStateDiffRlp, err := rlp.EncodeToBytes(&diff)
|
||
|
if err != nil {
|
||
|
t.Error(err)
|
||
|
}
|
||
|
expectedStateDiffRlp, err := rlp.EncodeToBytes(test.expected)
|
||
|
if err != nil {
|
||
|
t.Error(err)
|
||
|
}
|
||
|
sort.Slice(receivedStateDiffRlp, func(i, j int) bool { return receivedStateDiffRlp[i] < receivedStateDiffRlp[j] })
|
||
|
sort.Slice(expectedStateDiffRlp, func(i, j int) bool { return expectedStateDiffRlp[i] < expectedStateDiffRlp[j] })
|
||
|
if !bytes.Equal(receivedStateDiffRlp, expectedStateDiffRlp) {
|
||
|
actual, err := json.Marshal(diff)
|
||
|
if err != nil {
|
||
|
t.Error(err)
|
||
|
}
|
||
|
expected, err := json.Marshal(test.expected)
|
||
|
if err != nil {
|
||
|
t.Error(err)
|
||
|
}
|
||
|
t.Logf("Test failed: %s", test.name)
|
||
|
t.Errorf("actual state diff: %s\r\n\r\n\r\nexpected state diff: %s", actual, expected)
|
||
|
}
|
||
|
}
|
||
|
// Let's also confirm that our root state nodes form the state root hash in the headers
|
||
|
if !bytes.Equal(block1.Root().Bytes(), crypto.Keccak256(block1bBranchRootNode)) {
|
||
|
t.Errorf("block1 expected root %x does not match actual root %x", block1.Root().Bytes(), crypto.Keccak256(block1bBranchRootNode))
|
||
|
}
|
||
|
if !bytes.Equal(block2.Root().Bytes(), crypto.Keccak256(block2bBranchRootNode)) {
|
||
|
t.Errorf("block2 expected root %x does not match actual root %x", block2.Root().Bytes(), crypto.Keccak256(block2bBranchRootNode))
|
||
|
}
|
||
|
if !bytes.Equal(block3.Root().Bytes(), crypto.Keccak256(block3bBranchRootNode)) {
|
||
|
t.Errorf("block3 expected root %x does not match actual root %x", block3.Root().Bytes(), crypto.Keccak256(block3bBranchRootNode))
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
pragma solidity ^0.5.10;
|
||
|
|
||
|
contract test {
|
||
|
address payable owner;
|
||
|
|
||
|
modifier onlyOwner {
|
||
|
require(
|
||
|
msg.sender == owner,
|
||
|
"Only owner can call this function."
|
||
|
);
|
||
|
_;
|
||
|
}
|
||
|
|
||
|
uint256[105566] data;
|
||
|
|
||
|
constructor() public {
|
||
|
owner = msg.sender;
|
||
|
data = [1];
|
||
|
}
|
||
|
|
||
|
function Put(uint256 addr, uint256 value) public {
|
||
|
data[addr] = value;
|
||
|
}
|
||
|
|
||
|
function close() public onlyOwner { //onlyOwner is custom modifier
|
||
|
selfdestruct(owner); // `owner` is the owners address
|
||
|
}
|
||
|
}
|
||
|
*/
|