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") | 		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)
 | // - Add the contents of the optional tx access list (2930)
 | ||||||
| //
 | //
 | ||||||
| // Potential EIPs:
 | // Potential EIPs:
 | ||||||
| // - Reset transient storage(1153)
 | // - Reset access list (Berlin)
 | ||||||
| func (s *StateDB) Prepare(rules params.Rules, sender common.Address, dst *common.Address, precompiles []common.Address, list types.AccessList) { | // - 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 { | 	if rules.IsBerlin { | ||||||
| 		// Clear out any leftover from previous executions
 | 		// Clear out any leftover from previous executions
 | ||||||
| 		s.accessList = newAccessList() | 		al := newAccessList() | ||||||
|  | 		s.accessList = al | ||||||
| 
 | 
 | ||||||
| 		s.AddAddressToAccessList(sender) | 		al.AddAddress(sender) | ||||||
| 		if dst != nil { | 		if dst != nil { | ||||||
| 			s.AddAddressToAccessList(*dst) | 			al.AddAddress(*dst) | ||||||
| 			// If it's a create-tx, the destination will be added inside evm.create
 | 			// If it's a create-tx, the destination will be added inside evm.create
 | ||||||
| 		} | 		} | ||||||
| 		for _, addr := range precompiles { | 		for _, addr := range precompiles { | ||||||
| 			s.AddAddressToAccessList(addr) | 			al.AddAddress(addr) | ||||||
| 		} | 		} | ||||||
| 		for _, el := range list { | 		for _, el := range list { | ||||||
| 			s.AddAddressToAccessList(el.Address) | 			al.AddAddress(el.Address) | ||||||
| 			for _, key := range el.StorageKeys { | 			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
 | 	// Reset transient storage at the beginning of transaction execution
 | ||||||
| 	s.transientStorage = newTransientStorage() | 	s.transientStorage = newTransientStorage() | ||||||
|  | |||||||
| @ -322,7 +322,7 @@ func (st *StateTransition) TransitionDb() (*ExecutionResult, error) { | |||||||
| 	// Execute the preparatory steps for state transition which includes:
 | 	// Execute the preparatory steps for state transition which includes:
 | ||||||
| 	// - prepare accessList(post-berlin)
 | 	// - prepare accessList(post-berlin)
 | ||||||
| 	// - reset transient storage(eip 1153)
 | 	// - 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 ( | 	var ( | ||||||
| 		ret   []byte | 		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
 | 	// 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
 | 	// even if the feature/fork is not active yet
 | ||||||
| 	AddSlotToAccessList(addr common.Address, slot common.Hash) | 	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) | 	RevertToSnapshot(int) | ||||||
| 	Snapshot() 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:
 | 	// Execute the preparatory steps for state transition which includes:
 | ||||||
| 	// - prepare accessList(post-berlin)
 | 	// - prepare accessList(post-berlin)
 | ||||||
| 	// - reset transient storage(eip 1153)
 | 	// - 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) | 	cfg.State.CreateAccount(address) | ||||||
| 	// set the receiver's (the executing contract) code for execution.
 | 	// 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:
 | 	// Execute the preparatory steps for state transition which includes:
 | ||||||
| 	// - prepare accessList(post-berlin)
 | 	// - prepare accessList(post-berlin)
 | ||||||
| 	// - reset transient storage(eip 1153)
 | 	// - 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.
 | 	// Call the code with the given configuration.
 | ||||||
| 	code, address, leftOverGas, err := vmenv.Create( | 	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:
 | 	// Execute the preparatory steps for state transition which includes:
 | ||||||
| 	// - prepare accessList(post-berlin)
 | 	// - prepare accessList(post-berlin)
 | ||||||
| 	// - reset transient storage(eip 1153)
 | 	// - 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.
 | 	// Call the code with the given configuration.
 | ||||||
| 	ret, leftOverGas, err := vmenv.Call( | 	ret, leftOverGas, err := vmenv.Call( | ||||||
|  | |||||||
| @ -241,7 +241,7 @@ func runBenchmark(b *testing.B, t *StateTest) { | |||||||
| 			b.ResetTimer() | 			b.ResetTimer() | ||||||
| 			for n := 0; n < b.N; n++ { | 			for n := 0; n < b.N; n++ { | ||||||
| 				snapshot := statedb.Snapshot() | 				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() | 				b.StartTimer() | ||||||
| 				start := time.Now() | 				start := time.Now() | ||||||
| 
 | 
 | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user