Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Account abstraction #13

Closed
wants to merge 114 commits into from
Closed
Show file tree
Hide file tree
Changes from 86 commits
Commits
Show all changes
114 commits
Select commit Hold shift + click to select a range
c1bd7ae
Use relative git submodule
May 6, 2020
238e704
Partially create a new opcode `PAYGAS`.
Apr 14, 2020
5154073
Grab opPaygas test
May 6, 2020
f9d3427
Merge pull request #1 from quilt/op-paygas
SamWilsn May 14, 2020
7b26baa
Included basic reorg timer. Will add higher definition timers soon.
villanuevawill May 16, 2020
2ea63f6
Include gauge on reorgs.
villanuevawill May 16, 2020
4505afa
Include additional meters to track definition on reorgs regarding # o…
villanuevawill May 16, 2020
1327ba7
Added validation timers. Tracking successful validation time vs. aver…
villanuevawill May 16, 2020
d373bb2
Include metrics dashboard export and prometheus settings/yaml file
villanuevawill May 17, 2020
fa6d79a
Added additional aa field to tx_list to be used in tx_pool for limiti…
villanuevawill May 19, 2020
5ed9330
Primitive implementation in place. One item in the queue, one item in…
villanuevawill May 20, 2020
0c13218
Cost and Signing returns correct values for AA transactions
villanuevawill May 21, 2020
e6eb1a2
Adjusted logic to allow for only one in pending/queued. Also remove t…
villanuevawill May 21, 2020
9917967
Merge pull request #2 from quilt/aa-metrics
villanuevawill May 21, 2020
3a82c2e
Only one tx allowed per AA account
villanuevawill May 21, 2020
79b6c79
Add flag for paygas mode to EVM interpreter
May 20, 2020
bfe712a
Merge pull request #3 from quilt/paygas-config
SamWilsn May 21, 2020
f1946b9
Support new AA transaction for now. Minor bugs around gas price, limit
villanuevawill May 22, 2020
eecdb02
Include initial set of passing tests to make sure queue and pool are …
villanuevawill May 22, 2020
bd81e01
Make certain instructions before PAYGAS invalid
May 26, 2020
0d45538
Merge pull request #5 from quilt/paygas-mode
SamWilsn May 27, 2020
1609219
Update tx pool to validate incoming transactions then replace queue/p…
villanuevawill May 28, 2020
108daa6
Expand tests to check for queue, pending replace. 1 tx limit for AA.
villanuevawill May 28, 2020
c798f81
For now remove reliance on Sender() function for aa from/addr field
villanuevawill May 29, 2020
ce81904
Add some direction for making sure the right tx is swapped with 1 tx …
villanuevawill May 29, 2020
afd41ce
Store the gas price popped by PAYGAS
Jun 1, 2020
6ac99c3
Remove logic that restricts new transactions from being validated.
villanuevawill Jun 1, 2020
5aad5a5
Remove ErrAACapacity. This isn't needed anymore.
villanuevawill Jun 1, 2020
92e2040
Merge pull request #9 from quilt/paygas-price
SamWilsn Jun 2, 2020
90df529
add support for ENTRY_POINT Address
adietrichs May 24, 2020
1f8eab5
set transaction sender to ENTRY_POINT if r = s = 0 and v = (27 or CHA…
adietrichs May 24, 2020
7761592
only allow EIP 155 AA txs (i.e. with v = CHAIN_ID * 2 + 35)
adietrichs May 25, 2020
7a442c5
added isAA field to transaction message struct
adietrichs May 26, 2020
1d4b15f
added AA handling to TransitionDb()
adietrichs May 26, 2020
7421f33
added IsAA message support for tests
adietrichs May 26, 2020
7726149
added IsAA method to the Transaction struct
adietrichs May 29, 2020
5e9e4e9
added Validate method to Transaction struct
adietrichs May 29, 2020
927ef82
moved Validate to new transaction_validator.go file to avoid import c…
adietrichs May 29, 2020
8236909
added Sponsor() to transaction message interface
adietrichs May 29, 2020
cd2d071
Add a gasLimit parameter to the Validate() function for AA transactions.
adietrichs May 29, 2020
05c26d9
Set msg.checkNonce to false for AA transactions
adietrichs Jun 2, 2020
c0977bf
Enforce 0 for unused transaction fields of AA transactions
adietrichs Jun 2, 2020
67dda34
Add paygasPrice to interpreter config
adietrichs Jun 2, 2020
5873f9b
Sync AA paygas config between EVM and interpreters
adietrichs Jun 2, 2020
1add179
Use paygasPrice for AA transaction refund after execution
adietrichs Jun 2, 2020
2b7b53e
Update Validate() to use the new paygasPrice field
adietrichs Jun 2, 2020
8353d91
Set paygasMode to PaygasContinue when preparing for AA transaction ex…
adietrichs Jun 2, 2020
d0aa829
Return error from st.TransitionDb() if PAYGAS was not called successf…
adietrichs Jun 2, 2020
9e8c99f
Deal with edge case where a txlist is AA, but tx is not AA (or vice v…
villanuevawill Jun 2, 2020
b4d1e84
Skip initial payment for gas for AA transactions
adietrichs Jun 3, 2020
f89c7ea
Add gas payment to PAYGAS, return error if balance insufficient
adietrichs Jun 3, 2020
b4f58f8
Merge pull request #8 from quilt/aa-tx-execution
adietrichs Jun 3, 2020
81e855a
fixed typo: !operation.internal
adietrichs Jun 5, 2020
6f5499a
Add support for non-EIP155 AA transactions
adietrichs Jun 5, 2020
bb806d1
Add paygasLimit to vmConfig and EVMInterpreter
adietrichs Jun 5, 2020
e68667a
Use paygasLimit to pass the gas limit from TransitionDb() to opPaygas()
adietrichs Jun 5, 2020
7eb1709
Add AA support to NewMessage() used for testing
adietrichs Jun 5, 2020
f58163b
Interpret secretKey 0xaa as AA transaction when parsing retesteth tests
adietrichs Jun 5, 2020
46ef9c2
adjust paygasRevert retesteth test to make it pass
adietrichs Jun 5, 2020
3ddc462
Merge pull request #10 from quilt/aa-tx-execution
adietrichs Jun 8, 2020
f8e1997
Merge pull request #11 from quilt/aa-tests-retesteth
adietrichs Jun 8, 2020
8e42687
Fix several small bugs in Validate()
adietrichs Jun 9, 2020
6d5af97
Add tests for transaction validation
adietrichs Jun 9, 2020
20c3165
change Validate() to expect PaygasMode already set to PaygasHalt
adietrichs Jun 9, 2020
ebd04c3
Propagate any EVM errors as execution errors if they occur during Val…
adietrichs Jun 9, 2020
94d472c
Switch transaction validation tests to a more flexible test contract …
adietrichs Jun 9, 2020
6266fba
Small updates to transaction validation, including error for malforme…
adietrichs Jun 9, 2020
f2753fb
Add transaction validation tests for invalid evm config and malformed…
adietrichs Jun 9, 2020
e6c57f1
For test AA transaction creation, set the minimum number of loops to 1
adietrichs Jun 9, 2020
64ad2c4
Merge pull request #12 from quilt/aa-tx-execution
adietrichs Jun 9, 2020
9ad60c4
Merge branch 'account-abstraction' into aa_tx_ordering
villanuevawill Jun 9, 2020
4bbb669
Remove checks for a conflict betweeen possible incoming AA/nonAA tran…
villanuevawill Jun 9, 2020
46cc2fc
Move validation timers to a more appropriate space.
villanuevawill Jun 9, 2020
0e7626b
Removed unnecessary workarounds with Ansgar's submitted work
villanuevawill Jun 9, 2020
e17614a
Removed nonce exception for aa transactions, since we read it from th…
villanuevawill Jun 9, 2020
0c897bc
Add proper aa validation, also expand the blockchain interface to sup…
villanuevawill Jun 10, 2020
a3ce459
Add aa validation timer & update dummy message to entry message
villanuevawill Jun 10, 2020
6a78ca1
Remove mock validate and return proper type for GasPrice()
villanuevawill Jun 10, 2020
31005ff
Add expansive testing on pending, queue for aa transactions
villanuevawill Jun 10, 2020
253b684
Set config for AA gas limit allowed
villanuevawill Jun 10, 2020
82a54d0
Remove stale tests
villanuevawill Jun 10, 2020
fb1cbf9
General cleanup, use contract address vs. EOA, equality checks.
villanuevawill Jun 11, 2020
ea087ff
Include state snaphshot reversion on validation
villanuevawill Jun 11, 2020
afc79d2
Merge pull request #7 from quilt/aa_tx_ordering
villanuevawill Jun 11, 2020
e1666e2
Fix nonce issue for aa contracts
villanuevawill Jun 11, 2020
9f83812
Merge pull request #14 from quilt/bugfix/aa-nonce
villanuevawill Jun 11, 2020
3143261
Add transaction.Sponsor() method and use it to make block creation co…
adietrichs Jun 16, 2020
f40a2ac
Remove nonce-based check for AA transactions during mempool management
adietrichs Jun 16, 2020
c870412
Update AA transaction validation tests to make AA contract nonces sta…
adietrichs Jun 16, 2020
07c58c6
update testdata root to account-abstraction head
adietrichs Jun 16, 2020
a73274a
Merge pull request #16 from quilt/aa-mining
adietrichs Jun 17, 2020
306e7de
switch use of Signer to Sponsor in miner
lightclient Jun 22, 2020
2eab199
Price ordering by miner should take into account AA price vs raw price
villanuevawill Jun 22, 2020
9e002a8
Merge pull request #18 from quilt/quilt/miner-additions
lightclient Jun 22, 2020
5268cc4
Merge pull request #17 from quilt/fix-miner
lightclient Jun 22, 2020
8daf017
Update to sponsor
villanuevawill Jun 22, 2020
a405616
Merge pull request #19 from quilt/sender_update
villanuevawill Jun 22, 2020
cd4ce62
Add trace logging for validation errors
villanuevawill Jun 30, 2020
5fc0c1c
Add AA support to eth_sendTransaction
adietrichs Jun 30, 2020
810819a
Merge pull request #20 from quilt/aa-validate-log
villanuevawill Jul 1, 2020
176e6e5
Transactions are removed/re-validated properly for aa
villanuevawill Jul 2, 2020
3041530
Merge pull request #21 from quilt/aa-ethapi
adietrichs Jul 2, 2020
6321014
Split into elif in order to deal with pending or queue
villanuevawill Jul 2, 2020
0cad215
Merge pull request #22 from quilt/bugfix-aa-includedtxs
villanuevawill Jul 2, 2020
bf44f14
Add PaygasMode and TxGasLimit to VM Context struct
adietrichs Jul 2, 2020
4292a15
Add support for the new paygas Context fields to NewEVMContext()
adietrichs Jul 2, 2020
3424bda
Use the new paygas Context fields instead of the old vmConfig ones
adietrichs Jul 2, 2020
a4f4ad9
Remove old paygas fields from vmConfig and interpreter
adietrichs Jul 2, 2020
39c2312
remove unreachable check for unset TxGasLimit
adietrichs Jul 2, 2020
e8c4930
Update AA transaction validation tests to work with the new paygas Co…
adietrichs Jul 2, 2020
33b57e3
Set PaygasMode to PaygasHalt during Validate() instead of during NewE…
adietrichs Jul 3, 2020
d8061e1
Merge pull request #23 from quilt/aa-paygas-refactor
adietrichs Jul 3, 2020
816204f
Add basic support for STATICCALLs to precompiles before PAYGAS using …
adietrichs Jul 2, 2020
9c4f387
Merge pull request #24 from quilt/aa-precompiles
adietrichs Jul 3, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitmodules
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
[submodule "tests"]
path = tests/testdata
url = https://github.com/ethereum/tests
url = ../tests
8 changes: 8 additions & 0 deletions accounts/abi/bind/backends/simulated.go
Original file line number Diff line number Diff line change
Expand Up @@ -650,6 +650,14 @@ func (m callmsg) GasPrice() *big.Int { return m.CallMsg.GasPrice }
func (m callmsg) Gas() uint64 { return m.CallMsg.Gas }
func (m callmsg) Value() *big.Int { return m.CallMsg.Value }
func (m callmsg) Data() []byte { return m.CallMsg.Data }
func (m callmsg) IsAA() bool { return m.CallMsg.IsAA }
func (m callmsg) Sponsor() common.Address {
if !m.CallMsg.IsAA {
return m.CallMsg.From
} else {
return *m.CallMsg.To
}
}

// filterBackend implements filters.Backend to support filtering for logs without
// taking bloom-bits acceleration structures into account.
Expand Down
19 changes: 19 additions & 0 deletions common/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,15 @@ func (h UnprefixedHash) MarshalText() ([]byte, error) {
// Address represents the 20 byte address of an Ethereum account.
type Address [AddressLength]byte

// NewEntryPointAddress returns an ENTRY_POINT Address.
func NewEntryPointAddress() Address {
var a Address
for i := range a {
a[i] = 0xFF
}
return a
}

// BytesToAddress returns Address with value b.
// If b is larger than len(h), b will be cropped from the left.
func BytesToAddress(b []byte) Address {
Expand All @@ -200,6 +209,16 @@ func IsHexAddress(s string) bool {
return len(s) == 2*AddressLength && isHex(s)
}

// IsEntryPointAddress returns true if the Address is the ENTRY_POINT Address.
func (a Address) IsEntryPoint() bool {
for i := range a {
if a[i] != 0xFF {
return false
}
}
return true
}

// Bytes gets the string representation of the underlying address.
func (a Address) Bytes() []byte { return a[:] }

Expand Down
167 changes: 167 additions & 0 deletions core/aa_transaction_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
// Copyright 2015 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.

package core

import (
"encoding/binary"
"math/big"
"testing"

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/consensus/ethash"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/params"
)

const (
contractCode = "3373ffffffffffffffffffffffffffffffffffffffff1460245736601f57005b600080fd5b60016000355b81900380602a57602035603957005b604035aa00"
)

// aaTransaction creates a new AA transaction to a deployed instance of the test contract.
// Parameters are the contract address, the transaction gas limit,
// the number of loops to run inside the contract (minimum: 1, gas per loop: 26),
// whether to call PAYGAS at the end, the gas price to be returned from PAYGAS (if called).
func aaTransaction(to common.Address, gaslimit uint64, loops uint64, callPaygas bool, gasPrice *big.Int) *types.Transaction {
data := make([]byte, 0x60)
if loops == 0 {
loops = 1
}
binary.BigEndian.PutUint64(data[0x18:0x20], loops)
if callPaygas {
data[0x3f] = 1
}
gasPriceBytes := gasPrice.Bytes()
copy(data[0x60-len(gasPriceBytes):], gasPriceBytes)

return types.NewTransaction(0, to, big.NewInt(0), gaslimit, big.NewInt(0), data).WithAASignature()
}

func setupBlockchain(blockGasLimit uint64) *BlockChain {
genesis := Genesis{Config: params.AllEthashProtocolChanges, GasLimit: blockGasLimit}
database := rawdb.NewMemoryDatabase()
genesis.MustCommit(database)
blockchain, _ := NewBlockChain(database, nil, genesis.Config, ethash.NewFaker(), vm.Config{}, nil)
return blockchain
}

func testValidate(blockchain *BlockChain, statedb *state.StateDB, transaction *types.Transaction, validationGasLimit uint64, expectedErr error, t *testing.T) {
var (
snapshotRevisionId = statedb.Snapshot()
context = NewEVMContext(types.AAEntryMessage, blockchain.CurrentHeader(), blockchain, &common.Address{})
vmenv = vm.NewEVM(context, statedb, blockchain.Config(), vm.Config{PaygasMode: vm.PaygasHalt})
err = Validate(transaction, types.HomesteadSigner{}, vmenv, validationGasLimit)
)
if err != expectedErr {
t.Error("\n\texpected:", expectedErr, "\n\tgot:", err)
}
statedb.RevertToSnapshot(snapshotRevisionId)
}

func TestTransactionValidation(t *testing.T) {
var (
blockchain = setupBlockchain(10000000)
statedb, _ = blockchain.State()

key, _ = crypto.GenerateKey()
contractCreator = crypto.PubkeyToAddress(key.PublicKey)
contractAddress = crypto.CreateAddress(contractCreator, 0)
tx = &types.Transaction{}
)
statedb.SetBalance(contractAddress, big.NewInt(100000))
statedb.SetCode(contractAddress, common.FromHex(contractCode))

// test: invalid, no PAYGAS
tx = aaTransaction(contractAddress, 100000, 1, false, big.NewInt(1))
testValidate(blockchain, statedb, tx, 400000, ErrNoPaygas, t)

// test: invalid, insufficient funds
tx = aaTransaction(contractAddress, 100000, 1, true, big.NewInt(2))
testValidate(blockchain, statedb, tx, 400000, vm.ErrPaygasInsufficientFunds, t)

// test: invalid, gasLimit too low for intrinsic gas cost
tx = aaTransaction(contractAddress, 1, 1, true, big.NewInt(1))
testValidate(blockchain, statedb, tx, 400000, ErrIntrinsicGas, t)

// test: invalid, gasLimit too low for loops
tx = aaTransaction(contractAddress, 100000, 100000, true, big.NewInt(1))
testValidate(blockchain, statedb, tx, 400000, vm.ErrOutOfGas, t)

// test: valid, gasLimit < validationGasLimit
tx = aaTransaction(contractAddress, 100000, 1, true, big.NewInt(1))
testValidate(blockchain, statedb, tx, 400000, nil, t)

// test: valid, validationGasLimit < gasLimit
tx = aaTransaction(contractAddress, 100000, 1, true, big.NewInt(1))
testValidate(blockchain, statedb, tx, 50000, nil, t)

// test: invalid, validationGasLimit too low for intrinsic gas cost
tx = aaTransaction(contractAddress, 100000, 1, true, big.NewInt(1))
testValidate(blockchain, statedb, tx, 1, ErrIntrinsicGas, t)

// test: invalid, validationGasLimit too low for loops
tx = aaTransaction(contractAddress, 100000, 100000, true, big.NewInt(1))
testValidate(blockchain, statedb, tx, 50000, vm.ErrOutOfGas, t)

statedb.SetBalance(contractAddress, big.NewInt(0))

// test: invalid, insufficient funds
tx = aaTransaction(contractAddress, 100000, 1, true, big.NewInt(1))
testValidate(blockchain, statedb, tx, 400000, vm.ErrPaygasInsufficientFunds, t)

// test: valid, gasPrice 0
tx = aaTransaction(contractAddress, 100000, 1, true, big.NewInt(0))
testValidate(blockchain, statedb, tx, 400000, nil, t)
}

func TestInvalidEVMConfig(t *testing.T) {
var (
blockchain = setupBlockchain(10000000)
statedb, _ = blockchain.State()

context = NewEVMContext(types.AAEntryMessage, blockchain.CurrentHeader(), blockchain, &common.Address{})
vmenv = vm.NewEVM(context, statedb, blockchain.Config(), vm.Config{})

tx = &types.Transaction{}
err = Validate(tx, types.HomesteadSigner{}, vmenv, 400000)
expectedErr = ErrIncorrectAAConfig
)
if err != expectedErr {
t.Error("\n\texpected:", expectedErr, "\n\tgot:", err)
}
}

func TestMalformedTransaction(t *testing.T) {
var (
blockchain = setupBlockchain(10000000)
statedb, _ = blockchain.State()

context = NewEVMContext(types.AAEntryMessage, blockchain.CurrentHeader(), blockchain, &common.Address{})
vmenv = vm.NewEVM(context, statedb, blockchain.Config(), vm.Config{PaygasMode: vm.PaygasHalt})

key, _ = crypto.GenerateKey()
tx = pricedTransaction(0, 100000, big.NewInt(0), key)
err = Validate(tx, types.HomesteadSigner{}, vmenv, 400000)
expectedErr = ErrMalformedAATransaction
)
if err != expectedErr {
t.Error("\n\texpected:", expectedErr, "\n\tgot:", err)
}
}
6 changes: 6 additions & 0 deletions core/error.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,4 +63,10 @@ var (
// ErrIntrinsicGas is returned if the transaction is specified to use less gas
// than required to start the invocation.
ErrIntrinsicGas = errors.New("intrinsic gas too low")

ErrInvalidAATransaction = errors.New("invalid account abstraction transaction")

ErrInvalidAAPrefix = errors.New("invalid account abstraction prefix")

ErrNoPaygas = errors.New("account abstraction transaction did not call PAYGAS")
)
62 changes: 55 additions & 7 deletions core/state_transition.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@ import (
"github.com/ethereum/go-ethereum/params"
)

var aaPrefix = [...]byte{
0x33, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0x14, 0x60, 0x24, 0x57, 0x36, 0x60, 0x1f, 0x57, 0x00, 0x5b, 0x60, 0x00, 0x80, 0xfd, 0x5b,
}

/*
The State Transitioning Model

Expand Down Expand Up @@ -66,6 +71,9 @@ type Message interface {
Nonce() uint64
CheckNonce() bool
Data() []byte

IsAA() bool
Sponsor() common.Address
}

// ExecutionResult includes all output after executing given evm
Expand Down Expand Up @@ -173,17 +181,23 @@ func (st *StateTransition) to() common.Address {
}

func (st *StateTransition) buyGas() error {
mgval := new(big.Int).Mul(new(big.Int).SetUint64(st.msg.Gas()), st.gasPrice)
if st.state.GetBalance(st.msg.From()).Cmp(mgval) < 0 {
return ErrInsufficientFunds
var mgval *big.Int
if !st.msg.IsAA() {
mgval = new(big.Int).Mul(new(big.Int).SetUint64(st.msg.Gas()), st.gasPrice)
if st.state.GetBalance(st.msg.Sponsor()).Cmp(mgval) < 0 {
return ErrInsufficientFunds
}
}
if err := st.gp.SubGas(st.msg.Gas()); err != nil {
return err
}
st.gas += st.msg.Gas()

st.initialGas = st.msg.Gas()
st.state.SubBalance(st.msg.From(), mgval)
if !st.msg.IsAA() {
st.state.SubBalance(st.msg.Sponsor(), mgval)
}

return nil
}

Expand Down Expand Up @@ -224,6 +238,28 @@ func (st *StateTransition) TransitionDb() (*ExecutionResult, error) {
// 5. there is no overflow when calculating intrinsic gas
// 6. caller has enough balance to cover asset transfer for **topmost** call

if st.msg.IsAA() {
if st.msg.Nonce() != 0 || st.msg.GasPrice().Sign() != 0 || st.msg.Value().Sign() != 0 {
return nil, ErrInvalidAATransaction
}

code := st.evm.StateDB.GetCode(st.to())
if code == nil || len(code) < len(aaPrefix) {
return nil, ErrInvalidAAPrefix
}
for i := range aaPrefix {
if code[i] != aaPrefix[i] {
return nil, ErrInvalidAAPrefix
}
}
if st.evm.PaygasMode() == vm.PaygasNoOp {
st.evm.SetPaygasMode(vm.PaygasContinue)
}
if st.evm.PaygasLimit() == 0 {
st.evm.SetPaygasLimit(st.msg.Gas())
}
}

// Check clauses 1-3, buy gas if everything is correct
if err := st.preCheck(); err != nil {
return nil, err
Expand Down Expand Up @@ -255,9 +291,21 @@ func (st *StateTransition) TransitionDb() (*ExecutionResult, error) {
if contractCreation {
ret, _, st.gas, vmerr = st.evm.Create(sender, st.data, st.gas, st.value)
} else {
// Increment the nonce for the next transaction
st.state.SetNonce(msg.From(), st.state.GetNonce(sender.Address())+1)
if !msg.IsAA() {
// Increment the nonce for the next transaction
st.state.SetNonce(msg.From(), st.state.GetNonce(sender.Address())+1)
}
ret, st.gas, vmerr = st.evm.Call(sender, st.to(), st.data, st.gas, st.value)
if msg.IsAA() && st.evm.PaygasMode() != vm.PaygasNoOp {
if vmerr != nil {
return nil, vmerr
} else {
return nil, ErrNoPaygas
}
}
}
if st.msg.IsAA() {
st.gasPrice = st.evm.PaygasPrice()
}
st.refundGas()
st.state.AddBalance(st.evm.Coinbase, new(big.Int).Mul(new(big.Int).SetUint64(st.gasUsed()), st.gasPrice))
Expand All @@ -279,7 +327,7 @@ func (st *StateTransition) refundGas() {

// Return ETH for remaining gas, exchanged at the original rate.
remaining := new(big.Int).Mul(new(big.Int).SetUint64(st.gas), st.gasPrice)
st.state.AddBalance(st.msg.From(), remaining)
st.state.AddBalance(st.msg.Sponsor(), remaining)

// Also return remaining gas to the block gas counter so it is
// available for the next transaction.
Expand Down
53 changes: 53 additions & 0 deletions core/transaction_validator.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// Copyright 2017 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.

package core

import (
"errors"

"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
)

var (
ErrIncorrectAAConfig = errors.New("incorrect AA config for EVM")
ErrMalformedAATransaction = errors.New("AA transaction malformed")
)

func Validate(tx *types.Transaction, s types.Signer, evm *vm.EVM, gasLimit uint64) error {
if evm.PaygasMode() != vm.PaygasHalt {
return ErrIncorrectAAConfig
}
evm.SetPaygasLimit(tx.Gas())
if gasLimit > tx.Gas() {
gasLimit = tx.Gas()
}
msg, err := tx.AsMessage(s)
if err != nil {
return err
} else if !msg.IsAA() {
return ErrMalformedAATransaction
}
msg.SetGas(gasLimit)
gp := new(GasPool).AddGas(gasLimit)
_, err = ApplyMessage(evm, msg, gp)
if err != nil {
return err
}
tx.SetAAGasPrice(evm.PaygasPrice())
return nil
}
Loading