mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-19 11:20:45 +00:00
missing fixes
This commit is contained in:
parent
a4f9402459
commit
2d40820732
3 changed files with 42 additions and 31 deletions
|
|
@ -665,9 +665,11 @@ func TestAuthClearRefillBase(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 0->a->0 in one tx: the indicator created by an earlier auth and cleared by a
|
// 0->a->0 in one tx: the AUTH_BASE state charge for the indicator set by an
|
||||||
// later one writes zero net bytes; the earlier indicator charge is refilled.
|
// earlier auth is levied once and is never credited back, even when a later
|
||||||
func TestAuthClearSameTxDoubleRefill(t *testing.T) {
|
// auth clears the indicator in the same transaction. The account leaf charge
|
||||||
|
// plus the kept AUTH_BASE charge remain.
|
||||||
|
func TestAuthClearSameTxKeepsCharge(t *testing.T) {
|
||||||
set, authority := signAuth(t, authKeyA, delegate8037, 0)
|
set, authority := signAuth(t, authKeyA, delegate8037, 0)
|
||||||
clr, _ := signAuth(t, authKeyA, common.Address{}, 1)
|
clr, _ := signAuth(t, authKeyA, common.Address{}, 1)
|
||||||
sdb := mkState(senderAlloc(nil))
|
sdb := mkState(senderAlloc(nil))
|
||||||
|
|
@ -676,8 +678,8 @@ func TestAuthClearSameTxDoubleRefill(t *testing.T) {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
_ = authority
|
_ = authority
|
||||||
if want := newAccountState; gp.cumulativeState != want {
|
if want := authWorstState; gp.cumulativeState != want {
|
||||||
t.Fatalf("state gas = %d, want %d (net-zero delegation)", gp.cumulativeState, want)
|
t.Fatalf("state gas = %d, want %d (account leaf + kept AUTH_BASE)", gp.cumulativeState, want)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,7 @@ func newAuthTestTransition(sdb *state.StateDB) *stateTransition {
|
||||||
func TestAuthRuntimeChargeNetNew(t *testing.T) {
|
func TestAuthRuntimeChargeNetNew(t *testing.T) {
|
||||||
auth, _ := signAuth(t, authKeyA, delegate8037, 0)
|
auth, _ := signAuth(t, authKeyA, delegate8037, 0)
|
||||||
st := newAuthTestTransition(mkState(senderAlloc(nil)))
|
st := newAuthTestTransition(mkState(senderAlloc(nil)))
|
||||||
if err := st.applyAuthorization(rules8037, &auth, map[common.Address]bool{}); err != nil {
|
if err := st.applyAuthorization(rules8037, &auth, map[common.Address]*authDelegationState{}); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
if want := params.AccountWriteAmsterdam; st.gasRemaining.UsedRegularGas != want {
|
if want := params.AccountWriteAmsterdam; st.gasRemaining.UsedRegularGas != want {
|
||||||
|
|
@ -62,7 +62,7 @@ func TestAuthRuntimeChargeNetNew(t *testing.T) {
|
||||||
func TestAuthRuntimeChargeExistingAccount(t *testing.T) {
|
func TestAuthRuntimeChargeExistingAccount(t *testing.T) {
|
||||||
auth, authority := signAuth(t, authKeyA, delegate8037, 0)
|
auth, authority := signAuth(t, authKeyA, delegate8037, 0)
|
||||||
st := newAuthTestTransition(mkState(senderAlloc(types.GenesisAlloc{authority: {Balance: big.NewInt(1)}})))
|
st := newAuthTestTransition(mkState(senderAlloc(types.GenesisAlloc{authority: {Balance: big.NewInt(1)}})))
|
||||||
if err := st.applyAuthorization(rules8037, &auth, map[common.Address]bool{}); err != nil {
|
if err := st.applyAuthorization(rules8037, &auth, map[common.Address]*authDelegationState{}); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
if want := params.AccountWriteAmsterdam; st.gasRemaining.UsedRegularGas != want {
|
if want := params.AccountWriteAmsterdam; st.gasRemaining.UsedRegularGas != want {
|
||||||
|
|
@ -81,7 +81,7 @@ func TestAuthRuntimeChargeWarmAuthority(t *testing.T) {
|
||||||
auth, authority := signAuth(t, authKeyA, delegate8037, 0)
|
auth, authority := signAuth(t, authKeyA, delegate8037, 0)
|
||||||
st := newAuthTestTransition(mkState(senderAlloc(types.GenesisAlloc{authority: {Balance: big.NewInt(1)}})))
|
st := newAuthTestTransition(mkState(senderAlloc(types.GenesisAlloc{authority: {Balance: big.NewInt(1)}})))
|
||||||
st.state.AddAddressToAccessList(authority)
|
st.state.AddAddressToAccessList(authority)
|
||||||
if err := st.applyAuthorization(rules8037, &auth, map[common.Address]bool{}); err != nil {
|
if err := st.applyAuthorization(rules8037, &auth, map[common.Address]*authDelegationState{}); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
if want := params.AccountWriteAmsterdam; st.gasRemaining.UsedRegularGas != want {
|
if want := params.AccountWriteAmsterdam; st.gasRemaining.UsedRegularGas != want {
|
||||||
|
|
@ -99,7 +99,7 @@ func TestAuthRuntimeInvalidNoCharge(t *testing.T) {
|
||||||
ChainID: *uint256.NewInt(999), Address: delegate8037, Nonce: 0, // wrong chain id
|
ChainID: *uint256.NewInt(999), Address: delegate8037, Nonce: 0, // wrong chain id
|
||||||
})
|
})
|
||||||
st := newAuthTestTransition(mkState(senderAlloc(nil)))
|
st := newAuthTestTransition(mkState(senderAlloc(nil)))
|
||||||
if err := st.applyAuthorization(rules8037, &bad, map[common.Address]bool{}); err == nil {
|
if err := st.applyAuthorization(rules8037, &bad, map[common.Address]*authDelegationState{}); err == nil {
|
||||||
t.Fatal("expected invalid-authorization error")
|
t.Fatal("expected invalid-authorization error")
|
||||||
}
|
}
|
||||||
if st.gasRemaining.UsedRegularGas != 0 || st.gasRemaining.UsedStateGas != 0 {
|
if st.gasRemaining.UsedRegularGas != 0 || st.gasRemaining.UsedStateGas != 0 {
|
||||||
|
|
@ -115,7 +115,7 @@ func TestAuthRuntimeDuplicateAuthorityOnce(t *testing.T) {
|
||||||
a0, _ := signAuth(t, authKeyA, delegate8037, 0)
|
a0, _ := signAuth(t, authKeyA, delegate8037, 0)
|
||||||
a1, _ := signAuth(t, authKeyA, delegate8037, 1)
|
a1, _ := signAuth(t, authKeyA, delegate8037, 1)
|
||||||
st := newAuthTestTransition(mkState(senderAlloc(nil)))
|
st := newAuthTestTransition(mkState(senderAlloc(nil)))
|
||||||
delegates := map[common.Address]bool{}
|
delegates := map[common.Address]*authDelegationState{}
|
||||||
if err := st.applyAuthorization(rules8037, &a0, delegates); err != nil {
|
if err := st.applyAuthorization(rules8037, &a0, delegates); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
@ -136,7 +136,7 @@ func TestAuthRuntimeOutOfGas(t *testing.T) {
|
||||||
auth, authority := signAuth(t, authKeyA, delegate8037, 0)
|
auth, authority := signAuth(t, authKeyA, delegate8037, 0)
|
||||||
st := newAuthTestTransition(mkState(senderAlloc(nil)))
|
st := newAuthTestTransition(mkState(senderAlloc(nil)))
|
||||||
st.gasRemaining = vm.NewGasBudget(10_000, 0) // covers neither leaf nor indicator
|
st.gasRemaining = vm.NewGasBudget(10_000, 0) // covers neither leaf nor indicator
|
||||||
if err := st.applyAuthorization(rules8037, &auth, map[common.Address]bool{}); err != ErrOutOfGasRuntime {
|
if err := st.applyAuthorization(rules8037, &auth, map[common.Address]*authDelegationState{}); err != ErrOutOfGasRuntime {
|
||||||
t.Fatalf("err = %v, want ErrOutOfGasRuntime", err)
|
t.Fatalf("err = %v, want ErrOutOfGasRuntime", err)
|
||||||
}
|
}
|
||||||
if st.state.GetNonce(authority) != 0 || len(st.state.GetCode(authority)) != 0 {
|
if st.state.GetNonce(authority) != 0 || len(st.state.GetCode(authority)) != 0 {
|
||||||
|
|
|
||||||
|
|
@ -991,6 +991,7 @@ func (st *stateTransition) settleGas(rules params.Rules, floorDataGas uint64) (g
|
||||||
|
|
||||||
// Settle down the final gas consumption in the block-level pool
|
// Settle down the final gas consumption in the block-level pool
|
||||||
if rules.IsAmsterdam {
|
if rules.IsAmsterdam {
|
||||||
|
txRegularGas = max(txRegularGas, floorDataGas)
|
||||||
if err = st.gp.ChargeGasAmsterdam(txRegularGas, txStateGas, gasUsed); err != nil {
|
if err = st.gp.ChargeGasAmsterdam(txRegularGas, txStateGas, gasUsed); err != nil {
|
||||||
return 0, 0, err
|
return 0, 0, err
|
||||||
}
|
}
|
||||||
|
|
@ -1043,8 +1044,17 @@ func (st *stateTransition) validateAuthorization(auth *types.SetCodeAuthorizatio
|
||||||
return authority, nil
|
return authority, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// authDelegationState tracks, per authority within a single transaction, the
|
||||||
|
// delegation state observed at transaction start and whether a (non-null)
|
||||||
|
// delegation has already been set for it earlier in the transaction. It mirrors
|
||||||
|
// the spec's `delegated_before_tx` flag and `delegation_set_for` set.
|
||||||
|
type authDelegationState struct {
|
||||||
|
preDelegated bool // authority carried a delegation at transaction start
|
||||||
|
setInTx bool // a non-null delegation was set for it earlier in this tx
|
||||||
|
}
|
||||||
|
|
||||||
// applyAuthorization applies an EIP-7702 code delegation to the state.
|
// applyAuthorization applies an EIP-7702 code delegation to the state.
|
||||||
func (st *stateTransition) applyAuthorization(rules params.Rules, auth *types.SetCodeAuthorization, delegates map[common.Address]bool) error {
|
func (st *stateTransition) applyAuthorization(rules params.Rules, auth *types.SetCodeAuthorization, delegates map[common.Address]*authDelegationState) error {
|
||||||
authority, err := st.validateAuthorization(auth)
|
authority, err := st.validateAuthorization(auth)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
@ -1062,11 +1072,12 @@ func (st *stateTransition) applyAuthorization(rules params.Rules, auth *types.Se
|
||||||
var cost vm.GasCosts
|
var cost vm.GasCosts
|
||||||
authBase := params.AuthorizationCreationSize * st.evm.Context.CostPerStateByte
|
authBase := params.AuthorizationCreationSize * st.evm.Context.CostPerStateByte
|
||||||
|
|
||||||
preDelegated, seen := delegates[authority]
|
track, seen := delegates[authority]
|
||||||
if !seen {
|
if !seen {
|
||||||
preDelegated = curDelegated
|
track = &authDelegationState{preDelegated: curDelegated}
|
||||||
delegates[authority] = preDelegated
|
delegates[authority] = track
|
||||||
}
|
}
|
||||||
|
preDelegated := track.preDelegated
|
||||||
// Every valid authorization writes the authority account: the
|
// Every valid authorization writes the authority account: the
|
||||||
// nonce bump, and possibly the delegation indicator. The first
|
// nonce bump, and possibly the delegation indicator. The first
|
||||||
// write to an account within the transaction carries the
|
// write to an account within the transaction carries the
|
||||||
|
|
@ -1091,25 +1102,23 @@ func (st *stateTransition) applyAuthorization(rules params.Rules, auth *types.Se
|
||||||
if st.state.Empty(authority) {
|
if st.state.Empty(authority) {
|
||||||
cost.StateGas += params.AccountCreationSize * st.evm.Context.CostPerStateByte
|
cost.StateGas += params.AccountCreationSize * st.evm.Context.CostPerStateByte
|
||||||
}
|
}
|
||||||
// Writing the 23-byte delegation indicator into a previously empty
|
// Writing the 23-byte delegation indicator adds net-new state bytes when
|
||||||
// slot adds net-new state bytes. Overwriting an occupied slot, or one
|
// the authority held no delegation at the start of the transaction and
|
||||||
// occupied at transaction start, writes no new bytes.
|
// none has been set for it earlier in the transaction. This AUTH_BASE
|
||||||
if auth.Address != (common.Address{}) && !curDelegated && !preDelegated {
|
// state charge is levied at most once per authority and is never
|
||||||
|
// credited back: a delegation set and then cleared within the same
|
||||||
|
// transaction keeps its charge.
|
||||||
|
if auth.Address != (common.Address{}) && !preDelegated && !track.setInTx {
|
||||||
cost.StateGas += authBase
|
cost.StateGas += authBase
|
||||||
}
|
}
|
||||||
// Clearing an indicator that was created by an earlier authorization
|
|
||||||
// within the same transaction writes zero net bytes; refill the
|
|
||||||
// earlier state charge as it is no longer justified.
|
|
||||||
//
|
|
||||||
// Note that the refund and the charges above can never apply to the
|
|
||||||
// same authorization. The ordering of the refund and the charge is
|
|
||||||
// therefore irrelevant.
|
|
||||||
if auth.Address == (common.Address{}) && curDelegated && !preDelegated {
|
|
||||||
st.gasRemaining.RefundState(authBase)
|
|
||||||
}
|
|
||||||
if !st.chargeRuntimeGas(cost) {
|
if !st.chargeRuntimeGas(cost) {
|
||||||
return ErrOutOfGasRuntime
|
return ErrOutOfGasRuntime
|
||||||
}
|
}
|
||||||
|
// Record that a non-null delegation has been set for this authority in
|
||||||
|
// this transaction, so a later set does not charge AUTH_BASE again.
|
||||||
|
if auth.Address != (common.Address{}) {
|
||||||
|
track.setInTx = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// Update nonce and account code.
|
// Update nonce and account code.
|
||||||
st.state.SetNonce(authority, auth.Nonce+1, tracing.NonceChangeAuthorization)
|
st.state.SetNonce(authority, auth.Nonce+1, tracing.NonceChangeAuthorization)
|
||||||
|
|
@ -1132,9 +1141,9 @@ func (st *stateTransition) applyAuthorization(rules params.Rules, auth *types.Se
|
||||||
// It reports whether the transaction budget covered all runtime authorization
|
// It reports whether the transaction budget covered all runtime authorization
|
||||||
// charges.
|
// charges.
|
||||||
func (st *stateTransition) applyAuthorizations(rules params.Rules, auths []types.SetCodeAuthorization) bool {
|
func (st *stateTransition) applyAuthorizations(rules params.Rules, auths []types.SetCodeAuthorization) bool {
|
||||||
preDelegated := make(map[common.Address]bool)
|
delegates := make(map[common.Address]*authDelegationState)
|
||||||
for _, auth := range auths {
|
for _, auth := range auths {
|
||||||
if err := st.applyAuthorization(rules, &auth, preDelegated); err == ErrOutOfGasRuntime {
|
if err := st.applyAuthorization(rules, &auth, delegates); err == ErrOutOfGasRuntime {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue