Skip to content

Commit 5383a2b

Browse files
s1narjl493456442holiman
authored andcommitted
internal/ethapi: eth_multicall (#27720)
This is a successor PR to #25743. This PR is based on a new iteration of the spec: ethereum/execution-apis#484. `eth_multicall` takes in a list of blocks, each optionally overriding fields like number, timestamp, etc. of a base block. Each block can include calls. At each block users can override the state. There are extra features, such as: - Include ether transfers as part of the logs - Overriding precompile codes with evm bytecode - Redirecting accounts to another address ## Breaking changes This PR includes the following breaking changes: - Block override fields of eth_call and debug_traceCall have had the following fields renamed - `coinbase` -> `feeRecipient` - `random` -> `prevRandao` - `baseFee` -> `baseFeePerGas` --------- Co-authored-by: Gary Rong <[email protected]> Co-authored-by: Martin Holst Swende <[email protected]> # Conflicts: # core/state_processor.go # core/vm/contracts.go # core/vm/evm.go # ethclient/ethclient_test.go # internal/ethapi/api.go # internal/ethapi/api_test.go
1 parent 304396a commit 5383a2b

18 files changed

+2507
-212
lines changed

core/state_processor.go

+8-3
Original file line numberDiff line numberDiff line change
@@ -186,9 +186,14 @@ func ApplyTransactionWithEVM(msg *Message, config *params.ChainConfig, gp *GasPo
186186
}
187187
*usedGas += result.UsedGas
188188

189+
return MakeReceipt(evm, result, statedb, blockNumber, blockHash, tx, *usedGas, root, receiptProcessors...), nil
190+
}
191+
192+
// MakeReceipt generates the receipt object for a transaction given its execution result.
193+
func MakeReceipt(evm *vm.EVM, result *ExecutionResult, statedb *state.StateDB, blockNumber *big.Int, blockHash common.Hash, tx *types.Transaction, usedGas uint64, root []byte, receiptProcessors ...ReceiptProcessor) *types.Receipt {
189194
// Create a new receipt for the transaction, storing the intermediate root and gas used
190195
// by the tx.
191-
receipt = &types.Receipt{Type: tx.Type(), PostState: root, CumulativeGasUsed: *usedGas}
196+
receipt := &types.Receipt{Type: tx.Type(), PostState: root, CumulativeGasUsed: usedGas}
192197
if result.Failed() {
193198
receipt.Status = types.ReceiptStatusFailed
194199
} else {
@@ -203,7 +208,7 @@ func ApplyTransactionWithEVM(msg *Message, config *params.ChainConfig, gp *GasPo
203208
}
204209

205210
// If the transaction created a contract, store the creation address in the receipt.
206-
if msg.To == nil {
211+
if tx.To() == nil {
207212
receipt.ContractAddress = crypto.CreateAddress(evm.TxContext.Origin, tx.Nonce())
208213
}
209214

@@ -215,7 +220,7 @@ func ApplyTransactionWithEVM(msg *Message, config *params.ChainConfig, gp *GasPo
215220
for _, receiptProcessor := range receiptProcessors {
216221
receiptProcessor.Apply(receipt)
217222
}
218-
return receipt, err
223+
return receipt
219224
}
220225

221226
// ApplyTransaction attempts to apply a transaction to the given state database

core/state_transition.go

+22-16
Original file line numberDiff line numberDiff line change
@@ -143,27 +143,31 @@ type Message struct {
143143
BlobGasFeeCap *big.Int
144144
BlobHashes []common.Hash
145145

146-
// When SkipAccountChecks is true, the message nonce is not checked against the
147-
// account nonce in state. It also disables checking that the sender is an EOA.
146+
// When SkipNonceChecks is true, the message nonce is not checked against the
147+
// account nonce in state.
148148
// This field will be set to true for operations like RPC eth_call.
149-
SkipAccountChecks bool
149+
SkipNonceChecks bool
150+
151+
// When SkipFromEOACheck is true, the message sender is not checked to be an EOA.
152+
SkipFromEOACheck bool
150153
}
151154

152155
// TransactionToMessage converts a transaction into a Message.
153156
func TransactionToMessage(tx *types.Transaction, s types.Signer, baseFee *big.Int) (*Message, error) {
154157
msg := &Message{
155-
Nonce: tx.Nonce(),
156-
GasLimit: tx.Gas(),
157-
GasPrice: new(big.Int).Set(tx.GasPrice()),
158-
GasFeeCap: new(big.Int).Set(tx.GasFeeCap()),
159-
GasTipCap: new(big.Int).Set(tx.GasTipCap()),
160-
To: tx.To(),
161-
Value: tx.Value(),
162-
Data: tx.Data(),
163-
AccessList: tx.AccessList(),
164-
SkipAccountChecks: false,
165-
BlobHashes: tx.BlobHashes(),
166-
BlobGasFeeCap: tx.BlobGasFeeCap(),
158+
Nonce: tx.Nonce(),
159+
GasLimit: tx.Gas(),
160+
GasPrice: new(big.Int).Set(tx.GasPrice()),
161+
GasFeeCap: new(big.Int).Set(tx.GasFeeCap()),
162+
GasTipCap: new(big.Int).Set(tx.GasTipCap()),
163+
To: tx.To(),
164+
Value: tx.Value(),
165+
Data: tx.Data(),
166+
AccessList: tx.AccessList(),
167+
SkipNonceChecks: false,
168+
SkipFromEOACheck: false,
169+
BlobHashes: tx.BlobHashes(),
170+
BlobGasFeeCap: tx.BlobGasFeeCap(),
167171
}
168172
// If baseFee provided, set gasPrice to effectiveGasPrice.
169173
if baseFee != nil {
@@ -280,7 +284,7 @@ func (st *StateTransition) buyGas() error {
280284
func (st *StateTransition) preCheck() error {
281285
// Only check transactions that are not fake
282286
msg := st.msg
283-
if !msg.SkipAccountChecks {
287+
if !msg.SkipNonceChecks {
284288
// Make sure this transaction's nonce is correct.
285289
stNonce := st.state.GetNonce(msg.From)
286290
if msgNonce := msg.Nonce; stNonce < msgNonce {
@@ -293,6 +297,8 @@ func (st *StateTransition) preCheck() error {
293297
return fmt.Errorf("%w: address %v, nonce: %d", ErrNonceMax,
294298
msg.From.Hex(), stNonce)
295299
}
300+
}
301+
if !msg.SkipFromEOACheck {
296302
// Make sure the sender is an EOA
297303
codeHash := st.state.GetCodeHash(msg.From)
298304
if codeHash != (common.Hash{}) && codeHash != types.EmptyCodeHash {

core/vm/contracts.go

+108-65
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222
"encoding/binary"
2323
"errors"
2424
"fmt"
25+
"maps"
2526
"math/big"
2627

2728
"github.com/prysmaticlabs/prysm/v5/crypto/bls"
@@ -51,105 +52,123 @@ type PrecompiledContract interface {
5152
Run(input []byte) ([]byte, error) // Run runs the precompiled contract
5253
}
5354

55+
// PrecompiledContracts contains the precompiled contracts supported at the given fork.
56+
type PrecompiledContracts map[common.Address]PrecompiledContract
57+
5458
// PrecompiledContractsHomestead contains the default set of pre-compiled Ethereum
5559
// contracts used in the Frontier and Homestead releases.
56-
var PrecompiledContractsHomestead = map[common.Address]PrecompiledContract{
57-
common.BytesToAddress([]byte{1}): &ecrecover{},
58-
common.BytesToAddress([]byte{2}): &sha256hash{},
59-
common.BytesToAddress([]byte{3}): &ripemd160hash{},
60-
common.BytesToAddress([]byte{4}): &dataCopy{},
60+
var PrecompiledContractsHomestead = PrecompiledContracts{
61+
common.BytesToAddress([]byte{0x1}): &ecrecover{},
62+
common.BytesToAddress([]byte{0x2}): &sha256hash{},
63+
common.BytesToAddress([]byte{0x3}): &ripemd160hash{},
64+
common.BytesToAddress([]byte{0x4}): &dataCopy{},
6165
}
6266

6367
// PrecompiledContractsByzantium contains the default set of pre-compiled Ethereum
6468
// contracts used in the Byzantium release.
65-
var PrecompiledContractsByzantium = map[common.Address]PrecompiledContract{
66-
common.BytesToAddress([]byte{1}): &ecrecover{},
67-
common.BytesToAddress([]byte{2}): &sha256hash{},
68-
common.BytesToAddress([]byte{3}): &ripemd160hash{},
69-
common.BytesToAddress([]byte{4}): &dataCopy{},
70-
common.BytesToAddress([]byte{5}): &bigModExp{eip2565: false},
71-
common.BytesToAddress([]byte{6}): &bn256AddByzantium{},
72-
common.BytesToAddress([]byte{7}): &bn256ScalarMulByzantium{},
73-
common.BytesToAddress([]byte{8}): &bn256PairingByzantium{},
69+
var PrecompiledContractsByzantium = PrecompiledContracts{
70+
common.BytesToAddress([]byte{0x1}): &ecrecover{},
71+
common.BytesToAddress([]byte{0x2}): &sha256hash{},
72+
common.BytesToAddress([]byte{0x3}): &ripemd160hash{},
73+
common.BytesToAddress([]byte{0x4}): &dataCopy{},
74+
common.BytesToAddress([]byte{0x5}): &bigModExp{eip2565: false},
75+
common.BytesToAddress([]byte{0x6}): &bn256AddByzantium{},
76+
common.BytesToAddress([]byte{0x7}): &bn256ScalarMulByzantium{},
77+
common.BytesToAddress([]byte{0x8}): &bn256PairingByzantium{},
7478
}
7579

7680
// PrecompiledContractsIstanbul contains the default set of pre-compiled Ethereum
7781
// contracts used in the Istanbul release.
7882
var PrecompiledContractsIstanbul = map[common.Address]PrecompiledContract{
79-
common.BytesToAddress([]byte{1}): &ecrecover{},
80-
common.BytesToAddress([]byte{2}): &sha256hash{},
81-
common.BytesToAddress([]byte{3}): &ripemd160hash{},
82-
common.BytesToAddress([]byte{4}): &dataCopy{},
83-
common.BytesToAddress([]byte{5}): &bigModExp{},
84-
common.BytesToAddress([]byte{6}): &bn256AddIstanbul{},
85-
common.BytesToAddress([]byte{7}): &bn256ScalarMulIstanbul{},
86-
common.BytesToAddress([]byte{8}): &bn256PairingIstanbul{},
87-
common.BytesToAddress([]byte{9}): &blake2F{},
83+
common.BytesToAddress([]byte{0x1}): &ecrecover{},
84+
common.BytesToAddress([]byte{0x2}): &sha256hash{},
85+
common.BytesToAddress([]byte{0x3}): &ripemd160hash{},
86+
common.BytesToAddress([]byte{0x4}): &dataCopy{},
87+
common.BytesToAddress([]byte{0x5}): &bigModExp{eip2565: false},
88+
common.BytesToAddress([]byte{0x6}): &bn256AddIstanbul{},
89+
common.BytesToAddress([]byte{0x7}): &bn256ScalarMulIstanbul{},
90+
common.BytesToAddress([]byte{0x8}): &bn256PairingIstanbul{},
91+
common.BytesToAddress([]byte{0x9}): &blake2F{},
8892

89-
common.BytesToAddress([]byte{100}): &btcValidate{},
93+
common.BytesToAddress([]byte{0x64}): &btcValidate{},
9094
}
9195

9296
// PrecompiledContractsIstanbul contains the default set of pre-compiled Ethereum
9397
// contracts used in the HashPower release.
9498
var PrecompiledContractsHashPower = map[common.Address]PrecompiledContract{
95-
common.BytesToAddress([]byte{1}): &ecrecover{},
96-
common.BytesToAddress([]byte{2}): &sha256hash{},
97-
common.BytesToAddress([]byte{3}): &ripemd160hash{},
98-
common.BytesToAddress([]byte{4}): &dataCopy{},
99-
common.BytesToAddress([]byte{5}): &bigModExp{},
100-
common.BytesToAddress([]byte{6}): &bn256AddIstanbul{},
101-
common.BytesToAddress([]byte{7}): &bn256ScalarMulIstanbul{},
102-
common.BytesToAddress([]byte{8}): &bn256PairingIstanbul{},
103-
common.BytesToAddress([]byte{9}): &blake2F{},
99+
common.BytesToAddress([]byte{0x1}): &ecrecover{},
100+
common.BytesToAddress([]byte{0x2}): &sha256hash{},
101+
common.BytesToAddress([]byte{0x3}): &ripemd160hash{},
102+
common.BytesToAddress([]byte{0x4}): &dataCopy{},
103+
common.BytesToAddress([]byte{0x5}): &bigModExp{eip2565: false},
104+
common.BytesToAddress([]byte{0x6}): &bn256AddIstanbul{},
105+
common.BytesToAddress([]byte{0x7}): &bn256ScalarMulIstanbul{},
106+
common.BytesToAddress([]byte{0x8}): &bn256PairingIstanbul{},
107+
common.BytesToAddress([]byte{0x9}): &blake2F{},
104108

105-
common.BytesToAddress([]byte{100}): &btcValidateV2{},
109+
common.BytesToAddress([]byte{0x64}): &btcValidateV2{},
106110
}
107111

108112
// PrecompiledContractsBerlin contains the default set of pre-compiled Ethereum
109113
// contracts used in the Berlin release.
110114
var PrecompiledContractsBerlin = map[common.Address]PrecompiledContract{
111-
common.BytesToAddress([]byte{1}): &ecrecover{},
112-
common.BytesToAddress([]byte{2}): &sha256hash{},
113-
common.BytesToAddress([]byte{3}): &ripemd160hash{},
114-
common.BytesToAddress([]byte{4}): &dataCopy{},
115-
common.BytesToAddress([]byte{5}): &bigModExp{eip2565: true},
116-
common.BytesToAddress([]byte{6}): &bn256AddIstanbul{},
117-
common.BytesToAddress([]byte{7}): &bn256ScalarMulIstanbul{},
118-
common.BytesToAddress([]byte{8}): &bn256PairingIstanbul{},
119-
common.BytesToAddress([]byte{9}): &blake2F{},
115+
common.BytesToAddress([]byte{0x1}): &ecrecover{},
116+
common.BytesToAddress([]byte{0x2}): &sha256hash{},
117+
common.BytesToAddress([]byte{0x3}): &ripemd160hash{},
118+
common.BytesToAddress([]byte{0x4}): &dataCopy{},
119+
common.BytesToAddress([]byte{0x5}): &bigModExp{eip2565: false},
120+
common.BytesToAddress([]byte{0x6}): &bn256AddIstanbul{},
121+
common.BytesToAddress([]byte{0x7}): &bn256ScalarMulIstanbul{},
122+
common.BytesToAddress([]byte{0x8}): &bn256PairingIstanbul{},
123+
common.BytesToAddress([]byte{0x9}): &blake2F{},
120124

121-
common.BytesToAddress([]byte{100}): &btcValidateV2{},
125+
common.BytesToAddress([]byte{0x64}): &btcValidateV2{},
122126
}
123127

124128
// PrecompiledContractsCancun contains the default set of pre-compiled Ethereum
125129
// contracts used in the Cancun release.
126-
var PrecompiledContractsCancun = map[common.Address]PrecompiledContract{
127-
common.BytesToAddress([]byte{1}): &ecrecover{},
128-
common.BytesToAddress([]byte{2}): &sha256hash{},
129-
common.BytesToAddress([]byte{3}): &ripemd160hash{},
130-
common.BytesToAddress([]byte{4}): &dataCopy{},
131-
common.BytesToAddress([]byte{5}): &bigModExp{eip2565: true},
132-
common.BytesToAddress([]byte{6}): &bn256AddIstanbul{},
133-
common.BytesToAddress([]byte{7}): &bn256ScalarMulIstanbul{},
134-
common.BytesToAddress([]byte{8}): &bn256PairingIstanbul{},
135-
common.BytesToAddress([]byte{9}): &blake2F{},
130+
var PrecompiledContractsCancun = PrecompiledContracts{
131+
common.BytesToAddress([]byte{0x1}): &ecrecover{},
132+
common.BytesToAddress([]byte{0x2}): &sha256hash{},
133+
common.BytesToAddress([]byte{0x3}): &ripemd160hash{},
134+
common.BytesToAddress([]byte{0x4}): &dataCopy{},
135+
common.BytesToAddress([]byte{0x5}): &bigModExp{eip2565: true},
136+
common.BytesToAddress([]byte{0x6}): &bn256AddIstanbul{},
137+
common.BytesToAddress([]byte{0x7}): &bn256ScalarMulIstanbul{},
138+
common.BytesToAddress([]byte{0x8}): &bn256PairingIstanbul{},
139+
common.BytesToAddress([]byte{0x9}): &blake2F{},
140+
common.BytesToAddress([]byte{0xa}): &kzgPointEvaluation{},
141+
}
142+
143+
// PrecompiledContractsPrague contains the set of pre-compiled Ethereum
144+
// contracts used in the Prague release.
145+
var PrecompiledContractsPrague = PrecompiledContracts{
146+
common.BytesToAddress([]byte{0x01}): &ecrecover{},
147+
common.BytesToAddress([]byte{0x02}): &sha256hash{},
148+
common.BytesToAddress([]byte{0x03}): &ripemd160hash{},
149+
common.BytesToAddress([]byte{0x04}): &dataCopy{},
150+
common.BytesToAddress([]byte{0x05}): &bigModExp{eip2565: true},
151+
common.BytesToAddress([]byte{0x06}): &bn256AddIstanbul{},
152+
common.BytesToAddress([]byte{0x07}): &bn256ScalarMulIstanbul{},
153+
common.BytesToAddress([]byte{0x08}): &bn256PairingIstanbul{},
154+
common.BytesToAddress([]byte{0x09}): &blake2F{},
136155
common.BytesToAddress([]byte{0x0a}): &kzgPointEvaluation{},
137156

138-
common.BytesToAddress([]byte{100}): &btcValidateV2{},
157+
common.BytesToAddress([]byte{0x64}): &btcValidateV2{},
139158
}
140159

141160
// PrecompiledContractsBLS contains the set of pre-compiled Ethereum
142161
// contracts specified in EIP-2537. These are exported for testing purposes.
143162
var PrecompiledContractsBLS = map[common.Address]PrecompiledContract{
144-
common.BytesToAddress([]byte{10}): &bls12381G1Add{},
145-
common.BytesToAddress([]byte{11}): &bls12381G1Mul{},
146-
common.BytesToAddress([]byte{12}): &bls12381G1MultiExp{},
147-
common.BytesToAddress([]byte{13}): &bls12381G2Add{},
148-
common.BytesToAddress([]byte{14}): &bls12381G2Mul{},
149-
common.BytesToAddress([]byte{15}): &bls12381G2MultiExp{},
150-
common.BytesToAddress([]byte{16}): &bls12381Pairing{},
151-
common.BytesToAddress([]byte{17}): &bls12381MapG1{},
152-
common.BytesToAddress([]byte{18}): &bls12381MapG2{},
163+
common.BytesToAddress([]byte{0xa}): &bls12381G1Add{},
164+
common.BytesToAddress([]byte{0xb}): &bls12381G1Mul{},
165+
common.BytesToAddress([]byte{0xc}): &bls12381G1MultiExp{},
166+
common.BytesToAddress([]byte{0xd}): &bls12381G2Add{},
167+
common.BytesToAddress([]byte{0xe}): &bls12381G2Mul{},
168+
common.BytesToAddress([]byte{0xf}): &bls12381G2MultiExp{},
169+
common.BytesToAddress([]byte{0x10}): &bls12381Pairing{},
170+
common.BytesToAddress([]byte{0x11}): &bls12381MapG1{},
171+
common.BytesToAddress([]byte{0x12}): &bls12381MapG2{},
153172
}
154173

155174
var (
@@ -182,7 +201,31 @@ func init() {
182201
}
183202
}
184203

185-
// ActivePrecompiles returns the precompiles enabled with the current configuration.
204+
func activePrecompiledContracts(rules params.Rules) PrecompiledContracts {
205+
switch {
206+
// case rules.IsVerkle:
207+
// return PrecompiledContractsVerkle
208+
case rules.IsPrague:
209+
return PrecompiledContractsPrague
210+
case rules.IsCancun:
211+
return PrecompiledContractsCancun
212+
case rules.IsBerlin:
213+
return PrecompiledContractsBerlin
214+
case rules.IsIstanbul:
215+
return PrecompiledContractsIstanbul
216+
case rules.IsByzantium:
217+
return PrecompiledContractsByzantium
218+
default:
219+
return PrecompiledContractsHomestead
220+
}
221+
}
222+
223+
// ActivePrecompiledContracts returns a copy of precompiled contracts enabled with the current configuration.
224+
func ActivePrecompiledContracts(rules params.Rules) PrecompiledContracts {
225+
return maps.Clone(activePrecompiledContracts(rules))
226+
}
227+
228+
// ActivePrecompiles returns the precompile addresses enabled with the current configuration.
186229
func ActivePrecompiles(rules params.Rules) []common.Address {
187230
switch {
188231
case rules.IsCancun:

0 commit comments

Comments
 (0)