mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-19 02:12:23 +00:00
core, trie: import remaining state processor tests
Co-authored-by: Ignacio Hagopian <jsign.uy@gmail.com>
This commit is contained in:
parent
6c6bf6fe64
commit
c637d308c5
2 changed files with 941 additions and 16 deletions
|
|
@ -17,6 +17,7 @@
|
||||||
package core
|
package core
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"crypto/ecdsa"
|
"crypto/ecdsa"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"math"
|
"math"
|
||||||
|
|
@ -36,6 +37,7 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
"github.com/ethereum/go-ethereum/trie"
|
"github.com/ethereum/go-ethereum/trie"
|
||||||
|
"github.com/ethereum/go-ethereum/trie/utils"
|
||||||
"github.com/ethereum/go-ethereum/triedb"
|
"github.com/ethereum/go-ethereum/triedb"
|
||||||
"github.com/ethereum/go-verkle"
|
"github.com/ethereum/go-verkle"
|
||||||
"github.com/holiman/uint256"
|
"github.com/holiman/uint256"
|
||||||
|
|
@ -616,3 +618,942 @@ func getParentBlockHash(statedb *state.StateDB, number uint64) common.Hash {
|
||||||
binary.BigEndian.PutUint64(key[24:], ringIndex)
|
binary.BigEndian.PutUint64(key[24:], ringIndex)
|
||||||
return statedb.GetState(params.HistoryStorageAddress, key)
|
return statedb.GetState(params.HistoryStorageAddress, key)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestProcessVerkleInvalidContractCreation(t *testing.T) {
|
||||||
|
var (
|
||||||
|
config = ¶ms.ChainConfig{
|
||||||
|
ChainID: big.NewInt(69420),
|
||||||
|
HomesteadBlock: big.NewInt(0),
|
||||||
|
EIP150Block: big.NewInt(0),
|
||||||
|
EIP155Block: big.NewInt(0),
|
||||||
|
EIP158Block: big.NewInt(0),
|
||||||
|
ByzantiumBlock: big.NewInt(0),
|
||||||
|
ConstantinopleBlock: big.NewInt(0),
|
||||||
|
PetersburgBlock: big.NewInt(0),
|
||||||
|
IstanbulBlock: big.NewInt(0),
|
||||||
|
MuirGlacierBlock: big.NewInt(0),
|
||||||
|
BerlinBlock: big.NewInt(0),
|
||||||
|
LondonBlock: big.NewInt(0),
|
||||||
|
Ethash: new(params.EthashConfig),
|
||||||
|
ShanghaiTime: u64(0),
|
||||||
|
VerkleTime: u64(0),
|
||||||
|
TerminalTotalDifficulty: common.Big0,
|
||||||
|
TerminalTotalDifficultyPassed: true,
|
||||||
|
}
|
||||||
|
coinbase = common.HexToAddress("0x71562b71999873DB5b286dF957af199Ec94617F7")
|
||||||
|
account1 = common.HexToAddress("0x687704DB07e902e9A8B3754031D168D46E3D586e")
|
||||||
|
account2 = common.HexToAddress("0x6177843db3138ae69679A54b95cf345ED759450d")
|
||||||
|
gspec = &Genesis{
|
||||||
|
Config: config,
|
||||||
|
Alloc: GenesisAlloc{
|
||||||
|
coinbase: GenesisAccount{
|
||||||
|
Balance: big.NewInt(1000000000000000000), // 1 ether
|
||||||
|
Nonce: 0,
|
||||||
|
},
|
||||||
|
account1: GenesisAccount{
|
||||||
|
Balance: big.NewInt(1000000000000000000), // 1 ether
|
||||||
|
Nonce: 0,
|
||||||
|
},
|
||||||
|
account2: GenesisAccount{
|
||||||
|
Balance: big.NewInt(1000000000000000000), // 1 ether
|
||||||
|
Nonce: 1,
|
||||||
|
},
|
||||||
|
params.HistoryStorageAddress: GenesisAccount{
|
||||||
|
Balance: big.NewInt(0),
|
||||||
|
Nonce: 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
// Create two blocks that reproduce what is happening on kaustinen.
|
||||||
|
// - The first block contains two failing contract creation transactions, that write to storage before they revert.
|
||||||
|
// - The second block contains a single failing contract creation transaction, that fails right off the bat.
|
||||||
|
_, _, _, _, statediffs := GenerateVerkleChainWithGenesis(gspec, beacon.New(ethash.NewFaker()), 2, func(i int, gen *BlockGen) {
|
||||||
|
gen.SetPoS()
|
||||||
|
|
||||||
|
if i == 0 {
|
||||||
|
var tx1, tx2, tx3 types.Transaction
|
||||||
|
// SSTORE at slot 41 and reverts
|
||||||
|
tx1payload := common.Hex2Bytes("f8d48084479c2c18830186a08080b8806000602955bda3f9600060ca55600060695523b360006039551983576000601255b0620c2fde2c592ac2600060bc55e0ac6000606455a63e22600060e655eb607e605c5360a2605d5360c7605e53601d605f5360eb606053606b606153608e60625360816063536079606453601e60655360fc60665360b7606753608b60685383021e7ca0cc20c65a97d2e526b8ec0f4266e8b01bdcde43b9aeb59d8bfb44e8eb8119c109a07a8e751813ae1b2ce734960dbc39a4f954917d7822a2c5d1dca18b06c584131f")
|
||||||
|
if err := tx1.UnmarshalBinary(tx1payload); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
gen.AddTx(&tx1)
|
||||||
|
|
||||||
|
// SSTORE at slot 133 and reverts
|
||||||
|
tx2payload := common.Hex2Bytes("02f8db83010f2c01843b9aca0084479c2c18830186a08080b88060006085553fad6000600a55600060565555600060b55506600060cf557f1b8b38183e7bd1bdfaa7123c5a4976e54cce0e42049d841411978fd3595e25c66019527f0538943712953cf08900aae40222a40b2d5a4ac8075ad8cf0870e2be307edbb96039527f9f3174ff85024747041ae7a611acffb987c513c088d90ab288aec080a0cd6ac65ce2cb0a912371f6b5a551ba8caffc22ec55ad4d3cb53de41d05eb77b6a02e0dfe8513dfa6ec7bfd7eda6f5c0dac21b39b982436045e128cec46cfd3f960")
|
||||||
|
if err := tx2.UnmarshalBinary(tx2payload); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
gen.AddTx(&tx2)
|
||||||
|
|
||||||
|
// this one is a simple transfer that succeeds, necessary to get the correct nonce in the other block.
|
||||||
|
tx3payload := common.Hex2Bytes("f8e80184479c2c18830186a094bbbbde4ca27f83fc18aa108170547ff57675936a80b8807ff71f7c15faadb969a76a5f54a81a0117e1e743cb7f24e378eda28442ea4c6eb6604a527fb5409e5718d44e23bfffac926e5ea726067f772772e7e19446acba0c853f62f5606a526020608a536088608b536039608c536004608d5360af608e537f7f7675d9f210e0a61564e6d11e7cd75f5bc9009ac9f6b94a0fc63035441a83021e7ba04a4a172d81ebb02847829b76a387ac09749c8b65668083699abe20c887fb9efca07c5b1a990702ec7b31a5e8e3935cd9a77649f8c25a84131229e24ab61aec6093")
|
||||||
|
if err := tx3.UnmarshalBinary(tx3payload); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
gen.AddTx(&tx3)
|
||||||
|
} else {
|
||||||
|
var tx types.Transaction
|
||||||
|
// immediately reverts
|
||||||
|
txpayload := common.Hex2Bytes("01f8d683010f2c028443ad7d0e830186a08080b880b00e7fa3c849dce891cce5fae8a4c46cbb313d6aec0c0ffe7863e05fb7b22d4807674c6055527ffbfcb0938f3e18f7937aa8fa95d880afebd5c4cec0d85186095832d03c85cf8a60755260ab60955360cf6096536066609753606e60985360fa609953609e609a53608e609b536024609c5360f6609d536072609e5360a4609fc080a08fc6f7101f292ff1fb0de8ac69c2d320fbb23bfe61cf327173786ea5daee6e37a044c42d91838ef06646294bf4f9835588aee66243b16a66a2da37641fae4c045f")
|
||||||
|
if err := tx.UnmarshalBinary(txpayload); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
gen.AddTx(&tx)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
tx1ContractAddress := crypto.CreateAddress(account1, 0)
|
||||||
|
tx1ContractStem := utils.GetTreeKey(tx1ContractAddress[:], uint256.NewInt(0), 105)
|
||||||
|
tx1ContractStem = tx1ContractStem[:31]
|
||||||
|
|
||||||
|
// Check that values 0x29 and 0x05 are found in the storage (and that they lead
|
||||||
|
// to no update, since the contract creation code reverted)
|
||||||
|
for _, stemStateDiff := range statediffs[0] {
|
||||||
|
// Check that the value 0x85, which is overflowing the account header,
|
||||||
|
// is present.
|
||||||
|
if bytes.Equal(stemStateDiff.Stem[:], common.Hex2Bytes("917f78f74226b0e3755134ce3e3433cac8df5a657f6c9b9a3d0122a3e4beb0")) {
|
||||||
|
for _, suffixDiff := range stemStateDiff.SuffixDiffs {
|
||||||
|
if suffixDiff.Suffix != 133 {
|
||||||
|
t.Fatalf("invalid suffix diff found for %x in block #1: %d\n", stemStateDiff.Stem, suffixDiff.Suffix)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if bytes.Equal(stemStateDiff.Stem[:], tx1ContractStem) {
|
||||||
|
for _, suffixDiff := range stemStateDiff.SuffixDiffs {
|
||||||
|
if suffixDiff.Suffix != 105 && suffixDiff.Suffix != 0 && suffixDiff.Suffix != 1 {
|
||||||
|
t.Fatalf("invalid suffix diff found for %x in block #1: %d\n", stemStateDiff.Stem, suffixDiff.Suffix)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if bytes.Equal(stemStateDiff.Stem[:], common.Hex2Bytes("5b5fdfedd6a0e932da408ac7d772a36513d1eee9b9926e52620c43a433aad7")) {
|
||||||
|
// BLOCKHASH contract stem
|
||||||
|
if len(stemStateDiff.SuffixDiffs) > 1 {
|
||||||
|
t.Fatalf("invalid suffix diff count found for BLOCKHASH contract: %d != 1", len(stemStateDiff.SuffixDiffs))
|
||||||
|
}
|
||||||
|
if stemStateDiff.SuffixDiffs[0].Suffix != 64 {
|
||||||
|
t.Fatalf("invalid suffix diff value found for BLOCKHASH contract: %d != 64", stemStateDiff.SuffixDiffs[0].Suffix)
|
||||||
|
}
|
||||||
|
// check that the "current value" is nil and that the new value isn't.
|
||||||
|
if stemStateDiff.SuffixDiffs[0].CurrentValue != nil {
|
||||||
|
t.Fatalf("non-nil current value in BLOCKHASH contract insert: %x", stemStateDiff.SuffixDiffs[0].CurrentValue)
|
||||||
|
}
|
||||||
|
if stemStateDiff.SuffixDiffs[0].NewValue == nil {
|
||||||
|
t.Fatalf("nil new value in BLOCKHASH contract insert")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for _, suffixDiff := range stemStateDiff.SuffixDiffs {
|
||||||
|
if suffixDiff.Suffix > 4 {
|
||||||
|
t.Fatalf("invalid suffix diff found for %x in block #1: %d\n", stemStateDiff.Stem, suffixDiff.Suffix)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check that no account has a value above 4 in the 2nd block as no storage nor
|
||||||
|
// code should make it to the witness.
|
||||||
|
for _, stemStateDiff := range statediffs[1] {
|
||||||
|
for _, suffixDiff := range stemStateDiff.SuffixDiffs {
|
||||||
|
if bytes.Equal(stemStateDiff.Stem[:], common.Hex2Bytes("5b5fdfedd6a0e932da408ac7d772a36513d1eee9b9926e52620c43a433aad7")) {
|
||||||
|
// BLOCKHASH contract stem
|
||||||
|
if len(stemStateDiff.SuffixDiffs) > 1 {
|
||||||
|
t.Fatalf("invalid suffix diff count found for BLOCKHASH contract at block #2: %d != 1", len(stemStateDiff.SuffixDiffs))
|
||||||
|
}
|
||||||
|
if stemStateDiff.SuffixDiffs[0].Suffix != 65 {
|
||||||
|
t.Fatalf("invalid suffix diff value found for BLOCKHASH contract at block #2: %d != 65", stemStateDiff.SuffixDiffs[0].Suffix)
|
||||||
|
}
|
||||||
|
if stemStateDiff.SuffixDiffs[0].NewValue == nil {
|
||||||
|
t.Fatalf("missing post state value for BLOCKHASH contract at block #2")
|
||||||
|
}
|
||||||
|
if *stemStateDiff.SuffixDiffs[0].NewValue != common.HexToHash("0788c2c0f23aa07eb8bf76fe6c1ca9064a4821c1fd0af803913da488a58dba54") {
|
||||||
|
t.Fatalf("invalid post state value for BLOCKHASH contract at block #2: 0788c2c0f23aa07eb8bf76fe6c1ca9064a4821c1fd0af803913da488a58dba54 != %x", (*stemStateDiff.SuffixDiffs[0].NewValue)[:])
|
||||||
|
}
|
||||||
|
} else if suffixDiff.Suffix > 4 {
|
||||||
|
t.Fatalf("invalid suffix diff found for %x in block #2: %d\n", stemStateDiff.Stem, suffixDiff.Suffix)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestProcessVerkleContractWithEmptyCode(t *testing.T) {
|
||||||
|
var (
|
||||||
|
config = ¶ms.ChainConfig{
|
||||||
|
ChainID: big.NewInt(69421),
|
||||||
|
HomesteadBlock: big.NewInt(0),
|
||||||
|
EIP150Block: big.NewInt(0),
|
||||||
|
EIP155Block: big.NewInt(0),
|
||||||
|
EIP158Block: big.NewInt(0),
|
||||||
|
ByzantiumBlock: big.NewInt(0),
|
||||||
|
ConstantinopleBlock: big.NewInt(0),
|
||||||
|
PetersburgBlock: big.NewInt(0),
|
||||||
|
IstanbulBlock: big.NewInt(0),
|
||||||
|
MuirGlacierBlock: big.NewInt(0),
|
||||||
|
BerlinBlock: big.NewInt(0),
|
||||||
|
LondonBlock: big.NewInt(0),
|
||||||
|
Ethash: new(params.EthashConfig),
|
||||||
|
ShanghaiTime: u64(0),
|
||||||
|
VerkleTime: u64(0),
|
||||||
|
TerminalTotalDifficulty: common.Big0,
|
||||||
|
TerminalTotalDifficultyPassed: true,
|
||||||
|
}
|
||||||
|
coinbase = common.HexToAddress("0x71562b71999873DB5b286dF957af199Ec94617F7")
|
||||||
|
account1 = common.HexToAddress("0x687704DB07e902e9A8B3754031D168D46E3D586e")
|
||||||
|
account2 = common.HexToAddress("0x6177843db3138ae69679A54b95cf345ED759450d")
|
||||||
|
gspec = &Genesis{
|
||||||
|
Config: config,
|
||||||
|
Alloc: GenesisAlloc{
|
||||||
|
coinbase: GenesisAccount{
|
||||||
|
Balance: big.NewInt(1000000000000000000), // 1 ether
|
||||||
|
Nonce: 0,
|
||||||
|
},
|
||||||
|
account1: GenesisAccount{
|
||||||
|
Balance: big.NewInt(1000000000000000000), // 1 ether
|
||||||
|
Nonce: 0,
|
||||||
|
},
|
||||||
|
account2: GenesisAccount{
|
||||||
|
Balance: big.NewInt(1000000000000000000), // 1 ether
|
||||||
|
Nonce: 3,
|
||||||
|
},
|
||||||
|
params.HistoryStorageAddress: GenesisAccount{
|
||||||
|
Balance: big.NewInt(0),
|
||||||
|
Nonce: 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
_, _, _, _, statediffs := GenerateVerkleChainWithGenesis(gspec, beacon.New(ethash.NewFaker()), 1, func(i int, gen *BlockGen) {
|
||||||
|
gen.SetPoS()
|
||||||
|
var tx types.Transaction
|
||||||
|
// a transaction that does some PUSH1n but returns a 0-sized contract
|
||||||
|
txpayload := common.Hex2Bytes("02f8db83010f2d03843b9aca008444cf6a05830186a08080b8807fdfbbb59f2371a76485ce557fd0de00c298d3ede52a3eab56d35af674eb49ec5860335260826053536001605453604c60555360f3605653606060575360446058536096605953600c605a5360df605b5360f3605c5360fb605d53600c605e53609a605f53607f60605360fe606153603d60625360f4606353604b60645360cac001a0486b6dc55b8a311568b7239a2cae1d77e7446dba71df61eaafd53f73820a138fa010bd48a45e56133ac4c5645142c2ea48950d40eb35050e9510b6bad9e15c5865")
|
||||||
|
if err := tx.UnmarshalBinary(txpayload); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
gen.AddTx(&tx)
|
||||||
|
})
|
||||||
|
|
||||||
|
for _, stemStateDiff := range statediffs[0] {
|
||||||
|
if bytes.Equal(stemStateDiff.Stem[:], common.Hex2Bytes("5b5fdfedd6a0e932da408ac7d772a36513d1eee9b9926e52620c43a433aad7")) {
|
||||||
|
// BLOCKHASH contract stem
|
||||||
|
if len(stemStateDiff.SuffixDiffs) > 1 {
|
||||||
|
t.Fatalf("invalid suffix diff count found for BLOCKHASH contract: %d != 1", len(stemStateDiff.SuffixDiffs))
|
||||||
|
}
|
||||||
|
if stemStateDiff.SuffixDiffs[0].Suffix != 64 {
|
||||||
|
t.Fatalf("invalid suffix diff value found for BLOCKHASH contract: %d != 64", stemStateDiff.SuffixDiffs[0].Suffix)
|
||||||
|
}
|
||||||
|
// check that the "current value" is nil and that the new value isn't.
|
||||||
|
if stemStateDiff.SuffixDiffs[0].CurrentValue != nil {
|
||||||
|
t.Fatalf("non-nil current value in BLOCKHASH contract insert: %x", stemStateDiff.SuffixDiffs[0].CurrentValue)
|
||||||
|
}
|
||||||
|
if stemStateDiff.SuffixDiffs[0].NewValue == nil {
|
||||||
|
t.Fatalf("nil new value in BLOCKHASH contract insert")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for _, suffixDiff := range stemStateDiff.SuffixDiffs {
|
||||||
|
if suffixDiff.Suffix > 4 {
|
||||||
|
// if d8898012c484fb48610ecb7963886339207dab004bce968b007b616ffa18e0 shows up, it means that the PUSHn
|
||||||
|
// in the transaction above added entries into the witness, when they should not have since they are
|
||||||
|
// part of a contract deployment.
|
||||||
|
t.Fatalf("invalid suffix diff found for %x in block #1: %d\n", stemStateDiff.Stem, suffixDiff.Suffix)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestProcessVerklExtCodeHashOpcode(t *testing.T) {
|
||||||
|
var (
|
||||||
|
config = ¶ms.ChainConfig{
|
||||||
|
ChainID: big.NewInt(69421),
|
||||||
|
HomesteadBlock: big.NewInt(0),
|
||||||
|
EIP150Block: big.NewInt(0),
|
||||||
|
EIP155Block: big.NewInt(0),
|
||||||
|
EIP158Block: big.NewInt(0),
|
||||||
|
ByzantiumBlock: big.NewInt(0),
|
||||||
|
ConstantinopleBlock: big.NewInt(0),
|
||||||
|
PetersburgBlock: big.NewInt(0),
|
||||||
|
IstanbulBlock: big.NewInt(0),
|
||||||
|
MuirGlacierBlock: big.NewInt(0),
|
||||||
|
BerlinBlock: big.NewInt(0),
|
||||||
|
LondonBlock: big.NewInt(0),
|
||||||
|
Ethash: new(params.EthashConfig),
|
||||||
|
ShanghaiTime: u64(0),
|
||||||
|
VerkleTime: u64(0),
|
||||||
|
TerminalTotalDifficulty: common.Big0,
|
||||||
|
TerminalTotalDifficultyPassed: true,
|
||||||
|
}
|
||||||
|
signer = types.LatestSigner(config)
|
||||||
|
testKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
|
||||||
|
coinbase = common.HexToAddress("0x71562b71999873DB5b286dF957af199Ec94617F7")
|
||||||
|
account1 = common.HexToAddress("0x687704DB07e902e9A8B3754031D168D46E3D586e")
|
||||||
|
account2 = common.HexToAddress("0x6177843db3138ae69679A54b95cf345ED759450d")
|
||||||
|
gspec = &Genesis{
|
||||||
|
Config: config,
|
||||||
|
Alloc: GenesisAlloc{
|
||||||
|
coinbase: GenesisAccount{
|
||||||
|
Balance: big.NewInt(1000000000000000000), // 1 ether
|
||||||
|
Nonce: 0,
|
||||||
|
},
|
||||||
|
account1: GenesisAccount{
|
||||||
|
Balance: big.NewInt(1000000000000000000), // 1 ether
|
||||||
|
Nonce: 0,
|
||||||
|
},
|
||||||
|
account2: GenesisAccount{
|
||||||
|
Balance: big.NewInt(1000000000000000000), // 1 ether
|
||||||
|
Nonce: 3,
|
||||||
|
},
|
||||||
|
params.HistoryStorageAddress: GenesisAccount{
|
||||||
|
Balance: big.NewInt(0),
|
||||||
|
Nonce: 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
dummyContract := []byte{
|
||||||
|
0x60, 2, // PUSH1 2
|
||||||
|
0x60, 12, // PUSH1 12
|
||||||
|
0x60, 0x00, // PUSH1 0
|
||||||
|
0x39, // CODECOPY
|
||||||
|
|
||||||
|
0x60, 2, // PUSH1 2
|
||||||
|
0x60, 0x00, // PUSH1 0
|
||||||
|
0xF3, // RETURN
|
||||||
|
|
||||||
|
// Contract that auto-calls EXTCODEHASH
|
||||||
|
0x60, 42, // PUSH1 42
|
||||||
|
}
|
||||||
|
dummyContractAddr := common.HexToAddress("3a220f351252089d385b29beca14e27f204c296a")
|
||||||
|
extCodeHashContract := []byte{
|
||||||
|
0x60, 22, // PUSH1 22
|
||||||
|
0x60, 12, // PUSH1 12
|
||||||
|
0x60, 0x00, // PUSH1 0
|
||||||
|
0x39, // CODECOPY
|
||||||
|
|
||||||
|
0x60, 22, // PUSH1 22
|
||||||
|
0x60, 0x00, // PUSH1 0
|
||||||
|
0xF3, // RETURN
|
||||||
|
|
||||||
|
// Contract that auto-calls EXTCODEHASH
|
||||||
|
0x73, // PUSH20
|
||||||
|
0x3a, 0x22, 0x0f, 0x35, 0x12, 0x52, 0x08, 0x9d, 0x38, 0x5b, 0x29, 0xbe, 0xca, 0x14, 0xe2, 0x7f, 0x20, 0x4c, 0x29, 0x6a,
|
||||||
|
0x3F, // EXTCODEHASH
|
||||||
|
}
|
||||||
|
extCodeHashContractAddr := common.HexToAddress("db7d6ab1f17c6b31909ae466702703daef9269cf")
|
||||||
|
_, _, _, _, statediffs := GenerateVerkleChainWithGenesis(gspec, beacon.New(ethash.NewFaker()), 2, func(i int, gen *BlockGen) {
|
||||||
|
gen.SetPoS()
|
||||||
|
|
||||||
|
if i == 0 {
|
||||||
|
// Create dummy contract.
|
||||||
|
tx, _ := types.SignTx(types.NewContractCreation(0, big.NewInt(0), 100_000, big.NewInt(875000000), dummyContract), signer, testKey)
|
||||||
|
gen.AddTx(tx)
|
||||||
|
|
||||||
|
// Create contract with EXTCODEHASH opcode.
|
||||||
|
tx, _ = types.SignTx(types.NewContractCreation(1, big.NewInt(0), 100_000, big.NewInt(875000000), extCodeHashContract), signer, testKey)
|
||||||
|
gen.AddTx(tx)
|
||||||
|
} else {
|
||||||
|
tx, _ := types.SignTx(types.NewTransaction(2, extCodeHashContractAddr, big.NewInt(0), 100_000, big.NewInt(875000000), nil), signer, testKey)
|
||||||
|
gen.AddTx(tx)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
contractKeccakTreeKey := utils.CodeHashKey(dummyContractAddr[:])
|
||||||
|
|
||||||
|
var stateDiffIdx = -1
|
||||||
|
for i, stemStateDiff := range statediffs[1] {
|
||||||
|
if bytes.Equal(stemStateDiff.Stem[:], contractKeccakTreeKey[:31]) {
|
||||||
|
stateDiffIdx = i
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if stateDiffIdx == -1 {
|
||||||
|
t.Fatalf("no state diff found for stem")
|
||||||
|
}
|
||||||
|
|
||||||
|
codeHashStateDiff := statediffs[1][stateDiffIdx].SuffixDiffs[0]
|
||||||
|
if codeHashStateDiff.Suffix != utils.CodeHashLeafKey {
|
||||||
|
t.Fatalf("code hash invalid suffix")
|
||||||
|
}
|
||||||
|
if codeHashStateDiff.CurrentValue == nil {
|
||||||
|
t.Fatalf("codeHash.CurrentValue must not be empty")
|
||||||
|
}
|
||||||
|
expCodeHash := crypto.Keccak256Hash(dummyContract[12:])
|
||||||
|
if *codeHashStateDiff.CurrentValue != expCodeHash {
|
||||||
|
t.Fatalf("codeHash.CurrentValue unexpected code hash")
|
||||||
|
}
|
||||||
|
if codeHashStateDiff.NewValue != nil {
|
||||||
|
t.Fatalf("codeHash.NewValue must be nil")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestProcessVerkleBalanceOpcode(t *testing.T) {
|
||||||
|
var (
|
||||||
|
config = ¶ms.ChainConfig{
|
||||||
|
ChainID: big.NewInt(69421),
|
||||||
|
HomesteadBlock: big.NewInt(0),
|
||||||
|
EIP150Block: big.NewInt(0),
|
||||||
|
EIP155Block: big.NewInt(0),
|
||||||
|
EIP158Block: big.NewInt(0),
|
||||||
|
ByzantiumBlock: big.NewInt(0),
|
||||||
|
ConstantinopleBlock: big.NewInt(0),
|
||||||
|
PetersburgBlock: big.NewInt(0),
|
||||||
|
IstanbulBlock: big.NewInt(0),
|
||||||
|
MuirGlacierBlock: big.NewInt(0),
|
||||||
|
BerlinBlock: big.NewInt(0),
|
||||||
|
LondonBlock: big.NewInt(0),
|
||||||
|
Ethash: new(params.EthashConfig),
|
||||||
|
ShanghaiTime: u64(0),
|
||||||
|
VerkleTime: u64(0),
|
||||||
|
TerminalTotalDifficulty: common.Big0,
|
||||||
|
TerminalTotalDifficultyPassed: true,
|
||||||
|
}
|
||||||
|
signer = types.LatestSigner(config)
|
||||||
|
testKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
|
||||||
|
coinbase = common.HexToAddress("0x71562b71999873DB5b286dF957af199Ec94617F7")
|
||||||
|
account1 = common.HexToAddress("0x687704DB07e902e9A8B3754031D168D46E3D586e")
|
||||||
|
account2 = common.HexToAddress("0x6177843db3138ae69679A54b95cf345ED759450d")
|
||||||
|
gspec = &Genesis{
|
||||||
|
Config: config,
|
||||||
|
Alloc: GenesisAlloc{
|
||||||
|
coinbase: GenesisAccount{
|
||||||
|
Balance: big.NewInt(1000000000000000000), // 1 ether
|
||||||
|
Nonce: 0,
|
||||||
|
},
|
||||||
|
account1: GenesisAccount{
|
||||||
|
Balance: big.NewInt(1000000000000000000), // 1 ether
|
||||||
|
Nonce: 0,
|
||||||
|
},
|
||||||
|
account2: GenesisAccount{
|
||||||
|
Balance: big.NewInt(1000000000000000000), // 1 ether
|
||||||
|
Nonce: 3,
|
||||||
|
},
|
||||||
|
params.HistoryStorageAddress: GenesisAccount{
|
||||||
|
Balance: big.NewInt(0),
|
||||||
|
Nonce: 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
_, _, _, _, statediffs := GenerateVerkleChainWithGenesis(gspec, beacon.New(ethash.NewFaker()), 1, func(i int, gen *BlockGen) {
|
||||||
|
gen.SetPoS()
|
||||||
|
txData := []byte{
|
||||||
|
0x73, // PUSH20
|
||||||
|
0x61, 0x77, 0x84, 0x3d, 0xb3, 0x13, 0x8a, 0xe6, 0x96, 0x79, 0xA5, 0x4b, 0x95, 0xcf, 0x34, 0x5E, 0xD7, 0x59, 0x45, 0x0d, // 0x6177843db3138ae69679A54b95cf345ED759450d
|
||||||
|
0x31, // BALANCE
|
||||||
|
}
|
||||||
|
tx, _ := types.SignTx(types.NewContractCreation(0, big.NewInt(0), 100_000, big.NewInt(875000000), txData), signer, testKey)
|
||||||
|
gen.AddTx(tx)
|
||||||
|
})
|
||||||
|
|
||||||
|
account2BalanceTreeKey := utils.BasicDataKey(account2[:])
|
||||||
|
|
||||||
|
var stateDiffIdx = -1
|
||||||
|
for i, stemStateDiff := range statediffs[0] {
|
||||||
|
if bytes.Equal(stemStateDiff.Stem[:], account2BalanceTreeKey[:31]) {
|
||||||
|
stateDiffIdx = i
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if stateDiffIdx == -1 {
|
||||||
|
t.Fatalf("no state diff found for stem")
|
||||||
|
}
|
||||||
|
|
||||||
|
var zero [32]byte
|
||||||
|
balanceStateDiff := statediffs[0][stateDiffIdx].SuffixDiffs[0]
|
||||||
|
if balanceStateDiff.Suffix != utils.BasicDataLeafKey {
|
||||||
|
t.Fatalf("invalid suffix diff")
|
||||||
|
}
|
||||||
|
if balanceStateDiff.CurrentValue == nil {
|
||||||
|
t.Fatalf("invalid current value")
|
||||||
|
}
|
||||||
|
if *balanceStateDiff.CurrentValue == zero {
|
||||||
|
t.Fatalf("invalid current value")
|
||||||
|
}
|
||||||
|
if balanceStateDiff.NewValue != nil {
|
||||||
|
t.Fatalf("invalid new value")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestProcessVerkleSelfDestructInSeparateTx(t *testing.T) {
|
||||||
|
var (
|
||||||
|
config = ¶ms.ChainConfig{
|
||||||
|
ChainID: big.NewInt(69421),
|
||||||
|
HomesteadBlock: big.NewInt(0),
|
||||||
|
EIP150Block: big.NewInt(0),
|
||||||
|
EIP155Block: big.NewInt(0),
|
||||||
|
EIP158Block: big.NewInt(0),
|
||||||
|
ByzantiumBlock: big.NewInt(0),
|
||||||
|
ConstantinopleBlock: big.NewInt(0),
|
||||||
|
PetersburgBlock: big.NewInt(0),
|
||||||
|
IstanbulBlock: big.NewInt(0),
|
||||||
|
MuirGlacierBlock: big.NewInt(0),
|
||||||
|
BerlinBlock: big.NewInt(0),
|
||||||
|
LondonBlock: big.NewInt(0),
|
||||||
|
Ethash: new(params.EthashConfig),
|
||||||
|
ShanghaiTime: u64(0),
|
||||||
|
VerkleTime: u64(0),
|
||||||
|
TerminalTotalDifficulty: common.Big0,
|
||||||
|
TerminalTotalDifficultyPassed: true,
|
||||||
|
}
|
||||||
|
signer = types.LatestSigner(config)
|
||||||
|
testKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
|
||||||
|
coinbase = common.HexToAddress("0x71562b71999873DB5b286dF957af199Ec94617F7")
|
||||||
|
account1 = common.HexToAddress("0x687704DB07e902e9A8B3754031D168D46E3D586e")
|
||||||
|
account2 = common.HexToAddress("0x6177843db3138ae69679A54b95cf345ED759450d")
|
||||||
|
gspec = &Genesis{
|
||||||
|
Config: config,
|
||||||
|
Alloc: GenesisAlloc{
|
||||||
|
coinbase: GenesisAccount{
|
||||||
|
Balance: big.NewInt(1000000000000000000), // 1 ether
|
||||||
|
Nonce: 0,
|
||||||
|
},
|
||||||
|
account1: GenesisAccount{
|
||||||
|
Balance: big.NewInt(1000000000000000000), // 1 ether
|
||||||
|
Nonce: 0,
|
||||||
|
},
|
||||||
|
account2: GenesisAccount{
|
||||||
|
Balance: big.NewInt(1000000000000000000), // 1 ether
|
||||||
|
Nonce: 3,
|
||||||
|
},
|
||||||
|
params.HistoryStorageAddress: GenesisAccount{
|
||||||
|
Balance: big.NewInt(0),
|
||||||
|
Nonce: 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
// The goal of this test is to test SELFDESTRUCT that happens in a contract execution which is created
|
||||||
|
// in a previous transaction.
|
||||||
|
|
||||||
|
selfDestructContract := []byte{
|
||||||
|
0x60, 22, // PUSH1 22
|
||||||
|
0x60, 12, // PUSH1 12
|
||||||
|
0x60, 0x00, // PUSH1 0
|
||||||
|
0x39, // CODECOPY
|
||||||
|
|
||||||
|
0x60, 22, // PUSH1 22
|
||||||
|
0x60, 0x00, // PUSH1 0
|
||||||
|
0xF3, // RETURN
|
||||||
|
|
||||||
|
// Deployed code
|
||||||
|
0x73, // PUSH20
|
||||||
|
0x61, 0x77, 0x84, 0x3d, 0xb3, 0x13, 0x8a, 0xe6, 0x96, 0x79, 0xA5, 0x4b, 0x95, 0xcf, 0x34, 0x5E, 0xD7, 0x59, 0x45, 0x0d, // 0x6177843db3138ae69679A54b95cf345ED759450d
|
||||||
|
0xFF, // SELFDESTRUCT
|
||||||
|
}
|
||||||
|
selfDestructContractAddr := common.HexToAddress("3a220f351252089d385b29beca14e27f204c296a")
|
||||||
|
_, _, _, _, statediffs := GenerateVerkleChainWithGenesis(gspec, beacon.New(ethash.NewFaker()), 2, func(i int, gen *BlockGen) {
|
||||||
|
gen.SetPoS()
|
||||||
|
|
||||||
|
if i == 0 {
|
||||||
|
// Create selfdestruct contract, sending 42 wei.
|
||||||
|
tx, _ := types.SignTx(types.NewContractCreation(0, big.NewInt(42), 100_000, big.NewInt(875000000), selfDestructContract), signer, testKey)
|
||||||
|
gen.AddTx(tx)
|
||||||
|
} else {
|
||||||
|
// Call it.
|
||||||
|
tx, _ := types.SignTx(types.NewTransaction(1, selfDestructContractAddr, big.NewInt(0), 100_000, big.NewInt(875000000), nil), signer, testKey)
|
||||||
|
gen.AddTx(tx)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
var zero [32]byte
|
||||||
|
{ // Check self-destructed contract in the witness
|
||||||
|
selfDestructContractTreeKey := utils.CodeHashKey(selfDestructContractAddr[:])
|
||||||
|
|
||||||
|
var stateDiffIdx = -1
|
||||||
|
for i, stemStateDiff := range statediffs[1] {
|
||||||
|
if bytes.Equal(stemStateDiff.Stem[:], selfDestructContractTreeKey[:31]) {
|
||||||
|
stateDiffIdx = i
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if stateDiffIdx == -1 {
|
||||||
|
t.Fatalf("no state diff found for stem")
|
||||||
|
}
|
||||||
|
|
||||||
|
balanceStateDiff := statediffs[1][stateDiffIdx].SuffixDiffs[0]
|
||||||
|
if balanceStateDiff.Suffix != utils.BasicDataLeafKey {
|
||||||
|
t.Fatalf("balance invalid suffix")
|
||||||
|
}
|
||||||
|
|
||||||
|
// The original balance was 42.
|
||||||
|
var fourtyTwo [16]byte
|
||||||
|
fourtyTwo[15] = 42
|
||||||
|
if !bytes.Equal((*balanceStateDiff.CurrentValue)[utils.BasicDataBalanceOffset:], fourtyTwo[:]) {
|
||||||
|
t.Fatalf("the pre-state balance before self-destruct must be %x, got %x", fourtyTwo, *balanceStateDiff.CurrentValue)
|
||||||
|
}
|
||||||
|
|
||||||
|
// The new balance must be 0.
|
||||||
|
if !bytes.Equal((*balanceStateDiff.NewValue)[utils.BasicDataBalanceOffset:], zero[utils.BasicDataBalanceOffset:]) {
|
||||||
|
t.Fatalf("the post-state balance after self-destruct must be 0")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{ // Check self-destructed target in the witness.
|
||||||
|
selfDestructTargetTreeKey := utils.CodeHashKey(account2[:])
|
||||||
|
|
||||||
|
var stateDiffIdx = -1
|
||||||
|
for i, stemStateDiff := range statediffs[1] {
|
||||||
|
if bytes.Equal(stemStateDiff.Stem[:], selfDestructTargetTreeKey[:31]) {
|
||||||
|
stateDiffIdx = i
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if stateDiffIdx == -1 {
|
||||||
|
t.Fatalf("no state diff found for stem")
|
||||||
|
}
|
||||||
|
|
||||||
|
balanceStateDiff := statediffs[1][stateDiffIdx].SuffixDiffs[0]
|
||||||
|
if balanceStateDiff.Suffix != utils.BasicDataLeafKey {
|
||||||
|
t.Fatalf("balance invalid suffix")
|
||||||
|
}
|
||||||
|
if balanceStateDiff.CurrentValue == nil {
|
||||||
|
t.Fatalf("codeHash.CurrentValue must not be empty")
|
||||||
|
}
|
||||||
|
if balanceStateDiff.NewValue == nil {
|
||||||
|
t.Fatalf("codeHash.NewValue must not be empty")
|
||||||
|
}
|
||||||
|
preStateBalance := binary.BigEndian.Uint64(balanceStateDiff.CurrentValue[utils.BasicDataBalanceOffset+8:])
|
||||||
|
postStateBalance := binary.BigEndian.Uint64(balanceStateDiff.NewValue[utils.BasicDataBalanceOffset+8:])
|
||||||
|
if postStateBalance-preStateBalance != 42 {
|
||||||
|
t.Fatalf("the post-state balance after self-destruct must be 42, got %d-%d=%d", postStateBalance, preStateBalance, postStateBalance-preStateBalance)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestProcessVerkleSelfDestructInSameTx(t *testing.T) {
|
||||||
|
var (
|
||||||
|
config = ¶ms.ChainConfig{
|
||||||
|
ChainID: big.NewInt(69421),
|
||||||
|
HomesteadBlock: big.NewInt(0),
|
||||||
|
EIP150Block: big.NewInt(0),
|
||||||
|
EIP155Block: big.NewInt(0),
|
||||||
|
EIP158Block: big.NewInt(0),
|
||||||
|
ByzantiumBlock: big.NewInt(0),
|
||||||
|
ConstantinopleBlock: big.NewInt(0),
|
||||||
|
PetersburgBlock: big.NewInt(0),
|
||||||
|
IstanbulBlock: big.NewInt(0),
|
||||||
|
MuirGlacierBlock: big.NewInt(0),
|
||||||
|
BerlinBlock: big.NewInt(0),
|
||||||
|
LondonBlock: big.NewInt(0),
|
||||||
|
Ethash: new(params.EthashConfig),
|
||||||
|
ShanghaiTime: u64(0),
|
||||||
|
VerkleTime: u64(0),
|
||||||
|
TerminalTotalDifficulty: common.Big0,
|
||||||
|
TerminalTotalDifficultyPassed: true,
|
||||||
|
}
|
||||||
|
signer = types.LatestSigner(config)
|
||||||
|
testKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
|
||||||
|
coinbase = common.HexToAddress("0x71562b71999873DB5b286dF957af199Ec94617F7")
|
||||||
|
account1 = common.HexToAddress("0x687704DB07e902e9A8B3754031D168D46E3D586e")
|
||||||
|
account2 = common.HexToAddress("0x6177843db3138ae69679A54b95cf345ED759450d")
|
||||||
|
gspec = &Genesis{
|
||||||
|
Config: config,
|
||||||
|
Alloc: GenesisAlloc{
|
||||||
|
coinbase: GenesisAccount{
|
||||||
|
Balance: big.NewInt(1000000000000000000), // 1 ether
|
||||||
|
Nonce: 0,
|
||||||
|
},
|
||||||
|
account1: GenesisAccount{
|
||||||
|
Balance: big.NewInt(1000000000000000000), // 1 ether
|
||||||
|
Nonce: 0,
|
||||||
|
},
|
||||||
|
account2: GenesisAccount{
|
||||||
|
Balance: big.NewInt(1000000000000000000), // 1 ether
|
||||||
|
Nonce: 3,
|
||||||
|
},
|
||||||
|
params.HistoryStorageAddress: GenesisAccount{
|
||||||
|
Balance: big.NewInt(0),
|
||||||
|
Nonce: 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
// The goal of this test is to test SELFDESTRUCT that happens in a contract execution which is created
|
||||||
|
// in **the same** transaction sending the remaining balance to an external (i.e: not itself) account.
|
||||||
|
|
||||||
|
selfDestructContract := []byte{
|
||||||
|
0x73, // PUSH20
|
||||||
|
0x61, 0x77, 0x84, 0x3d, 0xb3, 0x13, 0x8a, 0xe6, 0x96, 0x79, 0xA5, 0x4b, 0x95, 0xcf, 0x34, 0x5E, 0xD7, 0x59, 0x45, 0x0d, // 0x6177843db3138ae69679A54b95cf345ED759450d
|
||||||
|
0xFF, // SELFDESTRUCT
|
||||||
|
}
|
||||||
|
selfDestructContractAddr := common.HexToAddress("3a220f351252089d385b29beca14e27f204c296a")
|
||||||
|
_, _, _, _, statediffs := GenerateVerkleChainWithGenesis(gspec, beacon.New(ethash.NewFaker()), 1, func(i int, gen *BlockGen) {
|
||||||
|
gen.SetPoS()
|
||||||
|
tx, _ := types.SignTx(types.NewContractCreation(0, big.NewInt(42), 100_000, big.NewInt(875000000), selfDestructContract), signer, testKey)
|
||||||
|
gen.AddTx(tx)
|
||||||
|
})
|
||||||
|
|
||||||
|
{ // Check self-destructed contract in the witness
|
||||||
|
selfDestructContractTreeKey := utils.CodeHashKey(selfDestructContractAddr[:])
|
||||||
|
|
||||||
|
var stateDiffIdx = -1
|
||||||
|
for i, stemStateDiff := range statediffs[0] {
|
||||||
|
if bytes.Equal(stemStateDiff.Stem[:], selfDestructContractTreeKey[:31]) {
|
||||||
|
stateDiffIdx = i
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if stateDiffIdx == -1 {
|
||||||
|
t.Fatalf("no state diff found for stem")
|
||||||
|
}
|
||||||
|
|
||||||
|
balanceStateDiff := statediffs[0][stateDiffIdx].SuffixDiffs[0]
|
||||||
|
if balanceStateDiff.Suffix != utils.BasicDataLeafKey {
|
||||||
|
t.Fatalf("balance invalid suffix")
|
||||||
|
}
|
||||||
|
|
||||||
|
if balanceStateDiff.CurrentValue != nil {
|
||||||
|
t.Fatalf("the pre-state balance before must be nil, since the contract didn't exist")
|
||||||
|
}
|
||||||
|
|
||||||
|
if balanceStateDiff.NewValue != nil {
|
||||||
|
t.Fatalf("the post-state balance after self-destruct must be nil since the contract shouldn't be created at all")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{ // Check self-destructed target in the witness.
|
||||||
|
selfDestructTargetTreeKey := utils.CodeHashKey(account2[:])
|
||||||
|
|
||||||
|
var stateDiffIdx = -1
|
||||||
|
for i, stemStateDiff := range statediffs[0] {
|
||||||
|
if bytes.Equal(stemStateDiff.Stem[:], selfDestructTargetTreeKey[:31]) {
|
||||||
|
stateDiffIdx = i
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if stateDiffIdx == -1 {
|
||||||
|
t.Fatalf("no state diff found for stem")
|
||||||
|
}
|
||||||
|
|
||||||
|
balanceStateDiff := statediffs[0][stateDiffIdx].SuffixDiffs[0]
|
||||||
|
if balanceStateDiff.Suffix != utils.BasicDataLeafKey {
|
||||||
|
t.Fatalf("balance invalid suffix")
|
||||||
|
}
|
||||||
|
if balanceStateDiff.CurrentValue == nil {
|
||||||
|
t.Fatalf("codeHash.CurrentValue must not be empty")
|
||||||
|
}
|
||||||
|
if balanceStateDiff.NewValue == nil {
|
||||||
|
t.Fatalf("codeHash.NewValue must not be empty")
|
||||||
|
}
|
||||||
|
preStateBalance := binary.BigEndian.Uint64(balanceStateDiff.CurrentValue[utils.BasicDataBalanceOffset+8:])
|
||||||
|
postStateBalance := binary.BigEndian.Uint64(balanceStateDiff.NewValue[utils.BasicDataBalanceOffset+8:])
|
||||||
|
if postStateBalance-preStateBalance != 42 {
|
||||||
|
t.Fatalf("the post-state balance after self-destruct must be 42. got %d", postStateBalance)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestProcessVerkleSelfDestructInSeparateTxWithSelfBeneficiary(t *testing.T) {
|
||||||
|
var (
|
||||||
|
config = ¶ms.ChainConfig{
|
||||||
|
ChainID: big.NewInt(69421),
|
||||||
|
HomesteadBlock: big.NewInt(0),
|
||||||
|
EIP150Block: big.NewInt(0),
|
||||||
|
EIP155Block: big.NewInt(0),
|
||||||
|
EIP158Block: big.NewInt(0),
|
||||||
|
ByzantiumBlock: big.NewInt(0),
|
||||||
|
ConstantinopleBlock: big.NewInt(0),
|
||||||
|
PetersburgBlock: big.NewInt(0),
|
||||||
|
IstanbulBlock: big.NewInt(0),
|
||||||
|
MuirGlacierBlock: big.NewInt(0),
|
||||||
|
BerlinBlock: big.NewInt(0),
|
||||||
|
LondonBlock: big.NewInt(0),
|
||||||
|
Ethash: new(params.EthashConfig),
|
||||||
|
ShanghaiTime: u64(0),
|
||||||
|
VerkleTime: u64(0),
|
||||||
|
TerminalTotalDifficulty: common.Big0,
|
||||||
|
TerminalTotalDifficultyPassed: true,
|
||||||
|
}
|
||||||
|
signer = types.LatestSigner(config)
|
||||||
|
testKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
|
||||||
|
coinbase = common.HexToAddress("0x71562b71999873DB5b286dF957af199Ec94617F7")
|
||||||
|
account1 = common.HexToAddress("0x687704DB07e902e9A8B3754031D168D46E3D586e")
|
||||||
|
account2 = common.HexToAddress("0x6177843db3138ae69679A54b95cf345ED759450d")
|
||||||
|
gspec = &Genesis{
|
||||||
|
Config: config,
|
||||||
|
Alloc: GenesisAlloc{
|
||||||
|
coinbase: GenesisAccount{
|
||||||
|
Balance: big.NewInt(1000000000000000000), // 1 ether
|
||||||
|
Nonce: 0,
|
||||||
|
},
|
||||||
|
account1: GenesisAccount{
|
||||||
|
Balance: big.NewInt(1000000000000000000), // 1 ether
|
||||||
|
Nonce: 0,
|
||||||
|
},
|
||||||
|
account2: GenesisAccount{
|
||||||
|
Balance: big.NewInt(1000000000000000000), // 1 ether
|
||||||
|
Nonce: 3,
|
||||||
|
},
|
||||||
|
params.HistoryStorageAddress: GenesisAccount{
|
||||||
|
Balance: big.NewInt(0),
|
||||||
|
Nonce: 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
// The goal of this test is to test SELFDESTRUCT that happens in a contract execution which is created
|
||||||
|
// in a *previous* transaction sending the remaining balance to itself.
|
||||||
|
|
||||||
|
selfDestructContract := []byte{
|
||||||
|
0x60, 22, // PUSH1 22
|
||||||
|
0x60, 12, // PUSH1 12
|
||||||
|
0x60, 0x00, // PUSH1 0
|
||||||
|
0x39, // CODECOPY
|
||||||
|
|
||||||
|
0x60, 22, // PUSH1 22
|
||||||
|
0x60, 0x00, // PUSH1 0
|
||||||
|
0xF3, // RETURN
|
||||||
|
|
||||||
|
// Deployed code
|
||||||
|
0x73, // PUSH20
|
||||||
|
0x3a, 0x22, 0x0f, 0x35, 0x12, 0x52, 0x08, 0x9d, 0x38, 0x5b, 0x29, 0xbe, 0xca, 0x14, 0xe2, 0x7f, 0x20, 0x4c, 0x29, 0x6a, // 0x3a220f351252089d385b29beca14e27f204c296a
|
||||||
|
0xFF, // SELFDESTRUCT
|
||||||
|
}
|
||||||
|
selfDestructContractAddr := common.HexToAddress("3a220f351252089d385b29beca14e27f204c296a")
|
||||||
|
_, _, _, _, statediffs := GenerateVerkleChainWithGenesis(gspec, beacon.New(ethash.NewFaker()), 2, func(i int, gen *BlockGen) {
|
||||||
|
gen.SetPoS()
|
||||||
|
if i == 0 {
|
||||||
|
// Create selfdestruct contract, sending 42 wei.
|
||||||
|
tx, _ := types.SignTx(types.NewContractCreation(0, big.NewInt(42), 100_000, big.NewInt(875000000), selfDestructContract), signer, testKey)
|
||||||
|
gen.AddTx(tx)
|
||||||
|
} else {
|
||||||
|
// Call it.
|
||||||
|
tx, _ := types.SignTx(types.NewTransaction(1, selfDestructContractAddr, big.NewInt(0), 100_000, big.NewInt(875000000), nil), signer, testKey)
|
||||||
|
gen.AddTx(tx)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
{
|
||||||
|
// Check self-destructed contract in the witness.
|
||||||
|
// The way 6780 is implemented today, it always SubBalance from the self-destructed contract, and AddBalance
|
||||||
|
// to the beneficiary. In this case both addresses are the same, thus this might be optimizable from a gas
|
||||||
|
// perspective. But until that happens, we need to honor this "balance reading" adding it to the witness.
|
||||||
|
|
||||||
|
selfDestructContractTreeKey := utils.CodeHashKey(selfDestructContractAddr[:])
|
||||||
|
|
||||||
|
var stateDiffIdx = -1
|
||||||
|
for i, stemStateDiff := range statediffs[1] {
|
||||||
|
if bytes.Equal(stemStateDiff.Stem[:], selfDestructContractTreeKey[:31]) {
|
||||||
|
stateDiffIdx = i
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if stateDiffIdx == -1 {
|
||||||
|
t.Fatalf("no state diff found for stem")
|
||||||
|
}
|
||||||
|
|
||||||
|
balanceStateDiff := statediffs[1][stateDiffIdx].SuffixDiffs[0]
|
||||||
|
if balanceStateDiff.Suffix != utils.BasicDataLeafKey {
|
||||||
|
t.Fatalf("balance invalid suffix")
|
||||||
|
}
|
||||||
|
|
||||||
|
// The original balance was 42.
|
||||||
|
var fourtyTwo [16]byte
|
||||||
|
fourtyTwo[15] = 42
|
||||||
|
if !bytes.Equal((*balanceStateDiff.CurrentValue)[utils.BasicDataBalanceOffset:], fourtyTwo[:]) {
|
||||||
|
t.Fatalf("the pre-state balance before self-destruct must be 42")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Note that the SubBalance+AddBalance net effect is a 0 change, so NewValue
|
||||||
|
// must be nil.
|
||||||
|
if balanceStateDiff.NewValue != nil {
|
||||||
|
t.Fatalf("the post-state balance after self-destruct must be empty")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestProcessVerkleSelfDestructInSameTxWithSelfBeneficiary(t *testing.T) {
|
||||||
|
var (
|
||||||
|
config = ¶ms.ChainConfig{
|
||||||
|
ChainID: big.NewInt(69421),
|
||||||
|
HomesteadBlock: big.NewInt(0),
|
||||||
|
EIP150Block: big.NewInt(0),
|
||||||
|
EIP155Block: big.NewInt(0),
|
||||||
|
EIP158Block: big.NewInt(0),
|
||||||
|
ByzantiumBlock: big.NewInt(0),
|
||||||
|
ConstantinopleBlock: big.NewInt(0),
|
||||||
|
PetersburgBlock: big.NewInt(0),
|
||||||
|
IstanbulBlock: big.NewInt(0),
|
||||||
|
MuirGlacierBlock: big.NewInt(0),
|
||||||
|
BerlinBlock: big.NewInt(0),
|
||||||
|
LondonBlock: big.NewInt(0),
|
||||||
|
Ethash: new(params.EthashConfig),
|
||||||
|
ShanghaiTime: u64(0),
|
||||||
|
VerkleTime: u64(0),
|
||||||
|
TerminalTotalDifficulty: common.Big0,
|
||||||
|
TerminalTotalDifficultyPassed: true,
|
||||||
|
}
|
||||||
|
signer = types.LatestSigner(config)
|
||||||
|
testKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
|
||||||
|
coinbase = common.HexToAddress("0x71562b71999873DB5b286dF957af199Ec94617F7")
|
||||||
|
account1 = common.HexToAddress("0x687704DB07e902e9A8B3754031D168D46E3D586e")
|
||||||
|
account2 = common.HexToAddress("0x6177843db3138ae69679A54b95cf345ED759450d")
|
||||||
|
gspec = &Genesis{
|
||||||
|
Config: config,
|
||||||
|
Alloc: GenesisAlloc{
|
||||||
|
coinbase: GenesisAccount{
|
||||||
|
Balance: big.NewInt(1000000000000000000), // 1 ether
|
||||||
|
Nonce: 0,
|
||||||
|
},
|
||||||
|
account1: GenesisAccount{
|
||||||
|
Balance: big.NewInt(1000000000000000000), // 1 ether
|
||||||
|
Nonce: 0,
|
||||||
|
},
|
||||||
|
account2: GenesisAccount{
|
||||||
|
Balance: big.NewInt(1000000000000000000), // 1 ether
|
||||||
|
Nonce: 3,
|
||||||
|
},
|
||||||
|
params.HistoryStorageAddress: GenesisAccount{
|
||||||
|
Balance: big.NewInt(0),
|
||||||
|
Nonce: 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
// The goal of this test is to test SELFDESTRUCT that happens in a contract execution which is created
|
||||||
|
// in **the same** transaction sending the remaining balance to itself.
|
||||||
|
|
||||||
|
selfDestructContract := []byte{
|
||||||
|
0x73, // PUSH20
|
||||||
|
0x3a, 0x22, 0x0f, 0x35, 0x12, 0x52, 0x08, 0x9d, 0x38, 0x5b, 0x29, 0xbe, 0xca, 0x14, 0xe2, 0x7f, 0x20, 0x4c, 0x29, 0x6a, // 0x3a220f351252089d385b29beca14e27f204c296a
|
||||||
|
0xFF, // SELFDESTRUCT
|
||||||
|
}
|
||||||
|
selfDestructContractAddr := common.HexToAddress("3a220f351252089d385b29beca14e27f204c296a")
|
||||||
|
_, _, _, _, statediffs := GenerateVerkleChainWithGenesis(gspec, beacon.New(ethash.NewFaker()), 1, func(i int, gen *BlockGen) {
|
||||||
|
gen.SetPoS()
|
||||||
|
tx, _ := types.SignTx(types.NewContractCreation(0, big.NewInt(42), 100_000, big.NewInt(875000000), selfDestructContract), signer, testKey)
|
||||||
|
gen.AddTx(tx)
|
||||||
|
})
|
||||||
|
|
||||||
|
{ // Check self-destructed contract in the witness
|
||||||
|
selfDestructContractTreeKey := utils.CodeHashKey(selfDestructContractAddr[:])
|
||||||
|
|
||||||
|
var stateDiffIdx = -1
|
||||||
|
for i, stemStateDiff := range statediffs[0] {
|
||||||
|
if bytes.Equal(stemStateDiff.Stem[:], selfDestructContractTreeKey[:31]) {
|
||||||
|
stateDiffIdx = i
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if stateDiffIdx == -1 {
|
||||||
|
t.Fatalf("no state diff found for stem")
|
||||||
|
}
|
||||||
|
|
||||||
|
balanceStateDiff := statediffs[0][stateDiffIdx].SuffixDiffs[0]
|
||||||
|
if balanceStateDiff.Suffix != utils.BasicDataLeafKey {
|
||||||
|
t.Fatalf("balance invalid suffix")
|
||||||
|
}
|
||||||
|
|
||||||
|
if balanceStateDiff.CurrentValue != nil {
|
||||||
|
t.Fatalf("the pre-state balance before must be nil, since the contract didn't exist")
|
||||||
|
}
|
||||||
|
|
||||||
|
if balanceStateDiff.NewValue != nil {
|
||||||
|
t.Fatalf("the post-state balance after self-destruct must be nil since the contract shouldn't be created at all")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -174,22 +174,6 @@ func (t *VerkleTrie) UpdateStorage(address common.Address, key, value []byte) er
|
||||||
// trie. If the account was not existent in the trie, no error will be returned.
|
// trie. If the account was not existent in the trie, no error will be returned.
|
||||||
// If the trie is corrupted, an error will be returned.
|
// If the trie is corrupted, an error will be returned.
|
||||||
func (t *VerkleTrie) DeleteAccount(addr common.Address) error {
|
func (t *VerkleTrie) DeleteAccount(addr common.Address) error {
|
||||||
var (
|
|
||||||
err error
|
|
||||||
values = make([][]byte, verkle.NodeWidth)
|
|
||||||
)
|
|
||||||
for i := 0; i < verkle.NodeWidth; i++ {
|
|
||||||
values[i] = zero[:]
|
|
||||||
}
|
|
||||||
switch n := t.root.(type) {
|
|
||||||
case *verkle.InternalNode:
|
|
||||||
err = n.InsertValuesAtStem(t.cache.GetStem(addr.Bytes()), values, t.nodeResolver)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("DeleteAccount (%x) error: %v", addr, err)
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
return errInvalidRootType
|
|
||||||
}
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue