mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-19 18:32:23 +00:00
Record witness access in EXTCODEHASH (#370)
* instructions: add access witness recording for EXTCODEHASH * add test for EXTCODEHASH witness recording * add test for access witness EXTCODEHASH Signed-off-by: Ignacio Hagopian <jsign.uy@gmail.com> * do not touch version Signed-off-by: Ignacio Hagopian <jsign.uy@gmail.com> --------- Signed-off-by: Ignacio Hagopian <jsign.uy@gmail.com>
This commit is contained in:
parent
2e671ea446
commit
077ad8728f
2 changed files with 140 additions and 0 deletions
|
|
@ -37,6 +37,7 @@ import (
|
|||
"github.com/ethereum/go-ethereum/core/vm"
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
"github.com/ethereum/go-ethereum/trie/utils"
|
||||
|
||||
//"github.com/ethereum/go-ethereum/rlp"
|
||||
"github.com/ethereum/go-ethereum/trie"
|
||||
|
|
@ -794,3 +795,135 @@ func TestProcessVerkleContractWithEmptyCode(t *testing.T) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
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),
|
||||
PragueTime: u64(0),
|
||||
TerminalTotalDifficulty: common.Big0,
|
||||
TerminalTotalDifficultyPassed: true,
|
||||
ProofInBlocks: true,
|
||||
}
|
||||
signer = types.LatestSigner(config)
|
||||
testKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
|
||||
bcdb = rawdb.NewMemoryDatabase() // Database for the blockchain
|
||||
gendb = rawdb.NewMemoryDatabase() // Database for the block-generation code, they must be separate as they are path-based.
|
||||
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,
|
||||
},
|
||||
},
|
||||
}
|
||||
)
|
||||
// Verkle trees use the snapshot, which must be enabled before the
|
||||
// data is saved into the tree+database.
|
||||
genesis := gspec.MustCommit(bcdb)
|
||||
|
||||
// Commit the genesis block to the block-generation database as it
|
||||
// is now independent of the blockchain database.
|
||||
gspec.MustCommit(gendb)
|
||||
|
||||
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")
|
||||
_, _, _, statediff := GenerateVerkleChain(gspec.Config, genesis, beacon.New(ethash.NewFaker()), gendb, 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.GetTreeKeyCodeKeccak(dummyContractAddr[:])
|
||||
|
||||
var stateDiffIdx = -1
|
||||
for i, stemStateDiff := range statediff[1] {
|
||||
if bytes.Equal(stemStateDiff.Stem[:], contractKeccakTreeKey[:31]) {
|
||||
stateDiffIdx = i
|
||||
break
|
||||
}
|
||||
}
|
||||
if stateDiffIdx == -1 {
|
||||
t.Fatalf("no state diff found for stem")
|
||||
}
|
||||
|
||||
codeHashStateDiff := statediff[1][stateDiffIdx].SuffixDiffs[0]
|
||||
if codeHashStateDiff.Suffix != utils.CodeKeccakLeafKey {
|
||||
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")
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -485,6 +485,13 @@ func opExtCodeCopy(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext)
|
|||
func opExtCodeHash(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||
slot := scope.Stack.peek()
|
||||
address := common.Address(slot.Bytes20())
|
||||
if interpreter.evm.chainRules.IsPrague {
|
||||
statelessGas := interpreter.evm.Accesses.TouchAddressOnReadAndComputeGas(slot.Bytes(), uint256.Int{}, trieUtils.CodeKeccakLeafKey)
|
||||
if !scope.Contract.UseGas(statelessGas) {
|
||||
scope.Contract.Gas = 0
|
||||
return nil, ErrOutOfGas
|
||||
}
|
||||
}
|
||||
if interpreter.evm.StateDB.Empty(address) {
|
||||
slot.Clear()
|
||||
} else {
|
||||
|
|
|
|||
Loading…
Reference in a new issue