Skip to content

Commit

Permalink
Implement eth_SendRawTransactionPermissioned
Browse files Browse the repository at this point in the history
  • Loading branch information
mdehoog committed Dec 14, 2024
1 parent efa05b1 commit 0b4c4ab
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 0 deletions.
13 changes: 13 additions & 0 deletions internal/ethapi/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -2208,6 +2208,19 @@ func (api *TransactionAPI) SendRawTransaction(ctx context.Context, input hexutil
return SubmitTransaction(ctx, api.b, tx)
}

// SendRawTransactionPermissioned is a version of SendRawTransaction that allows for
// a permissioned set of addresses allowed to deploy smart contracts.
func (api *TransactionAPI) SendRawTransactionPermissioned(ctx context.Context, input hexutil.Bytes, allowedCreators []common.Address) (common.Hash, error) {
tx := new(types.Transaction)
if err := tx.UnmarshalBinary(input); err != nil {
return common.Hash{}, err
}
if err := api.canSend(ctx, tx, allowedCreators); err != nil {
return common.Hash{}, err
}
return SubmitTransaction(ctx, api.b, tx)
}

// Sign calculates an ECDSA signature for:
// keccak256("\x19Ethereum Signed Message:\n" + len(message) + message).
//
Expand Down
58 changes: 58 additions & 0 deletions internal/ethapi/permissioned.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package ethapi

import (
"context"
"errors"

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

var ErrCreateUnauthorized = errors.New("unauthorized contract creation")

func (api *TransactionAPI) canSend(ctx context.Context, tx *types.Transaction, allowedCreators []common.Address) error {
mapAllowedCreators := make(map[common.Address]bool)
for _, creator := range allowedCreators {
mapAllowedCreators[creator] = true
}
state, head, err := api.b.StateAndHeaderByNumber(ctx, rpc.LatestBlockNumber)
if err != nil {
return err
}
signer := types.MakeSigner(api.b.ChainConfig(), head.Number, head.Time)
msg, err := core.TransactionToMessage(tx, signer, head.BaseFee)
if err != nil {
return err
}
if mapAllowedCreators[msg.From] {
return nil
}
if msg.To == nil {
return ErrCreateUnauthorized
}

var tracerError error
t := &tracing.Hooks{
OnOpcode: func(pc uint64, opcode byte, gas, cost uint64, scope tracing.OpContext, rData []byte, depth int, err error) {
op := vm.OpCode(opcode)
isCreate := op == vm.CREATE || op == vm.CREATE2
if isCreate && !mapAllowedCreators[scope.Address()] && !mapAllowedCreators[scope.Caller()] {
tracerError = ErrCreateUnauthorized
}
},
}
vmctx := core.NewEVMBlockContext(head, NewChainContext(ctx, api.b), nil, api.b.ChainConfig(), state)
vmenv := vm.NewEVM(vmctx, vm.TxContext{GasPrice: msg.GasPrice, BlobFeeCap: msg.BlobGasFeeCap}, state, api.b.ChainConfig(), vm.Config{Tracer: t, NoBaseFee: true})

var usedGas uint64
_, err = core.ApplyTransactionWithEVM(msg, api.b.ChainConfig(), new(core.GasPool).AddGas(msg.GasLimit), state, vmctx.BlockNumber, common.Hash{}, tx, &usedGas, vmenv)
if err != nil {
return err
}

return tracerError
}

0 comments on commit 0b4c4ab

Please sign in to comment.