Skip to content

Commit

Permalink
basisc slot/signature preconfs addition
Browse files Browse the repository at this point in the history
  • Loading branch information
cyberhorsey committed Jun 27, 2024
1 parent 30a615b commit c8648e9
Show file tree
Hide file tree
Showing 20 changed files with 166 additions and 18 deletions.
3 changes: 2 additions & 1 deletion accounts/abi/bind/base.go
Original file line number Diff line number Diff line change
Expand Up @@ -423,7 +423,8 @@ func (c *BoundContract) transact(opts *TransactOpts, contract *common.Address, i
if opts.NoSend {
return signedTx, nil
}
if err := c.transactor.SendTransaction(ensureContext(opts.Context), signedTx); err != nil {
// change(taiko): slot and sig
if err := c.transactor.SendTransaction(ensureContext(opts.Context), signedTx, 0, ""); err != nil {
return nil, err
}
return signedTx, nil
Expand Down
2 changes: 1 addition & 1 deletion accounts/abi/bind/base_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ func (mt *mockTransactor) EstimateGas(ctx context.Context, call ethereum.CallMsg
return 0, nil
}

func (mt *mockTransactor) SendTransaction(ctx context.Context, tx *types.Transaction) error {
func (mt *mockTransactor) SendTransaction(ctx context.Context, tx *types.Transaction, slot uint64, signature string) error {
return nil
}

Expand Down
6 changes: 3 additions & 3 deletions accounts/abi/bind/util_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ func TestWaitDeployed(t *testing.T) {
}()

// Send and mine the transaction.
backend.Client().SendTransaction(ctx, tx)
backend.Client().SendTransaction(ctx, tx, 0, "")
backend.Commit()

select {
Expand Down Expand Up @@ -116,7 +116,7 @@ func TestWaitDeployedCornerCases(t *testing.T) {
tx, _ = types.SignTx(tx, types.LatestSigner(params.AllDevChainProtocolChanges), testKey)
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
backend.Client().SendTransaction(ctx, tx)
backend.Client().SendTransaction(ctx, tx, 0, "")
backend.Commit()
notContractCreation := errors.New("tx is not contract creation")
if _, err := bind.WaitDeployed(ctx, backend.Client(), tx); err.Error() != notContractCreation.Error() {
Expand All @@ -134,6 +134,6 @@ func TestWaitDeployedCornerCases(t *testing.T) {
}
}()

backend.Client().SendTransaction(ctx, tx)
backend.Client().SendTransaction(ctx, tx, 0, "")
cancel()
}
5 changes: 5 additions & 0 deletions cmd/geth/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,11 @@ func makeFullNode(ctx *cli.Context) (*node.Node, ethapi.Backend) {
v := ctx.Uint64(utils.OverrideVerkle.Name)
cfg.Eth.OverrideVerkle = &v
}
// change(taiko):
if ctx.IsSet(utils.PreconfirmationForwardingURLFlag.Name) {
cfg.Eth.PreconfirmationForwardingURL = ctx.String(utils.PreconfirmationForwardingURLFlag.Name)
}

backend, eth := utils.RegisterEthService(stack, &cfg.Eth)

// CHANGE(TAIKO): register Taiko RPC APIs.
Expand Down
1 change: 1 addition & 0 deletions cmd/geth/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,7 @@ var (
utils.AllowUnprotectedTxs,
utils.BatchRequestLimit,
utils.BatchResponseMaxSize,
utils.PreconfirmationForwardingURLFlag,
}

metricsFlags = []cli.Flag{
Expand Down
8 changes: 8 additions & 0 deletions cmd/utils/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -788,6 +788,14 @@ var (
Category: flags.APICategory,
}

// CHANGE(taiko): preconf url
PreconfirmationForwardingURLFlag = &cli.StringFlag{
Name: "preconfirmationforwardingurl",
Usage: "URL to forward eth_sendTransaction requests before confirmation",
Category: flags.APICategory,
Value: "",
}

// Gas price oracle settings
GpoBlocksFlag = &cli.IntFlag{
Name: "gpo.blocks",
Expand Down
8 changes: 8 additions & 0 deletions eth/api_backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import (
"github.com/ethereum/go-ethereum/eth/tracers"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/miner"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rpc"
Expand All @@ -48,6 +49,13 @@ type EthAPIBackend struct {
allowUnprotectedTxs bool
eth *Ethereum
gpo *gasprice.Oracle
preconfirmationURL string // change(taiko)
}

// GetPreconfirmationForwardingURL
func (b *EthAPIBackend) GetPreconfirmationForwardingURL() string {
log.Info("getting preconf from backend", "url", b.preconfirmationURL)
return b.preconfirmationURL
}

// ChainConfig returns the active chain configuration.
Expand Down
7 changes: 6 additions & 1 deletion eth/backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,9 @@ type Ethereum struct {
lock sync.RWMutex // Protects the variadic fields (e.g. gas price and etherbase)

shutdownTracker *shutdowncheck.ShutdownTracker // Tracks if and when the node has shutdown ungracefully

// change(taiko)
PreconfirmationForwardingURL string
}

// New creates a new Ethereum object (including the
Expand Down Expand Up @@ -252,7 +255,9 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) {
eth.miner = miner.New(eth, &config.Miner, eth.blockchain.Config(), eth.EventMux(), eth.engine, eth.isLocalBlock)
eth.miner.SetExtra(makeExtraData(config.Miner.ExtraData))

eth.APIBackend = &EthAPIBackend{stack.Config().ExtRPCEnabled(), stack.Config().AllowUnprotectedTxs, eth, nil}
// change(TAIKO): preconfirmation URL
log.Info("preconf url in eth.New", "url", config.PreconfirmationForwardingURL)
eth.APIBackend = &EthAPIBackend{stack.Config().ExtRPCEnabled(), stack.Config().AllowUnprotectedTxs, eth, nil, config.PreconfirmationForwardingURL}
if eth.APIBackend.allowUnprotectedTxs {
log.Info("Unprotected transactions allowed")
}
Expand Down
3 changes: 3 additions & 0 deletions eth/ethconfig/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,9 @@ type Config struct {

// OverrideVerkle (TODO: remove after the fork)
OverrideVerkle *uint64 `toml:",omitempty"`

// change(taiko): preconf url
PreconfirmationForwardingURL string
}

// CreateConsensusEngine creates a consensus engine for the given chain config.
Expand Down
29 changes: 27 additions & 2 deletions ethclient/ethclient.go
Original file line number Diff line number Diff line change
Expand Up @@ -612,16 +612,41 @@ func (ec *Client) EstimateGas(ctx context.Context, msg ethereum.CallMsg) (uint64
return uint64(hex), nil
}

// change(taiko): slot / signature for preconfs
// SendTransaction injects a signed transaction into the pending pool for execution.
//
// If the transaction was a contract creation use the TransactionReceipt method to get the
// contract address after the transaction has been mined.
func (ec *Client) SendTransaction(ctx context.Context, tx *types.Transaction) error {
func (ec *Client) SendTransaction(ctx context.Context, tx *types.Transaction, slot uint64, signature string) error {
type rawTransactionRequest struct {
RawTx hexutil.Bytes `json:"tx"`
Slot uint64 `json:"slot"`
Signature string `json:"signature"`
}

data, err := tx.MarshalBinary()
if err != nil {
return err
}
return ec.c.CallContext(ctx, nil, "eth_sendRawTransaction", hexutil.Encode(data))

request := rawTransactionRequest{
RawTx: data,
Slot: slot,
Signature: signature,
}

type inclusionPreconfirmationResponse struct {
Request rawTransactionRequest `json:"request"`
ProposerSignature string `json:"proposerSignature"`
}

var result *inclusionPreconfirmationResponse = nil

if slot != 0 && signature != "" {
result = &inclusionPreconfirmationResponse{}
}

return ec.c.CallContext(ctx, result, "eth_sendRawTransaction", request)
}

func toBlockNumArg(number *big.Int) string {
Expand Down
2 changes: 1 addition & 1 deletion ethclient/ethclient_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -753,5 +753,5 @@ func sendTransaction(ec *Client) error {
if err != nil {
return err
}
return ec.SendTransaction(context.Background(), tx)
return ec.SendTransaction(context.Background(), tx, 0, "")
}
4 changes: 2 additions & 2 deletions ethclient/gethclient/gethclient_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -378,7 +378,7 @@ func testSubscribePendingTransactions(t *testing.T, client *rpc.Client) {
t.Fatal(err)
}
// Send transaction
err = ethcl.SendTransaction(context.Background(), signedTx)
err = ethcl.SendTransaction(context.Background(), signedTx, 0, "")
if err != nil {
t.Fatal(err)
}
Expand Down Expand Up @@ -412,7 +412,7 @@ func testSubscribeFullPendingTransactions(t *testing.T, client *rpc.Client) {
t.Fatal(err)
}
// Send transaction
err = ethcl.SendTransaction(context.Background(), signedTx)
err = ethcl.SendTransaction(context.Background(), signedTx, 0, "")
if err != nil {
t.Fatal(err)
}
Expand Down
8 changes: 4 additions & 4 deletions ethclient/simulated/backend_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ func TestSendTransaction(t *testing.T) {
t.Errorf("could not create transaction: %v", err)
}
// send tx to simulated backend
err = client.SendTransaction(ctx, signedTx)
err = client.SendTransaction(ctx, signedTx, 0, "")
if err != nil {
t.Errorf("could not add tx to pending block: %v", err)
}
Expand Down Expand Up @@ -213,7 +213,7 @@ func TestForkResendTx(t *testing.T) {
if err != nil {
t.Fatalf("could not create transaction: %v", err)
}
client.SendTransaction(ctx, tx)
client.SendTransaction(ctx, tx, 0, "")
sim.Commit()

// 3.
Expand All @@ -229,7 +229,7 @@ func TestForkResendTx(t *testing.T) {

// 5.
sim.Commit()
if err := client.SendTransaction(ctx, tx); err != nil {
if err := client.SendTransaction(ctx, tx, 0, ""); err != nil {
t.Fatalf("sending transaction: %v", err)
}
sim.Commit()
Expand Down Expand Up @@ -260,7 +260,7 @@ func TestCommitReturnValue(t *testing.T) {
gasPrice := new(big.Int).Add(head.BaseFee, big.NewInt(1))
_tx := types.NewTransaction(0, testAddr, big.NewInt(1000), params.TxGas, gasPrice, nil)
tx, _ := types.SignTx(_tx, types.HomesteadSigner{}, testKey)
client.SendTransaction(ctx, tx)
client.SendTransaction(ctx, tx, 0, "")

h2 := sim.Commit()

Expand Down
2 changes: 1 addition & 1 deletion interfaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ type LogFilterer interface {
// API can use package accounts to maintain local private keys and need can retrieve the
// next available nonce using PendingNonceAt.
type TransactionSender interface {
SendTransaction(ctx context.Context, tx *types.Transaction) error
SendTransaction(ctx context.Context, tx *types.Transaction, slot uint64, signature string) error
}

// GasPricer wraps the gas price oracle, which monitors the blockchain to determine the
Expand Down
18 changes: 16 additions & 2 deletions internal/ethapi/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -1800,6 +1800,7 @@ func (s *TransactionAPI) SendTransaction(ctx context.Context, args TransactionAr
if err != nil {
return common.Hash{}, err
}

return SubmitTransaction(ctx, s.b, signed)
}

Expand All @@ -1822,13 +1823,26 @@ func (s *TransactionAPI) FillTransaction(ctx context.Context, args TransactionAr
return &SignTransactionResult{data, tx}, nil
}

// change(taiko): preconf logic
// SendRawTransaction will add the signed transaction to the transaction pool.
// The sender is responsible for signing the transaction and using the correct nonce.
func (s *TransactionAPI) SendRawTransaction(ctx context.Context, input hexutil.Bytes) (common.Hash, error) {
func (s *TransactionAPI) SendRawTransaction(ctx context.Context, txBytes hexutil.Bytes, slot *uint64, signature *string) (interface{}, error) {
// Decode the raw transaction
tx := new(types.Transaction)
if err := tx.UnmarshalBinary(input); err != nil {
if err := tx.UnmarshalBinary(txBytes); err != nil {
return common.Hash{}, err
}

fmt.Println("url", s.b.GetPreconfirmationForwardingURL(), slot, signature)
// Check if PreconfirmationForwardingURL is set
if forwardURL := s.b.GetPreconfirmationForwardingURL(); forwardURL != "" {
if signature != nil && slot != nil {
// Forward the raw transaction to the specified URL
return forwardRawTransaction(forwardURL, txBytes, *slot, *signature)
}
}

// Submit the transaction to the local node
return SubmitTransaction(ctx, s.b, tx)
}

Expand Down
4 changes: 4 additions & 0 deletions internal/ethapi/api_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -464,6 +464,10 @@ func (b *testBackend) setPendingBlock(block *types.Block) {
b.pending = block
}

// change(taiko): get preconf url
func (b testBackend) GetPreconfirmationForwardingURL() string {
return ""
}
func (b testBackend) SyncProgress() ethereum.SyncProgress { return ethereum.SyncProgress{} }
func (b testBackend) SuggestGasTipCap(ctx context.Context) (*big.Int, error) {
return big.NewInt(0), nil
Expand Down
3 changes: 3 additions & 0 deletions internal/ethapi/backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,9 @@ type Backend interface {
SubscribePendingLogsEvent(ch chan<- []*types.Log) event.Subscription
BloomStatus() (uint64, uint64)
ServiceFilter(ctx context.Context, session *bloombits.MatcherSession)

// change(taiko)
GetPreconfirmationForwardingURL() string
}

func GetAPIs(apiBackend Backend) []rpc.API {
Expand Down
63 changes: 63 additions & 0 deletions internal/ethapi/preconf.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package ethapi

import (
"bytes"
"encoding/json"
"fmt"
"net/http"

"github.com/ethereum/go-ethereum/common/hexutil"
)

type InclusionPreconfirmationRequest struct {
Tx []byte `json:"tx"`
Slot uint64 `json:"slot"`
Signature string `json:"signature"`
}

type InclusionPreconfirmationResponse struct {
Request InclusionPreconfirmationRequest `json:"request"`
ProposerSignature string `json:"proposerSignature"`
}

// change(taiko)
func forwardRawTransaction(forwardURL string, input hexutil.Bytes, slot uint64, signature string) (*InclusionPreconfirmationResponse, error) {
// Prepare the request
request := InclusionPreconfirmationRequest{
Tx: input,
Slot: slot, // Set the appropriate slot value
Signature: signature, // Set the appropriate signature value (a keccak256 hash)
}

jsonData, err := json.Marshal(request)
if err != nil {
return nil, err
}

// Send the request
req, err := http.NewRequest("POST", fmt.Sprintf("%v/%v", forwardURL, "commitments/v1/request_preconf"), bytes.NewBuffer(jsonData))
if err != nil {
return nil, err
}
req.Header.Set("Content-Type", "application/json")

client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()

if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("failed to forward transaction, status code: %d", resp.StatusCode)
}

// Parse the response
var response InclusionPreconfirmationResponse
err = json.NewDecoder(resp.Body).Decode(&response)
if err != nil {
return nil, err
}

return &response, nil
}
5 changes: 5 additions & 0 deletions internal/ethapi/transaction_args_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,11 @@ func (b *backendMock) setFork(fork string) error {
return nil
}

// change(taiko)
func (b *backendMock) GetPreconfirmationForwardingURL() string {
return ""
}

func (b *backendMock) SuggestGasTipCap(ctx context.Context) (*big.Int, error) {
return big.NewInt(42), nil
}
Expand Down
3 changes: 3 additions & 0 deletions node/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,9 @@ type Config struct {
EnablePersonal bool `toml:"-"`

DBEngine string `toml:",omitempty"`

// CHANGE(taiko): preconf url
PreconfirmationForwardingURL string `json:"preconfirmationforwardingurl,omitempty"`
}

// IPCEndpoint resolves an IPC endpoint based on a configured value, taking into
Expand Down

0 comments on commit c8648e9

Please sign in to comment.