From 3d5d2f1948f40ded7ba98397f82b25ae199f31cb Mon Sep 17 00:00:00 2001 From: ImJeremyHe Date: Thu, 7 Dec 2023 10:58:54 +0800 Subject: [PATCH 1/2] Encode transactions in RLP format --- arbos/espresso/client.go | 2 +- arbos/parse_l2.go | 17 ++++++----------- execution/gethexec/executionengine.go | 3 +-- system_tests/espresso_test.go | 4 ++-- 4 files changed, 10 insertions(+), 16 deletions(-) diff --git a/arbos/espresso/client.go b/arbos/espresso/client.go index 0286acdaf4..7c2e12c3b9 100644 --- a/arbos/espresso/client.go +++ b/arbos/espresso/client.go @@ -62,7 +62,7 @@ type RawTransaction struct { } func (c *Client) SubmitTransaction(ctx context.Context, tx *types.Transaction) error { - var txnBytes, err = json.Marshal(tx) + var txnBytes, err = tx.MarshalBinary() if err != nil { return err } diff --git a/arbos/parse_l2.go b/arbos/parse_l2.go index 89098f0f7b..7f076c5323 100644 --- a/arbos/parse_l2.go +++ b/arbos/parse_l2.go @@ -3,7 +3,6 @@ package arbos import ( "bytes" "encoding/binary" - "encoding/json" "errors" "fmt" "io" @@ -15,6 +14,7 @@ import ( "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/rlp" "github.com/offchainlabs/nitro/arbos/arbostypes" "github.com/offchainlabs/nitro/arbos/espresso" "github.com/offchainlabs/nitro/arbos/util" @@ -199,7 +199,7 @@ func parseL2Message(rd io.Reader, poster common.Address, timestamp uint64, reque continue } newTx := new(types.Transaction) - if err := json.Unmarshal(nextMsg, &newTx); err != nil { + if err := newTx.UnmarshalBinary(nextMsg); err != nil { return nil, err } segments = append(segments, newTx) @@ -237,7 +237,7 @@ func parseEspressoMsg(rd io.Reader) ([]espresso.Bytes, *arbostypes.EspressoBlock } if jst == nil { j := new(arbostypes.EspressoBlockJustification) - if err := json.Unmarshal(nextMsg, &j); err != nil { + if err := rlp.DecodeBytes(nextMsg, &j); err != nil { return nil, nil, err } jst = j @@ -465,23 +465,18 @@ func parseBatchPostingReportMessage(rd io.Reader, chainId *big.Int, msgBatchGasC // messageFromEspresso serializes raw data from the espresso block into an arbitrum message, // including malformed and invalid transactions. // This allows validators to rebuild a block and check the espresso commitment. -// -// Note that the raw data is actually in JSON format, which can result in a larger size than necessary. -// Storing it in L1 call data would lead to some waste. However, for the sake of this Proof of Concept, -// this is deemed acceptable. Addtionally, after we finish the integration, there is no need to store -// message in L1. func MessageFromEspresso(header *arbostypes.L1IncomingMessageHeader, txes []espresso.Bytes, jst *arbostypes.EspressoBlockJustification) (arbostypes.L1IncomingMessage, error) { var l2Message []byte l2Message = append(l2Message, L2MessageKind_EspressoTx) - jstJson, err := json.Marshal(jst) + jstBin, err := rlp.EncodeToBytes(jst) if err != nil { return arbostypes.L1IncomingMessage{}, err } sizeBuf := make([]byte, 8) - binary.BigEndian.PutUint64(sizeBuf, uint64(len(jstJson))) + binary.BigEndian.PutUint64(sizeBuf, uint64(len(jstBin))) l2Message = append(l2Message, sizeBuf...) - l2Message = append(l2Message, jstJson...) + l2Message = append(l2Message, jstBin...) for _, tx := range txes { binary.BigEndian.PutUint64(sizeBuf, uint64(len(tx))) l2Message = append(l2Message, sizeBuf...) diff --git a/execution/gethexec/executionengine.go b/execution/gethexec/executionengine.go index 855dd30f0b..13d579a305 100644 --- a/execution/gethexec/executionengine.go +++ b/execution/gethexec/executionengine.go @@ -3,7 +3,6 @@ package gethexec import ( "context" "encoding/binary" - "encoding/json" "errors" "fmt" "sync" @@ -295,7 +294,7 @@ func (s *ExecutionEngine) SequenceTransactionsEspresso( txes := types.Transactions{} for _, tx := range rawTxes { var out types.Transaction - if err := json.Unmarshal(tx, &out); err != nil { + if err := out.UnmarshalBinary(tx); err != nil { log.Warn("Malformed tx is found") continue } diff --git a/system_tests/espresso_test.go b/system_tests/espresso_test.go index acf3440569..40063501c0 100644 --- a/system_tests/espresso_test.go +++ b/system_tests/espresso_test.go @@ -49,12 +49,12 @@ func onlyMalformedTxs(t *testing.T) [][]byte { // Two valid transactions and two invalid transactions with invalid nonces func userTxs(t *testing.T, l2Info *BlockchainTestInfo) [][]byte { tx1 := l2Info.PrepareTx("Faucet", "Owner", 3e7, big.NewInt(1e16), nil) - tx1Bin, err := json.Marshal(tx1) + tx1Bin, err := tx1.MarshalBinary() if err != nil { panic(err) } tx2 := l2Info.PrepareTx("Owner", "Faucet", 3e7, big.NewInt(1e16), nil) - tx2Bin, err := json.Marshal(tx2) + tx2Bin, err := tx2.MarshalBinary() if err != nil { panic(err) } From e88f700aaa27fe553adf8bde3924bb722513004b Mon Sep 17 00:00:00 2001 From: sveitser Date: Fri, 8 Dec 2023 09:27:06 +0100 Subject: [PATCH 2/2] Fix transaction encoding When moving to RLP encoding using int8 as a workaround to avoid base64 no longer works. I'm not sure the way the encoding is done now is a good idea though, we may want to rethink it. --- arbos/espresso/client.go | 8 ++++---- execution/gethexec/espresso_sequencer.go | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/arbos/espresso/client.go b/arbos/espresso/client.go index 7c2e12c3b9..fc5c45ebb3 100644 --- a/arbos/espresso/client.go +++ b/arbos/espresso/client.go @@ -58,7 +58,7 @@ func (c *Client) FetchHeader(ctx context.Context, blockHeight uint64) (Header, e type RawTransaction struct { Vm int `json:"vm"` - Payload []int8 `json:"payload"` + Payload []uint `json:"payload"` } func (c *Client) SubmitTransaction(ctx context.Context, tx *types.Transaction) error { @@ -68,9 +68,9 @@ func (c *Client) SubmitTransaction(ctx context.Context, tx *types.Transaction) e } // json.RawMessage is a []byte array, which is marshalled as a base64-encoded string. // Our sequencer API expects a JSON array. - payload := make([]int8, len(txnBytes)) + payload := make([]uint, len(txnBytes)) for i := range payload { - payload[i] = int8(txnBytes[i]) + payload[i] = uint(txnBytes[i]) } txn := RawTransaction{ Vm: int(c.namespace), @@ -80,7 +80,7 @@ func (c *Client) SubmitTransaction(ctx context.Context, tx *types.Transaction) e if err != nil { return err } - fmt.Println(c.baseUrl) + request, err := http.NewRequest("POST", c.baseUrl+"submit/submit", bytes.NewBuffer(marshalled)) if err != nil { return err diff --git a/execution/gethexec/espresso_sequencer.go b/execution/gethexec/espresso_sequencer.go index 357d291b94..7039afd159 100644 --- a/execution/gethexec/espresso_sequencer.go +++ b/execution/gethexec/espresso_sequencer.go @@ -123,7 +123,7 @@ func (s *EspressoSequencer) Start(ctxIn context.Context) error { // Required methods for the TransactionPublisher interface func (s *EspressoSequencer) PublishTransaction(parentCtx context.Context, tx *types.Transaction, options *arbitrum_types.ConditionalOptions) error { if err := s.hotShotState.client.SubmitTransaction(parentCtx, tx); err != nil { - log.Error("Failed to submit transaction", err) + log.Error("Failed to submit transaction", "error", err, "tx", tx) return err } return nil