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

sendBundleToBuilder suavecli helper #78

Merged
merged 2 commits into from
Oct 27, 2023
Merged
Changes from 1 commit
Commits
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
Next Next commit
sendBundleToBuilder suavecli helper, minor fixes
  • Loading branch information
Ruteri committed Oct 27, 2023
commit 191b638eb10474776fc3ba6e87062e8b56346adf
4 changes: 2 additions & 2 deletions core/vm/contracts_suave_eth.go
Original file line number Diff line number Diff line change
@@ -502,10 +502,10 @@ func (c *submitBundleJsonRPC) runImpl(suaveContext *SuaveContext, url string, me
defer cancel()

request := map[string]interface{}{
"id": 1,
"id": json.RawMessage([]byte("1")),
"jsonrpc": "2.0",
"method": method,
"params": json.RawMessage(params),
"params": []interface{}{json.RawMessage(params)},
}

body, err := json.Marshal(request)
4 changes: 2 additions & 2 deletions core/vm/suave.go
Original file line number Diff line number Diff line change
@@ -117,10 +117,10 @@ func (p *SuavePrecompiledContractWrapper) Run(input []byte) ([]byte, error) {
ret, err = stub.buildEthBlock(input)

case fillMevShareBundleAddress:
return stub.fillMevShareBundle(input)
ret, err = stub.fillMevShareBundle(input)

case submitBundleJsonRPCAddress:
return stub.submitBundleJsonRPC(input)
ret, err = stub.submitBundleJsonRPC(input)

case submitEthBlockBidToRelayAddress:
ret, err = stub.submitEthBlockBidToRelay(input)
1 change: 1 addition & 0 deletions suave/cmd/suavecli/main.go
Original file line number Diff line number Diff line change
@@ -25,6 +25,7 @@ var commands = map[string]func(){
"deployMevShareContract": cmdDeployMevShareContract,
// send
"sendBundle": cmdSendBundle,
"sendBundleToBuilder": cmdSendBundleToBuilder,
"sendMevShareBundle": cmdSendMevShareBundle,
"sendMevShareMatch": cmdSendMevShareMatch,
"sendBuildShareBlock": cmdSendBuildShareBlock,
174 changes: 174 additions & 0 deletions suave/cmd/suavecli/sendBundleToBuilder.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
package main

import (
"context"
"crypto/ecdsa"
"encoding/json"
"flag"
"fmt"
"math/big"
"os"
"time"

"github.com/ethereum/go-ethereum/cmd/utils"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/rpc"
"github.com/ethereum/go-ethereum/suave/e2e"
"github.com/ethereum/go-ethereum/suave/sdk"
)

func cmdSendBundleToBuilder() {
flagset := flag.NewFlagSet("sendBundleToBuilder", flag.ExitOnError)

goerliBuilderUrl := "https://relay-goerli.flashbots.net/"

var (
suaveRpc = flagset.String("suave_rpc", "http://127.0.0.1:8545", "address of suave rpc")
executionNodeAddressHex = flagset.String("ex_node_addr", "0x4E2B0c0e428AE1CDE26d5BcF17Ba83f447068E5B", "wallet address of execution node")
goerliRpc = flagset.String("goerli_rpc", "http://127.0.0.1:8555", "address of goerli rpc")
privKeyHex = flagset.String("privkey", "", "private key as hex (for testing)")
verbosity = flagset.Int("verbosity", int(log.LvlInfo), "log verbosity (0-5)")
privKey *ecdsa.PrivateKey
)

var contractAddress *common.Address = nil
suaveContractAddress := common.HexToAddress("0x9281aFDb7997A3c01d0e6D985C7D157B8d6d0398")
contractAddress = &suaveContractAddress

flagset.Parse(os.Args[2:])

glogger := log.NewGlogHandler(log.StreamHandler(os.Stderr, log.TerminalFormat(false)))
log.Root().SetHandler(glogger)
glogger.Verbosity(log.Lvl(*verbosity))

privKey, err := crypto.HexToECDSA(*privKeyHex)
RequireNoErrorf(err, "-nodekeyhex: %v", err)
/* shush linter */ privKey.Public()

if executionNodeAddressHex == nil || *executionNodeAddressHex == "" {
utils.Fatalf("please provide ex_node_addr")
}
executionNodeAddress := common.HexToAddress(*executionNodeAddressHex)

suaveClient, err := rpc.DialContext(context.TODO(), *suaveRpc)
RequireNoErrorf(err, "could not connect to suave rpc: %v", err)

suaveSdkClient := sdk.NewClient(suaveClient, privKey, executionNodeAddress)

goerliClient, err := rpc.DialContext(context.TODO(), *goerliRpc)
RequireNoErrorf(err, "could not connect to goerli rpc: %v", err)

goerliSigner := types.LatestSigner(core.DefaultGoerliGenesisBlock().Config)

// Simply forwards to coinbase
addr := crypto.PubkeyToAddress(privKey.PublicKey)

if contractAddress == nil {
constructorArgs, err := e2e.EthBundleSenderContract.Abi.Constructor.Inputs.Pack([]string{goerliBuilderUrl})
RequireNoErrorf(err, "could not pack inputs: %v", err)

deploymentTxRes, err := sdk.DeployContract(append(e2e.EthBundleSenderContract.Code, constructorArgs...), suaveSdkClient)
RequireNoErrorf(err, "could not send deployment tx: %v", err)
deploymentReceipt, err := deploymentTxRes.Wait()

RequireNoErrorf(err, "error waiting for deployment tx inclusion: %v", err)
if deploymentReceipt.Status != 1 {
jsonEncodedReceipt, _ := deploymentReceipt.MarshalJSON()
utils.Fatalf("deployment not successful: %s", string(jsonEncodedReceipt))
}

contractAddress = &deploymentReceipt.ContractAddress
fmt.Println("contract address: ", deploymentReceipt.ContractAddress.Hex())
}

bundleSenderContract := sdk.GetContract(*contractAddress, e2e.EthBundleSenderContract.Abi, suaveSdkClient)
allowedPeekers := []common.Address{bundleSenderContract.Address()}
var goerliAccNonceBytes hexutil.Uint64
err = goerliClient.Call(&goerliAccNonceBytes, "eth_getTransactionCount", addr, "latest")
RequireNoErrorf(err, "could not call eth_getTransactionCount on goerli: %v", err)
goerliAccNonce := uint64(goerliAccNonceBytes)

// Prepare the bundle to land
// contractAddr := common.HexToAddress("0xAA5C331DF478c26e6909181fc306Ea535F0e4CCe")
ethTx1, err := types.SignTx(types.NewTx(&types.DynamicFeeTx{
To: &addr,
Nonce: goerliAccNonce,
GasTipCap: big.NewInt(74285714285),
GasFeeCap: big.NewInt(74285714285),
Gas: 21000,
Value: big.NewInt(1), // in wei
Data: []byte{},
}), goerliSigner, privKey)
RequireNoErrorf(err, "could not sign eth tx: %v", err)

ethTx2, err := types.SignTx(types.NewTx(&types.DynamicFeeTx{
To: &addr,
Nonce: goerliAccNonce + 1,
GasTipCap: big.NewInt(714285714285),
GasFeeCap: big.NewInt(714285714285),
Gas: 21000,
Value: big.NewInt(1), // in wei
Data: []byte{},
}), goerliSigner, privKey)
RequireNoErrorf(err, "could not sign eth tx: %v", err)

ethBundle := &types.SBundle{
Txs: types.Transactions{ethTx1, ethTx2},
RevertingHashes: []common.Hash{},
}
RequireNoErrorf(err, "could not marshal bundle: %v", err)

{
txs := []string{}
for _, tx := range ethBundle.Txs {
txJson, _ := tx.MarshalJSON()
txs = append(txs, string(txJson))
}
log.Info("Prepared eth bundle", "txs", txs)
}

for {
var currentGoerliBlockNumber hexutil.Uint64
err = goerliClient.Call(&currentGoerliBlockNumber, "eth_blockNumber")
RequireNoErrorf(err, "could not call eth_blockNumber on goerli: %v", err)

var suaveTxRess []*sdk.TransactionResult

minTargetBlock := uint64(currentGoerliBlockNumber) + uint64(1)
maxTargetBlock := minTargetBlock + uint64(10) // TODO: 25
for cTargetBlock := minTargetBlock; cTargetBlock <= maxTargetBlock; cTargetBlock++ {
// Send a bundle bid
ethBundle.BlockNumber = big.NewInt(int64(cTargetBlock))
ethBundleBytes, err := json.Marshal(ethBundle)
confidentialDataBytes, err := bundleBidAbi.Methods["fetchBidConfidentialBundleData"].Outputs.Pack(ethBundleBytes)
RequireNoErrorf(err, "could not pack bundle confidential data: %v", err)

confidentialRequestTxRes, err := bundleSenderContract.SendTransaction("newBid", []interface{}{cTargetBlock, allowedPeekers, []common.Address{}}, confidentialDataBytes)
RequireNoErrorf(err, "could not send bundle request: %v", err)
suaveTxRess = append(suaveTxRess, confidentialRequestTxRes)
}

for _, txRes := range suaveTxRess {
receipt, err := txRes.Wait()
if err != nil {
fmt.Println("Could not get the receipt", err)
}

if receipt.Status != 1 {
jsonEncodedReceipt, _ := receipt.MarshalJSON()
fmt.Println("Sending bundle request failed", string(jsonEncodedReceipt))
}
}

log.Info("All is good!")
time.Sleep(time.Minute)
}

// TODO: mby wait for confidentialRequestTxRes
// TODO: confirm (maybe in background) that the transactions all landed in blocks
}
16 changes: 9 additions & 7 deletions suave/e2e/workflow_test.go
Original file line number Diff line number Diff line change
@@ -297,7 +297,8 @@ func TestBundleSenderContract(t *testing.T) {
clt := fr.NewSDKClient()

bundleSentToBuilder := &struct {
Params types.RpcSBundle
Id json.RawMessage
Params []types.RpcSBundle
}{}
serveHttp := func(t *testing.T, w http.ResponseWriter, r *http.Request) {
bodyBytes, err := io.ReadAll(r.Body)
@@ -363,17 +364,18 @@ func TestBundleSenderContract(t *testing.T) {
require.Equal(t, uint8(types.SuaveTxType), receipts[0].Type)
require.Equal(t, uint64(1), receipts[0].Status)

require.Equal(t, 1, len(bundleSentToBuilder.Params.Txs))
require.Equal(t, 1, len(bundleSentToBuilder.Params))
require.Equal(t, 1, len(bundleSentToBuilder.Params[0].Txs))

var recoveredTx types.Transaction
require.NoError(t, recoveredTx.UnmarshalBinary(bundleSentToBuilder.Params.Txs[0]))
require.NoError(t, recoveredTx.UnmarshalBinary(bundleSentToBuilder.Params[0].Txs[0]))
expectedTxJson, err := signedTx.MarshalJSON()
require.NoError(t, err)
recoveredTxJson, err := recoveredTx.MarshalJSON()
require.NoError(t, err)
require.Equal(t, expectedTxJson, recoveredTxJson)

require.Equal(t, bundleSentToBuilder.Params.BlockNumber.ToInt().Uint64(), targetBlock)
require.Equal(t, bundleSentToBuilder.Params[0].BlockNumber.ToInt().Uint64(), targetBlock)
}
}

@@ -552,7 +554,7 @@ func TestMevShareBundleSenderContract(t *testing.T) {
clt := fr.NewSDKClient()

bundleSentToBuilder := &struct {
Params types.RPCMevShareBundle
Params []types.RPCMevShareBundle
}{}
serveHttp := func(t *testing.T, w http.ResponseWriter, r *http.Request) {
bodyBytes, err := io.ReadAll(r.Body)
@@ -622,7 +624,7 @@ func TestMevShareBundleSenderContract(t *testing.T) {
require.NoError(t, err)
require.Equal(t, uint64(1), receipt.Status)

retrievedBlockNumber, err := hexutil.DecodeUint64(bundleSentToBuilder.Params.Inclusion.Block)
retrievedBlockNumber, err := hexutil.DecodeUint64(bundleSentToBuilder.Params[0].Inclusion.Block)
require.NoError(t, err)
require.Equal(t, targetBlock, retrievedBlockNumber)

@@ -633,7 +635,7 @@ func TestMevShareBundleSenderContract(t *testing.T) {
require.NoError(t, err)

retrievedTxs := []string{}
for _, be := range bundleSentToBuilder.Params.Body {
for _, be := range bundleSentToBuilder.Params[0].Body {
retrievedTxs = append(retrievedTxs, be.Tx)
}