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
|
||||
// later one writes zero net bytes; the earlier indicator charge is refilled.
|
||||
func TestAuthClearSameTxDoubleRefill(t *testing.T) {
|
||||
// 0->a->0 in one tx: the AUTH_BASE state charge for the indicator set by an
|
||||
// earlier auth is levied once and is never credited back, even when a later
|
||||
// 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)
|
||||
clr, _ := signAuth(t, authKeyA, common.Address{}, 1)
|
||||
sdb := mkState(senderAlloc(nil))
|
||||
|
|
@ -676,8 +678,8 @@ func TestAuthClearSameTxDoubleRefill(t *testing.T) {
|
|||
t.Fatal(err)
|
||||
}
|
||||
_ = authority
|
||||
if want := newAccountState; gp.cumulativeState != want {
|
||||
t.Fatalf("state gas = %d, want %d (net-zero delegation)", gp.cumulativeState, want)
|
||||
if want := authWorstState; 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) {
|
||||
auth, _ := signAuth(t, authKeyA, delegate8037, 0)
|
||||
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)
|
||||
}
|
||||
if want := params.AccountWriteAmsterdam; st.gasRemaining.UsedRegularGas != want {
|
||||
|
|
@ -62,7 +62,7 @@ func TestAuthRuntimeChargeNetNew(t *testing.T) {
|
|||
func TestAuthRuntimeChargeExistingAccount(t *testing.T) {
|
||||
auth, authority := signAuth(t, authKeyA, delegate8037, 0)
|
||||
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)
|
||||
}
|
||||
if want := params.AccountWriteAmsterdam; st.gasRemaining.UsedRegularGas != want {
|
||||
|
|
@ -81,7 +81,7 @@ func TestAuthRuntimeChargeWarmAuthority(t *testing.T) {
|
|||
auth, authority := signAuth(t, authKeyA, delegate8037, 0)
|
||||
st := newAuthTestTransition(mkState(senderAlloc(types.GenesisAlloc{authority: {Balance: big.NewInt(1)}})))
|
||||
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)
|
||||
}
|
||||
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
|
||||
})
|
||||
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")
|
||||
}
|
||||
if st.gasRemaining.UsedRegularGas != 0 || st.gasRemaining.UsedStateGas != 0 {
|
||||
|
|
@ -115,7 +115,7 @@ func TestAuthRuntimeDuplicateAuthorityOnce(t *testing.T) {
|
|||
a0, _ := signAuth(t, authKeyA, delegate8037, 0)
|
||||
a1, _ := signAuth(t, authKeyA, delegate8037, 1)
|
||||
st := newAuthTestTransition(mkState(senderAlloc(nil)))
|
||||
delegates := map[common.Address]bool{}
|
||||
delegates := map[common.Address]*authDelegationState{}
|
||||
if err := st.applyAuthorization(rules8037, &a0, delegates); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
|
@ -136,7 +136,7 @@ func TestAuthRuntimeOutOfGas(t *testing.T) {
|
|||
auth, authority := signAuth(t, authKeyA, delegate8037, 0)
|
||||
st := newAuthTestTransition(mkState(senderAlloc(nil)))
|
||||
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)
|
||||
}
|
||||
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
|
||||
if rules.IsAmsterdam {
|
||||
txRegularGas = max(txRegularGas, floorDataGas)
|
||||
if err = st.gp.ChargeGasAmsterdam(txRegularGas, txStateGas, gasUsed); err != nil {
|
||||
return 0, 0, err
|
||||
}
|
||||
|
|
@ -1043,8 +1044,17 @@ func (st *stateTransition) validateAuthorization(auth *types.SetCodeAuthorizatio
|
|||
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.
|
||||
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)
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
@ -1062,11 +1072,12 @@ func (st *stateTransition) applyAuthorization(rules params.Rules, auth *types.Se
|
|||
var cost vm.GasCosts
|
||||
authBase := params.AuthorizationCreationSize * st.evm.Context.CostPerStateByte
|
||||
|
||||
preDelegated, seen := delegates[authority]
|
||||
track, seen := delegates[authority]
|
||||
if !seen {
|
||||
preDelegated = curDelegated
|
||||
delegates[authority] = preDelegated
|
||||
track = &authDelegationState{preDelegated: curDelegated}
|
||||
delegates[authority] = track
|
||||
}
|
||||
preDelegated := track.preDelegated
|
||||
// Every valid authorization writes the authority account: the
|
||||
// nonce bump, and possibly the delegation indicator. The first
|
||||
// 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) {
|
||||
cost.StateGas += params.AccountCreationSize * st.evm.Context.CostPerStateByte
|
||||
}
|
||||
// Writing the 23-byte delegation indicator into a previously empty
|
||||
// slot adds net-new state bytes. Overwriting an occupied slot, or one
|
||||
// occupied at transaction start, writes no new bytes.
|
||||
if auth.Address != (common.Address{}) && !curDelegated && !preDelegated {
|
||||
// Writing the 23-byte delegation indicator adds net-new state bytes when
|
||||
// the authority held no delegation at the start of the transaction and
|
||||
// none has been set for it earlier in the transaction. This AUTH_BASE
|
||||
// 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
|
||||
}
|
||||
// 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) {
|
||||
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.
|
||||
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
|
||||
// charges.
|
||||
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 {
|
||||
if err := st.applyAuthorization(rules, &auth, preDelegated); err == ErrOutOfGasRuntime {
|
||||
if err := st.applyAuthorization(rules, &auth, delegates); err == ErrOutOfGasRuntime {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue