forked from cerc-io/plugeth
		
	core: implement EIP-3651, warm coinbase (#25819)
Implements EIP-3651, "Warm Coinbase", for Shanghai hardfork. Specification: https://eips.ethereum.org/EIPS/eip-3651.
This commit is contained in:
		
							parent
							
								
									64dccf7aa4
								
							
						
					
					
						commit
						ec2ec2d08e
					
				| @ -4187,3 +4187,111 @@ func TestTransientStorageReset(t *testing.T) { | ||||
| 		t.Fatalf("Unexpected dirty storage slot") | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func TestEIP3651(t *testing.T) { | ||||
| 	var ( | ||||
| 		aa     = common.HexToAddress("0x000000000000000000000000000000000000aaaa") | ||||
| 		bb     = common.HexToAddress("0x000000000000000000000000000000000000bbbb") | ||||
| 		engine = ethash.NewFaker() | ||||
| 
 | ||||
| 		// A sender who makes transactions, has some funds
 | ||||
| 		key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") | ||||
| 		key2, _ = crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a") | ||||
| 		addr1   = crypto.PubkeyToAddress(key1.PublicKey) | ||||
| 		addr2   = crypto.PubkeyToAddress(key2.PublicKey) | ||||
| 		funds   = new(big.Int).Mul(common.Big1, big.NewInt(params.Ether)) | ||||
| 		gspec   = &Genesis{ | ||||
| 			Config: params.AllEthashProtocolChanges, | ||||
| 			Alloc: GenesisAlloc{ | ||||
| 				addr1: {Balance: funds}, | ||||
| 				addr2: {Balance: funds}, | ||||
| 				// The address 0xAAAA sloads 0x00 and 0x01
 | ||||
| 				aa: { | ||||
| 					Code: []byte{ | ||||
| 						byte(vm.PC), | ||||
| 						byte(vm.PC), | ||||
| 						byte(vm.SLOAD), | ||||
| 						byte(vm.SLOAD), | ||||
| 					}, | ||||
| 					Nonce:   0, | ||||
| 					Balance: big.NewInt(0), | ||||
| 				}, | ||||
| 				// The address 0xBBBB calls 0xAAAA
 | ||||
| 				bb: { | ||||
| 					Code: []byte{ | ||||
| 						byte(vm.PUSH1), 0, // out size
 | ||||
| 						byte(vm.DUP1),  // out offset
 | ||||
| 						byte(vm.DUP1),  // out insize
 | ||||
| 						byte(vm.DUP1),  // in offset
 | ||||
| 						byte(vm.PUSH2), // address
 | ||||
| 						byte(0xaa), | ||||
| 						byte(0xaa), | ||||
| 						byte(vm.GAS), // gas
 | ||||
| 						byte(vm.DELEGATECALL), | ||||
| 					}, | ||||
| 					Nonce:   0, | ||||
| 					Balance: big.NewInt(0), | ||||
| 				}, | ||||
| 			}, | ||||
| 		} | ||||
| 	) | ||||
| 
 | ||||
| 	gspec.Config.BerlinBlock = common.Big0 | ||||
| 	gspec.Config.LondonBlock = common.Big0 | ||||
| 	gspec.Config.ShanghaiBlock = common.Big0 | ||||
| 	signer := types.LatestSigner(gspec.Config) | ||||
| 
 | ||||
| 	_, blocks, _ := GenerateChainWithGenesis(gspec, engine, 1, func(i int, b *BlockGen) { | ||||
| 		b.SetCoinbase(aa) | ||||
| 		// One transaction to Coinbase
 | ||||
| 		txdata := &types.DynamicFeeTx{ | ||||
| 			ChainID:    gspec.Config.ChainID, | ||||
| 			Nonce:      0, | ||||
| 			To:         &bb, | ||||
| 			Gas:        500000, | ||||
| 			GasFeeCap:  newGwei(5), | ||||
| 			GasTipCap:  big.NewInt(2), | ||||
| 			AccessList: nil, | ||||
| 			Data:       []byte{}, | ||||
| 		} | ||||
| 		tx := types.NewTx(txdata) | ||||
| 		tx, _ = types.SignTx(tx, signer, key1) | ||||
| 
 | ||||
| 		b.AddTx(tx) | ||||
| 	}) | ||||
| 	chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), nil, gspec, nil, engine, vm.Config{Tracer: logger.NewMarkdownLogger(&logger.Config{}, os.Stderr)}, nil, nil) | ||||
| 	if err != nil { | ||||
| 		t.Fatalf("failed to create tester chain: %v", err) | ||||
| 	} | ||||
| 	if n, err := chain.InsertChain(blocks); err != nil { | ||||
| 		t.Fatalf("block %d: failed to insert into chain: %v", n, err) | ||||
| 	} | ||||
| 
 | ||||
| 	block := chain.GetBlockByNumber(1) | ||||
| 
 | ||||
| 	// 1+2: Ensure EIP-1559 access lists are accounted for via gas usage.
 | ||||
| 	innerGas := vm.GasQuickStep*2 + params.ColdSloadCostEIP2929*2 | ||||
| 	expectedGas := params.TxGas + 5*vm.GasFastestStep + vm.GasQuickStep + 100 + innerGas // 100 because 0xaaaa is in access list
 | ||||
| 	if block.GasUsed() != expectedGas { | ||||
| 		t.Fatalf("incorrect amount of gas spent: expected %d, got %d", expectedGas, block.GasUsed()) | ||||
| 	} | ||||
| 
 | ||||
| 	state, _ := chain.State() | ||||
| 
 | ||||
| 	// 3: Ensure that miner received only the tx's tip.
 | ||||
| 	actual := state.GetBalance(block.Coinbase()) | ||||
| 	expected := new(big.Int).Add( | ||||
| 		new(big.Int).SetUint64(block.GasUsed()*block.Transactions()[0].GasTipCap().Uint64()), | ||||
| 		ethash.ConstantinopleBlockReward, | ||||
| 	) | ||||
| 	if actual.Cmp(expected) != 0 { | ||||
| 		t.Fatalf("miner balance incorrect: expected %d, got %d", expected, actual) | ||||
| 	} | ||||
| 
 | ||||
| 	// 4: Ensure the tx sender paid for the gasUsed * (tip + block baseFee).
 | ||||
| 	actual = new(big.Int).Sub(funds, state.GetBalance(addr1)) | ||||
| 	expected = new(big.Int).SetUint64(block.GasUsed() * (block.Transactions()[0].GasTipCap().Uint64() + block.BaseFee().Uint64())) | ||||
| 	if actual.Cmp(expected) != 0 { | ||||
| 		t.Fatalf("sender balance incorrect: expected %d, got %d", expected, actual) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -1067,26 +1067,32 @@ func (s *StateDB) Commit(deleteEmptyObjects bool) (common.Hash, error) { | ||||
| // - Add the contents of the optional tx access list (2930)
 | ||||
| //
 | ||||
| // Potential EIPs:
 | ||||
| // - Reset transient storage(1153)
 | ||||
| func (s *StateDB) Prepare(rules params.Rules, sender common.Address, dst *common.Address, precompiles []common.Address, list types.AccessList) { | ||||
| // - Reset access list (Berlin)
 | ||||
| // - Add coinbase to access list (EIP-3651)
 | ||||
| // - Reset transient storage (EIP-1153)
 | ||||
| func (s *StateDB) Prepare(rules params.Rules, sender, coinbase common.Address, dst *common.Address, precompiles []common.Address, list types.AccessList) { | ||||
| 	if rules.IsBerlin { | ||||
| 		// Clear out any leftover from previous executions
 | ||||
| 		s.accessList = newAccessList() | ||||
| 		al := newAccessList() | ||||
| 		s.accessList = al | ||||
| 
 | ||||
| 		s.AddAddressToAccessList(sender) | ||||
| 		al.AddAddress(sender) | ||||
| 		if dst != nil { | ||||
| 			s.AddAddressToAccessList(*dst) | ||||
| 			al.AddAddress(*dst) | ||||
| 			// If it's a create-tx, the destination will be added inside evm.create
 | ||||
| 		} | ||||
| 		for _, addr := range precompiles { | ||||
| 			s.AddAddressToAccessList(addr) | ||||
| 			al.AddAddress(addr) | ||||
| 		} | ||||
| 		for _, el := range list { | ||||
| 			s.AddAddressToAccessList(el.Address) | ||||
| 			al.AddAddress(el.Address) | ||||
| 			for _, key := range el.StorageKeys { | ||||
| 				s.AddSlotToAccessList(el.Address, key) | ||||
| 				al.AddSlot(el.Address, key) | ||||
| 			} | ||||
| 		} | ||||
| 		if rules.IsShanghai { // EIP-3651: warm coinbase
 | ||||
| 			al.AddAddress(coinbase) | ||||
| 		} | ||||
| 	} | ||||
| 	// Reset transient storage at the beginning of transaction execution
 | ||||
| 	s.transientStorage = newTransientStorage() | ||||
|  | ||||
| @ -322,7 +322,7 @@ func (st *StateTransition) TransitionDb() (*ExecutionResult, error) { | ||||
| 	// Execute the preparatory steps for state transition which includes:
 | ||||
| 	// - prepare accessList(post-berlin)
 | ||||
| 	// - reset transient storage(eip 1153)
 | ||||
| 	st.state.Prepare(rules, msg.From(), msg.To(), vm.ActivePrecompiles(rules), msg.AccessList()) | ||||
| 	st.state.Prepare(rules, msg.From(), st.evm.Context.Coinbase, msg.To(), vm.ActivePrecompiles(rules), msg.AccessList()) | ||||
| 
 | ||||
| 	var ( | ||||
| 		ret   []byte | ||||
|  | ||||
| @ -69,7 +69,7 @@ type StateDB interface { | ||||
| 	// AddSlotToAccessList adds the given (address,slot) to the access list. This operation is safe to perform
 | ||||
| 	// even if the feature/fork is not active yet
 | ||||
| 	AddSlotToAccessList(addr common.Address, slot common.Hash) | ||||
| 	Prepare(rules params.Rules, sender common.Address, dest *common.Address, precompiles []common.Address, txAccesses types.AccessList) | ||||
| 	Prepare(rules params.Rules, sender, coinbase common.Address, dest *common.Address, precompiles []common.Address, txAccesses types.AccessList) | ||||
| 
 | ||||
| 	RevertToSnapshot(int) | ||||
| 	Snapshot() int | ||||
|  | ||||
| @ -122,7 +122,7 @@ func Execute(code, input []byte, cfg *Config) ([]byte, *state.StateDB, error) { | ||||
| 	// Execute the preparatory steps for state transition which includes:
 | ||||
| 	// - prepare accessList(post-berlin)
 | ||||
| 	// - reset transient storage(eip 1153)
 | ||||
| 	cfg.State.Prepare(rules, cfg.Origin, &address, vm.ActivePrecompiles(rules), nil) | ||||
| 	cfg.State.Prepare(rules, cfg.Origin, cfg.Coinbase, &address, vm.ActivePrecompiles(rules), nil) | ||||
| 
 | ||||
| 	cfg.State.CreateAccount(address) | ||||
| 	// set the receiver's (the executing contract) code for execution.
 | ||||
| @ -156,7 +156,7 @@ func Create(input []byte, cfg *Config) ([]byte, common.Address, uint64, error) { | ||||
| 	// Execute the preparatory steps for state transition which includes:
 | ||||
| 	// - prepare accessList(post-berlin)
 | ||||
| 	// - reset transient storage(eip 1153)
 | ||||
| 	cfg.State.Prepare(rules, cfg.Origin, nil, vm.ActivePrecompiles(rules), nil) | ||||
| 	cfg.State.Prepare(rules, cfg.Origin, cfg.Coinbase, nil, vm.ActivePrecompiles(rules), nil) | ||||
| 
 | ||||
| 	// Call the code with the given configuration.
 | ||||
| 	code, address, leftOverGas, err := vmenv.Create( | ||||
| @ -185,7 +185,7 @@ func Call(address common.Address, input []byte, cfg *Config) ([]byte, uint64, er | ||||
| 	// Execute the preparatory steps for state transition which includes:
 | ||||
| 	// - prepare accessList(post-berlin)
 | ||||
| 	// - reset transient storage(eip 1153)
 | ||||
| 	statedb.Prepare(rules, cfg.Origin, &address, vm.ActivePrecompiles(rules), nil) | ||||
| 	statedb.Prepare(rules, cfg.Origin, cfg.Coinbase, &address, vm.ActivePrecompiles(rules), nil) | ||||
| 
 | ||||
| 	// Call the code with the given configuration.
 | ||||
| 	ret, leftOverGas, err := vmenv.Call( | ||||
|  | ||||
| @ -241,7 +241,7 @@ func runBenchmark(b *testing.B, t *StateTest) { | ||||
| 			b.ResetTimer() | ||||
| 			for n := 0; n < b.N; n++ { | ||||
| 				snapshot := statedb.Snapshot() | ||||
| 				statedb.Prepare(rules, msg.From(), msg.To(), vm.ActivePrecompiles(rules), msg.AccessList()) | ||||
| 				statedb.Prepare(rules, msg.From(), context.Coinbase, msg.To(), vm.ActivePrecompiles(rules), msg.AccessList()) | ||||
| 				b.StartTimer() | ||||
| 				start := time.Now() | ||||
| 
 | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user