mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-20 10:52:25 +00:00
wip, l1call/l1delegatecall
This commit is contained in:
parent
e0d981f6f3
commit
1e74d11f5d
11 changed files with 249 additions and 38 deletions
|
|
@ -162,6 +162,7 @@ func makeConfigNode(ctx *cli.Context) (*node.Node, gethConfig) {
|
|||
if ctx.IsSet(utils.EthStatsURLFlag.Name) {
|
||||
cfg.Ethstats.URL = ctx.String(utils.EthStatsURLFlag.Name)
|
||||
}
|
||||
|
||||
applyMetricConfig(ctx, &cfg)
|
||||
|
||||
return stack, cfg
|
||||
|
|
@ -183,6 +184,9 @@ func makeFullNode(ctx *cli.Context) (*node.Node, ethapi.Backend) {
|
|||
// CHANGE(TAIKO): register Taiko RPC APIs.
|
||||
utils.RegisterTaikoAPIs(stack, &cfg.Eth, eth)
|
||||
|
||||
// CHANGE(TAIKO): register L1 node
|
||||
registerL1Node(ctx, &cfg)
|
||||
|
||||
// Create gauge with geth system and build information
|
||||
if eth != nil { // The 'eth' backend may be nil in light mode
|
||||
var protos []string
|
||||
|
|
@ -378,3 +382,11 @@ func setAccountManagerBackends(conf *node.Config, am *accounts.Manager, keydir s
|
|||
|
||||
return nil
|
||||
}
|
||||
|
||||
// CHANGE(TAIKO)
|
||||
func registerL1Node(ctx *cli.Context, cfg *gethConfig) {
|
||||
if ctx.IsSet(utils.L1RPCUrlFlag.Name) {
|
||||
v := ctx.String(utils.L1RPCUrlFlag.Name)
|
||||
cfg.Eth.L1RPCUrl = v
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -194,6 +194,11 @@ var (
|
|||
utils.MetricsInfluxDBBucketFlag,
|
||||
utils.MetricsInfluxDBOrganizationFlag,
|
||||
}
|
||||
|
||||
taikoFlags = []cli.Flag{
|
||||
utils.TaikoFlag,
|
||||
utils.L1RPCUrlFlag,
|
||||
}
|
||||
)
|
||||
|
||||
var app = flags.NewApp("the go-ethereum command line interface")
|
||||
|
|
@ -244,7 +249,7 @@ func init() {
|
|||
metricsFlags,
|
||||
)
|
||||
// CHANGE(taiko): append Taiko flags into the original GETH flags
|
||||
app.Flags = append(app.Flags, &utils.TaikoFlag)
|
||||
app.Flags = append(app.Flags, taikoFlags...)
|
||||
|
||||
flags.AutoEnvVars(app.Flags, "GETH")
|
||||
|
||||
|
|
|
|||
|
|
@ -1792,9 +1792,13 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
|
|||
}
|
||||
// Override any default configs for hard coded networks.
|
||||
switch {
|
||||
// CHANGE(taiko): when --taiko flag is set, use the Taiko genesis.
|
||||
// CHANGE(taiko): when --taiko flag is set, use the Taiko genesis, and set L1
|
||||
// rpc url.
|
||||
case ctx.IsSet(TaikoFlag.Name):
|
||||
cfg.Genesis = core.TaikoGenesisBlock(cfg.NetworkId)
|
||||
if ctx.IsSet(L1RPCUrlFlag.Name) {
|
||||
cfg.L1RPCUrl = ctx.String(L1RPCUrlFlag.Name)
|
||||
}
|
||||
case ctx.Bool(MainnetFlag.Name):
|
||||
if !ctx.IsSet(NetworkIdFlag.Name) {
|
||||
cfg.NetworkId = 1
|
||||
|
|
|
|||
|
|
@ -12,10 +12,15 @@ import (
|
|||
)
|
||||
|
||||
var (
|
||||
TaikoFlag = cli.BoolFlag{
|
||||
TaikoFlag = &cli.BoolFlag{
|
||||
Name: "taiko",
|
||||
Usage: "Taiko network",
|
||||
}
|
||||
L1RPCUrlFlag = &cli.StringFlag{
|
||||
Name: "l1RpcUrl",
|
||||
Usage: "Rpc url of an L1 node (must be archive)",
|
||||
Required: true,
|
||||
}
|
||||
)
|
||||
|
||||
// RegisterTaikoAPIs initializes and registers the Taiko RPC APIs.
|
||||
|
|
|
|||
|
|
@ -38,8 +38,18 @@ import (
|
|||
// requires a deterministic gas count based on the input size of the Run method of the
|
||||
// contract.
|
||||
type PrecompiledContract interface {
|
||||
RequiredGas(input []byte) uint64 // RequiredPrice calculates the contract gas use
|
||||
Run(input []byte) ([]byte, error) // Run runs the precompiled contract
|
||||
RequiredGas(input []byte) uint64 // RequiredPrice calculates the contract gas use
|
||||
Run(opt *TaikoRunOpts, input []byte) ([]byte, error) // Run runs the precompiled contract
|
||||
}
|
||||
|
||||
// CHANGE(TAIKO): TaikoL1RunOpts is an opt added to the PrecompiledContract Run method
|
||||
// to allow the taiko-specific precompiles to have access to additional necessary
|
||||
// params.
|
||||
type TaikoRunOpts struct {
|
||||
L1RPCUrl string
|
||||
StateDB StateDB
|
||||
Interpreter *EVMInterpreter
|
||||
Caller ContractRef
|
||||
}
|
||||
|
||||
// PrecompiledContractsHomestead contains the default set of pre-compiled Ethereum
|
||||
|
|
@ -105,6 +115,9 @@ var PrecompiledContractsCancun = map[common.Address]PrecompiledContract{
|
|||
common.BytesToAddress([]byte{8}): &bn256PairingIstanbul{},
|
||||
common.BytesToAddress([]byte{9}): &blake2F{},
|
||||
common.BytesToAddress([]byte{0x0a}): &kzgPointEvaluation{},
|
||||
// CHANGE(taik): l1call and l1delegatecall precompiles
|
||||
common.BytesToAddress([]byte{41}): &l1Call{},
|
||||
common.BytesToAddress([]byte{42}): &l1DelegateCall{},
|
||||
}
|
||||
|
||||
// PrecompiledContractsBLS contains the set of pre-compiled Ethereum
|
||||
|
|
@ -168,13 +181,13 @@ func ActivePrecompiles(rules params.Rules) []common.Address {
|
|||
// - the returned bytes,
|
||||
// - the _remaining_ gas,
|
||||
// - any error that occurred
|
||||
func RunPrecompiledContract(p PrecompiledContract, input []byte, suppliedGas uint64) (ret []byte, remainingGas uint64, err error) {
|
||||
func RunPrecompiledContract(p PrecompiledContract, input []byte, suppliedGas uint64, opts *TaikoRunOpts) (ret []byte, remainingGas uint64, err error) {
|
||||
gasCost := p.RequiredGas(input)
|
||||
if suppliedGas < gasCost {
|
||||
return nil, 0, ErrOutOfGas
|
||||
}
|
||||
suppliedGas -= gasCost
|
||||
output, err := p.Run(input)
|
||||
output, err := p.Run(opts, input)
|
||||
return output, suppliedGas, err
|
||||
}
|
||||
|
||||
|
|
@ -185,7 +198,7 @@ func (c *ecrecover) RequiredGas(input []byte) uint64 {
|
|||
return params.EcrecoverGas
|
||||
}
|
||||
|
||||
func (c *ecrecover) Run(input []byte) ([]byte, error) {
|
||||
func (c *ecrecover) Run(opts *TaikoRunOpts, input []byte) ([]byte, error) {
|
||||
const ecRecoverInputLength = 128
|
||||
|
||||
input = common.RightPadBytes(input, ecRecoverInputLength)
|
||||
|
|
@ -226,7 +239,7 @@ type sha256hash struct{}
|
|||
func (c *sha256hash) RequiredGas(input []byte) uint64 {
|
||||
return uint64(len(input)+31)/32*params.Sha256PerWordGas + params.Sha256BaseGas
|
||||
}
|
||||
func (c *sha256hash) Run(input []byte) ([]byte, error) {
|
||||
func (c *sha256hash) Run(opts *TaikoRunOpts, input []byte) ([]byte, error) {
|
||||
h := sha256.Sum256(input)
|
||||
return h[:], nil
|
||||
}
|
||||
|
|
@ -241,7 +254,7 @@ type ripemd160hash struct{}
|
|||
func (c *ripemd160hash) RequiredGas(input []byte) uint64 {
|
||||
return uint64(len(input)+31)/32*params.Ripemd160PerWordGas + params.Ripemd160BaseGas
|
||||
}
|
||||
func (c *ripemd160hash) Run(input []byte) ([]byte, error) {
|
||||
func (c *ripemd160hash) Run(opts *TaikoRunOpts, input []byte) ([]byte, error) {
|
||||
ripemd := ripemd160.New()
|
||||
ripemd.Write(input)
|
||||
return common.LeftPadBytes(ripemd.Sum(nil), 32), nil
|
||||
|
|
@ -257,7 +270,7 @@ type dataCopy struct{}
|
|||
func (c *dataCopy) RequiredGas(input []byte) uint64 {
|
||||
return uint64(len(input)+31)/32*params.IdentityPerWordGas + params.IdentityBaseGas
|
||||
}
|
||||
func (c *dataCopy) Run(in []byte) ([]byte, error) {
|
||||
func (c *dataCopy) Run(opts *TaikoRunOpts, in []byte) ([]byte, error) {
|
||||
return common.CopyBytes(in), nil
|
||||
}
|
||||
|
||||
|
|
@ -383,7 +396,7 @@ func (c *bigModExp) RequiredGas(input []byte) uint64 {
|
|||
return gas.Uint64()
|
||||
}
|
||||
|
||||
func (c *bigModExp) Run(input []byte) ([]byte, error) {
|
||||
func (c *bigModExp) Run(opts *TaikoRunOpts, input []byte) ([]byte, error) {
|
||||
var (
|
||||
baseLen = new(big.Int).SetBytes(getData(input, 0, 32)).Uint64()
|
||||
expLen = new(big.Int).SetBytes(getData(input, 32, 32)).Uint64()
|
||||
|
|
@ -463,7 +476,7 @@ func (c *bn256AddIstanbul) RequiredGas(input []byte) uint64 {
|
|||
return params.Bn256AddGasIstanbul
|
||||
}
|
||||
|
||||
func (c *bn256AddIstanbul) Run(input []byte) ([]byte, error) {
|
||||
func (c *bn256AddIstanbul) Run(opts *TaikoRunOpts, input []byte) ([]byte, error) {
|
||||
return runBn256Add(input)
|
||||
}
|
||||
|
||||
|
|
@ -476,7 +489,7 @@ func (c *bn256AddByzantium) RequiredGas(input []byte) uint64 {
|
|||
return params.Bn256AddGasByzantium
|
||||
}
|
||||
|
||||
func (c *bn256AddByzantium) Run(input []byte) ([]byte, error) {
|
||||
func (c *bn256AddByzantium) Run(opts *TaikoRunOpts, input []byte) ([]byte, error) {
|
||||
return runBn256Add(input)
|
||||
}
|
||||
|
||||
|
|
@ -501,7 +514,7 @@ func (c *bn256ScalarMulIstanbul) RequiredGas(input []byte) uint64 {
|
|||
return params.Bn256ScalarMulGasIstanbul
|
||||
}
|
||||
|
||||
func (c *bn256ScalarMulIstanbul) Run(input []byte) ([]byte, error) {
|
||||
func (c *bn256ScalarMulIstanbul) Run(opts *TaikoRunOpts, input []byte) ([]byte, error) {
|
||||
return runBn256ScalarMul(input)
|
||||
}
|
||||
|
||||
|
|
@ -514,7 +527,7 @@ func (c *bn256ScalarMulByzantium) RequiredGas(input []byte) uint64 {
|
|||
return params.Bn256ScalarMulGasByzantium
|
||||
}
|
||||
|
||||
func (c *bn256ScalarMulByzantium) Run(input []byte) ([]byte, error) {
|
||||
func (c *bn256ScalarMulByzantium) Run(opts *TaikoRunOpts, input []byte) ([]byte, error) {
|
||||
return runBn256ScalarMul(input)
|
||||
}
|
||||
|
||||
|
|
@ -569,7 +582,7 @@ func (c *bn256PairingIstanbul) RequiredGas(input []byte) uint64 {
|
|||
return params.Bn256PairingBaseGasIstanbul + uint64(len(input)/192)*params.Bn256PairingPerPointGasIstanbul
|
||||
}
|
||||
|
||||
func (c *bn256PairingIstanbul) Run(input []byte) ([]byte, error) {
|
||||
func (c *bn256PairingIstanbul) Run(opts *TaikoRunOpts, input []byte) ([]byte, error) {
|
||||
return runBn256Pairing(input)
|
||||
}
|
||||
|
||||
|
|
@ -582,7 +595,7 @@ func (c *bn256PairingByzantium) RequiredGas(input []byte) uint64 {
|
|||
return params.Bn256PairingBaseGasByzantium + uint64(len(input)/192)*params.Bn256PairingPerPointGasByzantium
|
||||
}
|
||||
|
||||
func (c *bn256PairingByzantium) Run(input []byte) ([]byte, error) {
|
||||
func (c *bn256PairingByzantium) Run(opts *TaikoRunOpts, input []byte) ([]byte, error) {
|
||||
return runBn256Pairing(input)
|
||||
}
|
||||
|
||||
|
|
@ -608,7 +621,7 @@ var (
|
|||
errBlake2FInvalidFinalFlag = errors.New("invalid final flag")
|
||||
)
|
||||
|
||||
func (c *blake2F) Run(input []byte) ([]byte, error) {
|
||||
func (c *blake2F) Run(opts *TaikoRunOpts, input []byte) ([]byte, error) {
|
||||
// Make sure the input is valid (correct length and final flag)
|
||||
if len(input) != blake2FInputLength {
|
||||
return nil, errBlake2FInvalidInputLength
|
||||
|
|
@ -662,7 +675,7 @@ func (c *bls12381G1Add) RequiredGas(input []byte) uint64 {
|
|||
return params.Bls12381G1AddGas
|
||||
}
|
||||
|
||||
func (c *bls12381G1Add) Run(input []byte) ([]byte, error) {
|
||||
func (c *bls12381G1Add) Run(opts *TaikoRunOpts, input []byte) ([]byte, error) {
|
||||
// Implements EIP-2537 G1Add precompile.
|
||||
// > G1 addition call expects `256` bytes as an input that is interpreted as byte concatenation of two G1 points (`128` bytes each).
|
||||
// > Output is an encoding of addition operation result - single G1 point (`128` bytes).
|
||||
|
|
@ -700,7 +713,7 @@ func (c *bls12381G1Mul) RequiredGas(input []byte) uint64 {
|
|||
return params.Bls12381G1MulGas
|
||||
}
|
||||
|
||||
func (c *bls12381G1Mul) Run(input []byte) ([]byte, error) {
|
||||
func (c *bls12381G1Mul) Run(opts *TaikoRunOpts, input []byte) ([]byte, error) {
|
||||
// Implements EIP-2537 G1Mul precompile.
|
||||
// > G1 multiplication call expects `160` bytes as an input that is interpreted as byte concatenation of encoding of G1 point (`128` bytes) and encoding of a scalar value (`32` bytes).
|
||||
// > Output is an encoding of multiplication operation result - single G1 point (`128` bytes).
|
||||
|
|
@ -750,7 +763,7 @@ func (c *bls12381G1MultiExp) RequiredGas(input []byte) uint64 {
|
|||
return (uint64(k) * params.Bls12381G1MulGas * discount) / 1000
|
||||
}
|
||||
|
||||
func (c *bls12381G1MultiExp) Run(input []byte) ([]byte, error) {
|
||||
func (c *bls12381G1MultiExp) Run(opts *TaikoRunOpts, input []byte) ([]byte, error) {
|
||||
// Implements EIP-2537 G1MultiExp precompile.
|
||||
// G1 multiplication call expects `160*k` bytes as an input that is interpreted as byte concatenation of `k` slices each of them being a byte concatenation of encoding of G1 point (`128` bytes) and encoding of a scalar value (`32` bytes).
|
||||
// Output is an encoding of multiexponentiation operation result - single G1 point (`128` bytes).
|
||||
|
|
@ -793,7 +806,7 @@ func (c *bls12381G2Add) RequiredGas(input []byte) uint64 {
|
|||
return params.Bls12381G2AddGas
|
||||
}
|
||||
|
||||
func (c *bls12381G2Add) Run(input []byte) ([]byte, error) {
|
||||
func (c *bls12381G2Add) Run(opts *TaikoRunOpts, input []byte) ([]byte, error) {
|
||||
// Implements EIP-2537 G2Add precompile.
|
||||
// > G2 addition call expects `512` bytes as an input that is interpreted as byte concatenation of two G2 points (`256` bytes each).
|
||||
// > Output is an encoding of addition operation result - single G2 point (`256` bytes).
|
||||
|
|
@ -831,7 +844,7 @@ func (c *bls12381G2Mul) RequiredGas(input []byte) uint64 {
|
|||
return params.Bls12381G2MulGas
|
||||
}
|
||||
|
||||
func (c *bls12381G2Mul) Run(input []byte) ([]byte, error) {
|
||||
func (c *bls12381G2Mul) Run(opts *TaikoRunOpts, input []byte) ([]byte, error) {
|
||||
// Implements EIP-2537 G2MUL precompile logic.
|
||||
// > G2 multiplication call expects `288` bytes as an input that is interpreted as byte concatenation of encoding of G2 point (`256` bytes) and encoding of a scalar value (`32` bytes).
|
||||
// > Output is an encoding of multiplication operation result - single G2 point (`256` bytes).
|
||||
|
|
@ -881,7 +894,7 @@ func (c *bls12381G2MultiExp) RequiredGas(input []byte) uint64 {
|
|||
return (uint64(k) * params.Bls12381G2MulGas * discount) / 1000
|
||||
}
|
||||
|
||||
func (c *bls12381G2MultiExp) Run(input []byte) ([]byte, error) {
|
||||
func (c *bls12381G2MultiExp) Run(opts *TaikoRunOpts, input []byte) ([]byte, error) {
|
||||
// Implements EIP-2537 G2MultiExp precompile logic
|
||||
// > G2 multiplication call expects `288*k` bytes as an input that is interpreted as byte concatenation of `k` slices each of them being a byte concatenation of encoding of G2 point (`256` bytes) and encoding of a scalar value (`32` bytes).
|
||||
// > Output is an encoding of multiexponentiation operation result - single G2 point (`256` bytes).
|
||||
|
|
@ -924,7 +937,7 @@ func (c *bls12381Pairing) RequiredGas(input []byte) uint64 {
|
|||
return params.Bls12381PairingBaseGas + uint64(len(input)/384)*params.Bls12381PairingPerPairGas
|
||||
}
|
||||
|
||||
func (c *bls12381Pairing) Run(input []byte) ([]byte, error) {
|
||||
func (c *bls12381Pairing) Run(opts *TaikoRunOpts, input []byte) ([]byte, error) {
|
||||
// Implements EIP-2537 Pairing precompile logic.
|
||||
// > Pairing call expects `384*k` bytes as an inputs that is interpreted as byte concatenation of `k` slices. Each slice has the following structure:
|
||||
// > - `128` bytes of G1 point encoding
|
||||
|
|
@ -1003,7 +1016,7 @@ func (c *bls12381MapG1) RequiredGas(input []byte) uint64 {
|
|||
return params.Bls12381MapG1Gas
|
||||
}
|
||||
|
||||
func (c *bls12381MapG1) Run(input []byte) ([]byte, error) {
|
||||
func (c *bls12381MapG1) Run(opts *TaikoRunOpts, input []byte) ([]byte, error) {
|
||||
// Implements EIP-2537 Map_To_G1 precompile.
|
||||
// > Field-to-curve call expects `64` bytes an an input that is interpreted as a an element of the base field.
|
||||
// > Output of this call is `128` bytes and is G1 point following respective encoding rules.
|
||||
|
|
@ -1038,7 +1051,7 @@ func (c *bls12381MapG2) RequiredGas(input []byte) uint64 {
|
|||
return params.Bls12381MapG2Gas
|
||||
}
|
||||
|
||||
func (c *bls12381MapG2) Run(input []byte) ([]byte, error) {
|
||||
func (c *bls12381MapG2) Run(opts *TaikoRunOpts, input []byte) ([]byte, error) {
|
||||
// Implements EIP-2537 Map_FP2_TO_G2 precompile logic.
|
||||
// > Field-to-curve call expects `128` bytes an an input that is interpreted as a an element of the quadratic extension field.
|
||||
// > Output of this call is `256` bytes and is G2 point following respective encoding rules.
|
||||
|
|
@ -1093,7 +1106,7 @@ var (
|
|||
)
|
||||
|
||||
// Run executes the point evaluation precompile.
|
||||
func (b *kzgPointEvaluation) Run(input []byte) ([]byte, error) {
|
||||
func (b *kzgPointEvaluation) Run(opts *TaikoRunOpts, input []byte) ([]byte, error) {
|
||||
if len(input) != blobVerifyInputLength {
|
||||
return nil, errBlobVerifyInvalidInputLength
|
||||
}
|
||||
|
|
|
|||
|
|
@ -98,7 +98,7 @@ func testPrecompiled(addr string, test precompiledTest, t *testing.T) {
|
|||
in := common.Hex2Bytes(test.Input)
|
||||
gas := p.RequiredGas(in)
|
||||
t.Run(fmt.Sprintf("%s-Gas=%d", test.Name, gas), func(t *testing.T) {
|
||||
if res, _, err := RunPrecompiledContract(p, in, gas); err != nil {
|
||||
if res, _, err := RunPrecompiledContract(p, in, gas, nil); err != nil {
|
||||
t.Error(err)
|
||||
} else if common.Bytes2Hex(res) != test.Expected {
|
||||
t.Errorf("Expected %v, got %v", test.Expected, common.Bytes2Hex(res))
|
||||
|
|
@ -120,7 +120,7 @@ func testPrecompiledOOG(addr string, test precompiledTest, t *testing.T) {
|
|||
gas := p.RequiredGas(in) - 1
|
||||
|
||||
t.Run(fmt.Sprintf("%s-Gas=%d", test.Name, gas), func(t *testing.T) {
|
||||
_, _, err := RunPrecompiledContract(p, in, gas)
|
||||
_, _, err := RunPrecompiledContract(p, in, gas, nil)
|
||||
if err.Error() != "out of gas" {
|
||||
t.Errorf("Expected error [out of gas], got [%v]", err)
|
||||
}
|
||||
|
|
@ -137,7 +137,7 @@ func testPrecompiledFailure(addr string, test precompiledFailureTest, t *testing
|
|||
in := common.Hex2Bytes(test.Input)
|
||||
gas := p.RequiredGas(in)
|
||||
t.Run(test.Name, func(t *testing.T) {
|
||||
_, _, err := RunPrecompiledContract(p, in, gas)
|
||||
_, _, err := RunPrecompiledContract(p, in, gas, nil)
|
||||
if err.Error() != test.ExpectedError {
|
||||
t.Errorf("Expected error [%v], got [%v]", test.ExpectedError, err)
|
||||
}
|
||||
|
|
@ -169,7 +169,7 @@ func benchmarkPrecompiled(addr string, test precompiledTest, bench *testing.B) {
|
|||
bench.ResetTimer()
|
||||
for i := 0; i < bench.N; i++ {
|
||||
copy(data, in)
|
||||
res, _, err = RunPrecompiledContract(p, data, reqGas)
|
||||
res, _, err = RunPrecompiledContract(p, data, reqGas, nil)
|
||||
}
|
||||
bench.StopTimer()
|
||||
elapsed := uint64(time.Since(start))
|
||||
|
|
|
|||
|
|
@ -220,7 +220,14 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas
|
|||
}
|
||||
|
||||
if isPrecompile {
|
||||
ret, gas, err = RunPrecompiledContract(p, input, gas)
|
||||
// CHANGE(taiko): create taikorunopts
|
||||
opts := &TaikoRunOpts{
|
||||
L1RPCUrl: evm.chainConfig.L1RPCUrl,
|
||||
StateDB: evm.StateDB,
|
||||
Interpreter: evm.interpreter,
|
||||
Caller: caller,
|
||||
}
|
||||
ret, gas, err = RunPrecompiledContract(p, input, gas, opts)
|
||||
} else {
|
||||
// Initialise a new contract and set the code that is to be used by the EVM.
|
||||
// The contract is a scoped environment for this execution context only.
|
||||
|
|
@ -283,7 +290,14 @@ func (evm *EVM) CallCode(caller ContractRef, addr common.Address, input []byte,
|
|||
|
||||
// It is allowed to call precompiles, even via delegatecall
|
||||
if p, isPrecompile := evm.precompile(addr); isPrecompile {
|
||||
ret, gas, err = RunPrecompiledContract(p, input, gas)
|
||||
// CHANGE(taiko): create taikorunopts
|
||||
opts := &TaikoRunOpts{
|
||||
L1RPCUrl: evm.chainConfig.L1RPCUrl,
|
||||
StateDB: evm.StateDB,
|
||||
Interpreter: evm.interpreter,
|
||||
Caller: caller,
|
||||
}
|
||||
ret, gas, err = RunPrecompiledContract(p, input, gas, opts)
|
||||
} else {
|
||||
addrCopy := addr
|
||||
// Initialise a new contract and set the code that is to be used by the EVM.
|
||||
|
|
@ -328,7 +342,14 @@ func (evm *EVM) DelegateCall(caller ContractRef, addr common.Address, input []by
|
|||
|
||||
// It is allowed to call precompiles, even via delegatecall
|
||||
if p, isPrecompile := evm.precompile(addr); isPrecompile {
|
||||
ret, gas, err = RunPrecompiledContract(p, input, gas)
|
||||
// CHANGE(taiko): create taikorunopts
|
||||
opts := &TaikoRunOpts{
|
||||
L1RPCUrl: evm.chainConfig.L1RPCUrl,
|
||||
StateDB: evm.StateDB,
|
||||
Interpreter: evm.interpreter,
|
||||
Caller: caller,
|
||||
}
|
||||
ret, gas, err = RunPrecompiledContract(p, input, gas, opts)
|
||||
} else {
|
||||
addrCopy := addr
|
||||
// Initialise a new contract and make initialise the delegate values
|
||||
|
|
@ -377,7 +398,14 @@ func (evm *EVM) StaticCall(caller ContractRef, addr common.Address, input []byte
|
|||
}
|
||||
|
||||
if p, isPrecompile := evm.precompile(addr); isPrecompile {
|
||||
ret, gas, err = RunPrecompiledContract(p, input, gas)
|
||||
// CHANGE(taiko): create taikorunopts
|
||||
opts := &TaikoRunOpts{
|
||||
L1RPCUrl: evm.chainConfig.L1RPCUrl,
|
||||
StateDB: evm.StateDB,
|
||||
Interpreter: evm.interpreter,
|
||||
Caller: caller,
|
||||
}
|
||||
ret, gas, err = RunPrecompiledContract(p, input, gas, opts)
|
||||
} else {
|
||||
// At this point, we use a copy of address. If we don't, the go compiler will
|
||||
// leak the 'contract' to the outer scope, and make allocation for 'contract'
|
||||
|
|
|
|||
137
core/vm/taiko.go
Normal file
137
core/vm/taiko.go
Normal file
|
|
@ -0,0 +1,137 @@
|
|||
// 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 vm
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/ethereum/go-ethereum"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/ethclient"
|
||||
"github.com/ethereum/go-ethereum/rpc"
|
||||
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
)
|
||||
|
||||
// l1Call implemented as a native contract. it executes read-only code from
|
||||
// an L1 Contract in the context of the L1 contract.
|
||||
type l1Call struct{}
|
||||
|
||||
// RequiredGas returns the gas required to execute the pre-compiled contract.
|
||||
func (c *l1Call) RequiredGas(input []byte) uint64 {
|
||||
return params.L1Call
|
||||
}
|
||||
|
||||
// Run implements
|
||||
// solidity call such as:
|
||||
// l1call(abi.encodePacked(address(contractAddress), abiEncodedData))
|
||||
func (c *l1Call) Run(opts *TaikoRunOpts, input []byte) ([]byte, error) {
|
||||
r, err := rpc.Dial(opts.L1RPCUrl)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
client := ethclient.NewClient(r)
|
||||
|
||||
// get first 32 bytes which should be the address of the contract
|
||||
addr := common.BytesToAddress(input[:32])
|
||||
|
||||
// rest of bytes should be msg data
|
||||
msgData := input[64:]
|
||||
|
||||
// use latest blockNumber for now?
|
||||
// call contract, get the response, but dont execute it on L1.
|
||||
contractResponse, err := client.CallContract(
|
||||
context.Background(),
|
||||
ethereum.CallMsg{
|
||||
To: &addr,
|
||||
Data: msgData,
|
||||
},
|
||||
nil,
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return contractResponse, nil
|
||||
}
|
||||
|
||||
// l1DelegateCall implemented as a native contract.
|
||||
// it executes read-only code from an L1 contract in the context of the L2
|
||||
// calling contract.
|
||||
type l1DelegateCall struct{}
|
||||
|
||||
// RequiredGas returns the gas required to execute the pre-compiled contract.
|
||||
func (c *l1DelegateCall) RequiredGas(input []byte) uint64 {
|
||||
return params.L1DelegateCall
|
||||
}
|
||||
|
||||
// Run implements
|
||||
// solidity call such as:
|
||||
// l1delegetecall(abi.encodePacked(address(contractAddress), abiEncodedData))
|
||||
// defaults to latest block. TODO: get latest block synced from
|
||||
// TaikoL2 contract, dont allow usage of L1 blocks that havent been
|
||||
// synced to L2.
|
||||
func (c *l1DelegateCall) Run(opts *TaikoRunOpts, input []byte) ([]byte, error) {
|
||||
snapshot := opts.StateDB.Snapshot()
|
||||
|
||||
defer func() {
|
||||
opts.StateDB.RevertToSnapshot(snapshot)
|
||||
}()
|
||||
|
||||
// add the L1 bytecode gotten below to this stateDB, then execute contract, then REVERT.
|
||||
|
||||
r, err := rpc.Dial(opts.L1RPCUrl)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
client := ethclient.NewClient(r)
|
||||
|
||||
// get first 32 bytes which should be the address of the contract
|
||||
addr := common.BytesToAddress(input[:32])
|
||||
|
||||
// rest of bytes should be msg data
|
||||
msgData := input[32:]
|
||||
|
||||
// use latest blockNumber for now?
|
||||
// call contract, get the response, but dont execute it on L1.
|
||||
l1ContractBytecode, err := client.CodeAt(
|
||||
context.Background(),
|
||||
addr,
|
||||
nil,
|
||||
)
|
||||
|
||||
// load this bytecode in at an address, and execute the rest of this msg.data
|
||||
// at that address.
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// overwrite L2 contract with the L1 contract, at the same address.
|
||||
// it will be reverted after
|
||||
contract := NewContract(opts.Caller, AccountRef(addr), nil, 0)
|
||||
contract.SetCallCode(&addr, opts.StateDB.GetCodeHash(addr), l1ContractBytecode)
|
||||
ret, err := opts.Interpreter.Run(contract, msgData, false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
|
|
@ -169,6 +169,9 @@ type Config struct {
|
|||
|
||||
// OverrideVerkle (TODO: remove after the fork)
|
||||
OverrideVerkle *uint64 `toml:",omitempty"`
|
||||
|
||||
//CHANGE(taiko):
|
||||
L1RPCUrl string
|
||||
}
|
||||
|
||||
// CreateConsensusEngine creates a consensus engine for the given chain config.
|
||||
|
|
|
|||
|
|
@ -341,7 +341,8 @@ type ChainConfig struct {
|
|||
IsDevMode bool `json:"isDev,omitempty"`
|
||||
|
||||
// CHANGE(taiko): Taiko network flag.
|
||||
Taiko bool `json:"taiko"`
|
||||
Taiko bool `json:"taiko"`
|
||||
L1RPCUrl string `json:"l1RpcUrl"`
|
||||
}
|
||||
|
||||
// EthashConfig is the consensus engine configs for proof-of-work based sealing.
|
||||
|
|
|
|||
|
|
@ -140,6 +140,9 @@ const (
|
|||
Ripemd160PerWordGas uint64 = 120 // Per-word price for a RIPEMD160 operation
|
||||
IdentityBaseGas uint64 = 15 // Base price for a data copy operation
|
||||
IdentityPerWordGas uint64 = 3 // Per-work price for a data copy operation
|
||||
// CHANGE(taiko): Gas cost for l1call and l1delegatecall
|
||||
L1Call uint64 = 1000
|
||||
L1DelegateCall uint64 = 1500
|
||||
|
||||
Bn256AddGasByzantium uint64 = 500 // Byzantium gas needed for an elliptic curve addition
|
||||
Bn256AddGasIstanbul uint64 = 150 // Gas needed for an elliptic curve addition
|
||||
|
|
|
|||
Loading…
Reference in a new issue