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/core/vm"
|
||||||
"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/utils"
|
||||||
|
|
||||||
//"github.com/ethereum/go-ethereum/rlp"
|
//"github.com/ethereum/go-ethereum/rlp"
|
||||||
"github.com/ethereum/go-ethereum/trie"
|
"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) {
|
func opExtCodeHash(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||||
slot := scope.Stack.peek()
|
slot := scope.Stack.peek()
|
||||||
address := common.Address(slot.Bytes20())
|
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) {
|
if interpreter.evm.StateDB.Empty(address) {
|
||||||
slot.Clear()
|
slot.Clear()
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue