Skip to content

Commit

Permalink
add builder signature to header 0.1 and 0.2
Browse files Browse the repository at this point in the history
  • Loading branch information
Sneh1999 committed Oct 21, 2024
1 parent 86687b7 commit dc5d378
Show file tree
Hide file tree
Showing 5 changed files with 152 additions and 110 deletions.
156 changes: 78 additions & 78 deletions tagged-base64/tagged_base64_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,93 +25,93 @@ func TestStringParse(t *testing.T) {
// - Generated string can be parsed
// - Accessors and parsed string match the supplied values
func checkTb64(t *testing.T, tag string, value []byte) {
tb64, err := New(tag, value)
require.NoError(t, err)
str := tb64.String()
tb64, err := New(tag, value)
require.NoError(t, err)
str := tb64.String()

parsed, err := Parse(str)
require.NoError(t, err)
parsed, err := Parse(str)
require.NoError(t, err)

require.Equal(t, tb64, parsed)
require.Equal(t, tb64, parsed)

// Do we get back the tag we supplied?
require.Equal(t, parsed.Tag(), tag)
// Do we get back the tag we supplied?
require.Equal(t, parsed.Tag(), tag)

// Do we get back the binary value we supplied?
require.Equal(t, parsed.Value(), value)
// Do we get back the binary value we supplied?
require.Equal(t, parsed.Value(), value)
}

func TestParse(t *testing.T) {
// The empty string is not a valid TaggedBase64.
_, err := Parse("")
require.NotNil(t, err)

// The tag is alphanumeric with hyphen and underscore.
// The value here is the base64 encoding of foobar, but
// the encoding doesn't include the required checksum.
_, err = Parse("-_~Zm9vYmFy")
require.NotNil(t, err)

// An invalid tag should err.
_, err = Parse("&_~wA")
require.NotNil(t, err)

// A null value is not allowed.
b64Null := BASE64.EncodeToString([]byte{});
tagged := fmt.Sprintf("a~%s", b64Null)
_, err = Parse(tagged)
require.NotNil(t, err)

// The tag can be empty, but the value cannot because the value
// includes the checksum.
_, err = Parse("~")
require.NotNil(t, err)

checkTb64(t, "mytag", []byte("mytag"))

// Only base64 characters are allowed in the tag. No restrictions on
// the value because it will get base64 encoded.
checkTb64(
t,
"abcdefghijklmnopqrstuvwxyz-ABCDEFGHIJKLMNOPQRSTUVWXYZ_0123456789",
[]byte("~Yeah, we can have spaces and odd stuff—😀 here. ¯⧵_(ツ)_/¯"),
)
checkTb64(
t,
"",
[]byte("abcdefghijklmnopqrstuvwxyz-ABCDEFGHIJKLMNOPQRSTUVWXYZ_0123456789~"),
);

// All the following have invalid characters in the tag.
_, err = New("~", []byte{})
require.NotNil(t, err)
_, err = New("a~", []byte{})
require.NotNil(t, err)
_, err = New("~b", []byte{})
require.NotNil(t, err)
_, err = New("c~d", []byte{})
require.NotNil(t, err)
_, err = New("e~f~", []byte{})
require.NotNil(t, err)
_, err = New("g~h~i", []byte{})
require.NotNil(t, err)
_, err = New("Oh, no!", []byte{})
require.NotNil(t, err)
_, err = New("Σ", []byte{})
require.NotNil(t, err)
// The empty string is not a valid TaggedBase64.
_, err := Parse("")
require.NotNil(t, err)

// The tag is alphanumeric with hyphen and underscore.
// The value here is the base64 encoding of foobar, but
// the encoding doesn't include the required checksum.
_, err = Parse("-_~Zm9vYmFy")
require.NotNil(t, err)

// An invalid tag should err.
_, err = Parse("&_~wA")
require.NotNil(t, err)

// A null value is not allowed.
b64Null := BASE64.EncodeToString([]byte{})
tagged := fmt.Sprintf("a~%s", b64Null)
_, err = Parse(tagged)
require.NotNil(t, err)

// The tag can be empty, but the value cannot because the value
// includes the checksum.
_, err = Parse("~")
require.NotNil(t, err)

checkTb64(t, "mytag", []byte("mytag"))

// Only base64 characters are allowed in the tag. No restrictions on
// the value because it will get base64 encoded.
checkTb64(
t,
"abcdefghijklmnopqrstuvwxyz-ABCDEFGHIJKLMNOPQRSTUVWXYZ_0123456789",
[]byte("~Yeah, we can have spaces and odd stuff—😀 here. ¯⧵_(ツ)_/¯"),
)
checkTb64(
t,
"",
[]byte("abcdefghijklmnopqrstuvwxyz-ABCDEFGHIJKLMNOPQRSTUVWXYZ_0123456789~"),
)

// All the following have invalid characters in the tag.
_, err = New("~", []byte{})
require.NotNil(t, err)
_, err = New("a~", []byte{})
require.NotNil(t, err)
_, err = New("~b", []byte{})
require.NotNil(t, err)
_, err = New("c~d", []byte{})
require.NotNil(t, err)
_, err = New("e~f~", []byte{})
require.NotNil(t, err)
_, err = New("g~h~i", []byte{})
require.NotNil(t, err)
_, err = New("Oh, no!", []byte{})
require.NotNil(t, err)
_, err = New("Σ", []byte{})
require.NotNil(t, err)
}

func TestCompat(t *testing.T) {
// A hard-coded example, to check compatibility with the original, Rust implementation.
tag := "abcdefghijklmnopqrstuvwxyz-ABCDEFGHIJKLMNOPQRSTUVWXYZ_0123456789"
data := []byte("~Yeah, we can have spaces and odd stuff—😀 here. ¯⧵_(ツ)_/¯")
expected := "abcdefghijklmnopqrstuvwxyz-ABCDEFGHIJKLMNOPQRSTUVWXYZ_0123456789~flllYWgsIHdlIGNhbiBoYXZlIHNwYWNlcyBhbmQgb2RkIHN0dWZm4oCU8J-YgCBoZXJlLiDCr-KntV8o44OEKV8vwq_6"

tb64, err := New(tag, data)
require.NoError(t, err)
s := tb64.String()
require.Equal(t, s, expected)
parsed, err := Parse(expected)
require.NoError(t, err)
require.Equal(t, tb64, parsed)
tag := "abcdefghijklmnopqrstuvwxyz-ABCDEFGHIJKLMNOPQRSTUVWXYZ_0123456789"
data := []byte("~Yeah, we can have spaces and odd stuff—😀 here. ¯⧵_(ツ)_/¯")
expected := "abcdefghijklmnopqrstuvwxyz-ABCDEFGHIJKLMNOPQRSTUVWXYZ_0123456789~flllYWgsIHdlIGNhbiBoYXZlIHNwYWNlcyBhbmQgb2RkIHN0dWZm4oCU8J-YgCBoZXJlLiDCr-KntV8o44OEKV8vwq_6"

tb64, err := New(tag, data)
require.NoError(t, err)
s := tb64.String()
require.Equal(t, s, expected)
parsed, err := Parse(expected)
require.NoError(t, err)
require.Equal(t, tb64, parsed)
}
12 changes: 12 additions & 0 deletions types/headers.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ type Header struct {
BlockMerkleTreeRoot *TaggedBase64 `json:"block_merkle_tree_root"`
FeeMerkleTreeRoot *TaggedBase64 `json:"fee_merkle_tree_root"`
FeeInfo *FeeInfo `json:"fee_info"`
BuilderSignature *BuilderSignature `json:"builder_signature"`
}

func (h *Header) Version() Version {
Expand All @@ -152,6 +153,10 @@ func (h *Header) GetFeeMerkleTreeRoot() *TaggedBase64 {
return h.FeeMerkleTreeRoot
}

func (h *Header) GetBuilderSignature() *BuilderSignature {
return h.BuilderSignature
}

func (h *Header) UnmarshalJSON(b []byte) error {
// Parse using pointers so we can distinguish between missing and default fields.
type Dec struct {
Expand All @@ -166,6 +171,7 @@ func (h *Header) UnmarshalJSON(b []byte) error {
BlockMerkleTreeRoot **TaggedBase64 `json:"block_merkle_tree_root"`
FeeMerkleTreeRoot **TaggedBase64 `json:"fee_merkle_tree_root"`
FeeInfo **FeeInfo `json:"fee_info"`
BuilderSignature **BuilderSignature `json:"builder_signature"`
}

var dec Dec
Expand Down Expand Up @@ -218,6 +224,11 @@ func (h *Header) UnmarshalJSON(b []byte) error {
}
h.FeeInfo = *dec.FeeInfo

if dec.BuilderSignature == nil {
return fmt.Errorf("Field builder_signature of type Header is required")
}
h.BuilderSignature = *dec.BuilderSignature

if dec.ChainConfig == nil {
return fmt.Errorf("Field chain_info of type Header is required")
}
Expand Down Expand Up @@ -248,6 +259,7 @@ func (self *Header) Commit() Commitment {
VarSizeField("block_merkle_tree_root", self.BlockMerkleTreeRoot.Value()).
VarSizeField("fee_merkle_tree_root", self.FeeMerkleTreeRoot.Value()).
Field("fee_info", self.FeeInfo.Commit()).
Field("builder_signature", self.BuilderSignature.Commit()).
Finalize()
}

Expand Down
63 changes: 34 additions & 29 deletions types/test-data/header0_1.json
Original file line number Diff line number Diff line change
@@ -1,32 +1,37 @@
{
"chain_config": {
"chain_config": {
"chain_config": {
"Left": {
"chain_id": "35353",
"max_block_size": "10240",
"base_fee": "0",
"fee_contract": "0x0000000000000000000000000000000000000000",
"fee_recipient": "0x0000000000000000000000000000000000000000"
}
}
},
"height": 42,
"timestamp": 789,
"l1_head": 124,
"l1_finalized": {
"number": 123,
"timestamp": "0x456",
"hash": "0x0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
},
"payload_commitment": "HASH~1yS-KEtL3oDZDBJdsW51Pd7zywIiHesBZsTbpOzrxOfu",
"builder_commitment": "BUILDER_COMMITMENT~1yS-KEtL3oDZDBJdsW51Pd7zywIiHesBZsTbpOzrxOdZ",
"ns_table": {
"bytes": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
},
"block_merkle_tree_root": "MERKLE_COMM~yB4_Aqa35_PoskgTpcCR1oVLh6BUdLHIs7erHKWi-usUAAAAAAAAAAEAAAAAAAAAJg",
"fee_merkle_tree_root": "MERKLE_COMM~VJ9z239aP9GZDrHp3VxwPd_0l28Hc5KEAB1pFeCIxhYgAAAAAAAAAAIAAAAAAAAAdA",
"fee_info": {
"account": "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266",
"amount": "0"
"Left": {
"chain_id": "35353",
"max_block_size": "10240",
"base_fee": "0",
"fee_contract": "0x0000000000000000000000000000000000000000",
"fee_recipient": "0x0000000000000000000000000000000000000000"
}
}
}
},
"height": 42,
"timestamp": 789,
"l1_head": 124,
"l1_finalized": {
"number": 123,
"timestamp": "0x456",
"hash": "0x0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
},
"payload_commitment": "HASH~1yS-KEtL3oDZDBJdsW51Pd7zywIiHesBZsTbpOzrxOfu",
"builder_commitment": "BUILDER_COMMITMENT~1yS-KEtL3oDZDBJdsW51Pd7zywIiHesBZsTbpOzrxOdZ",
"ns_table": {
"bytes": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
},
"block_merkle_tree_root": "MERKLE_COMM~yB4_Aqa35_PoskgTpcCR1oVLh6BUdLHIs7erHKWi-usUAAAAAAAAAAEAAAAAAAAAJg",
"fee_merkle_tree_root": "MERKLE_COMM~VJ9z239aP9GZDrHp3VxwPd_0l28Hc5KEAB1pFeCIxhYgAAAAAAAAAAIAAAAAAAAAdA",
"fee_info": {
"account": "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266",
"amount": "0"
},
"builder_signature": {
"r": "0x1f92bab6350d4f33e04f9e9278d89f644d0abea16d6f882e91f87bec4e0ba53d",
"s": "0x2067627270a89b06e7486c2c56fef0fee5f49a14b296a1cde580b0b40fa7430f",
"v": 27
}
}
19 changes: 19 additions & 0 deletions types/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,20 @@ func (self *FeeInfo) Commit() Commitment {
Finalize()
}

type BuilderSignature struct {
R common.Hash `json:"r"`
S common.Hash `json:"s"`
V uint64 `json:"v"`
}

func (bs *BuilderSignature) Commit() Commitment {
return NewRawCommitmentBuilder("BUILDER_SIGNATURE").
FixedSizeField("r", bs.R[:]).
FixedSizeField("s", bs.S[:]).
Uint64Field("v", bs.V).
Finalize()
}

// For some intricate reasons, rollups need to build a dummy header as a placeholder. However, an empty Header can be serialized
// but can not be deserialized because of the checks. Thus we provide this dummy header as a workaround.
func GetDummyHeader() Header {
Expand Down Expand Up @@ -390,5 +404,10 @@ func GetDummyHeader() Header {
PayloadCommitment: payloadCommitment,
FeeInfo: &FeeInfo{Account: common.HexToAddress("0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266"), Amount: *NewU256().SetUint64(0).ToDecimal()},
L1Finalized: &blockInfo,
BuilderSignature: &BuilderSignature{
R: common.HexToHash("0x1f92bab6350d4f33e04f9e9278d89f644d0abea16d6f882e91f87bec4e0ba53d"),
S: common.HexToHash("0x2067627270a89b06e7486c2c56fef0fee5f49a14b296a1cde580b0b40fa7430f"),
V: uint64(27),
},
}
}
12 changes: 9 additions & 3 deletions types/types_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,11 @@ var ReferenceHeader Header = Header{
BlockMerkleTreeRoot: ReferenceBlockMerkleTreeRoot,
FeeMerkleTreeRoot: ReferenceFeeMerkleTreeRoot,
FeeInfo: &FeeInfo{Account: common.HexToAddress("0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266"), Amount: *NewU256().SetUint64(0).ToDecimal()},
BuilderSignature: &BuilderSignature{
R: common.HexToHash("0x1f92bab6350d4f33e04f9e9278d89f644d0abea16d6f882e91f87bec4e0ba53d"),
S: common.HexToHash("0x2067627270a89b06e7486c2c56fef0fee5f49a14b296a1cde580b0b40fa7430f"),
V: 27,
},
}

var ReferenceTransaction Transaction = Transaction{
Expand Down Expand Up @@ -118,7 +123,8 @@ func TestEspressoTypesHeaderJson(t *testing.T) {
},
"block_merkle_tree_root": "MERKLE_COMM~yB4_Aqa35_PoskgTpcCR1oVLh6BUdLHIs7erHKWi-usUAAAAAAAAAAEAAAAAAAAAJg",
"fee_merkle_tree_root": "MERKLE_COMM~VJ9z239aP9GZDrHp3VxwPd_0l28Hc5KEAB1pFeCIxhYgAAAAAAAAAAIAAAAAAAAAdA",
"fee_info":{"account":"0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266","amount":"0"}
"fee_info":{"account":"0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266","amount":"0"},
"builder_signature":{"r":"0x1f92bab6350d4f33e04f9e9278d89f644d0abea16d6f882e91f87bec4e0ba53d","s":"0x2067627270a89b06e7486c2c56fef0fee5f49a14b296a1cde580b0b40fa7430f","v":27}
}`))

// Check encoding.
Expand All @@ -135,7 +141,7 @@ func TestEspressoTypesHeaderJson(t *testing.T) {
}
require.Equal(t, decoded, ReferenceHeader)

CheckJsonRequiredFields[Header](t, data, "height", "timestamp", "l1_head", "payload_commitment", "builder_commitment", "block_merkle_tree_root", "fee_merkle_tree_root", "fee_info", "chain_config")
CheckJsonRequiredFields[Header](t, data, "height", "timestamp", "l1_head", "payload_commitment", "builder_commitment", "block_merkle_tree_root", "fee_merkle_tree_root", "fee_info", "builder_signature", "chain_config")
}

func TestEspressoTransactionJson(t *testing.T) {
Expand Down Expand Up @@ -174,7 +180,7 @@ func TestEspressoTypesNsTable(t *testing.T) {
}

func TestEspressoTypesHeaderCommit(t *testing.T) {
require.Equal(t, ReferenceHeader.Commit(), Commitment{108, 66, 152, 60, 96, 143, 195, 17, 58, 161, 229, 97, 42, 65, 218, 52, 73, 30, 164, 118, 5, 26, 70, 222, 184, 71, 228, 1, 92, 215, 177, 152})
require.Equal(t, ReferenceHeader.Commit(), Commitment{231, 29, 239, 71, 22, 101, 198, 223, 100, 115, 197, 203, 125, 6, 172, 149, 141, 226, 79, 254, 84, 28, 152, 122, 37, 222, 143, 27, 192, 81, 80, 57})
}

func TestEspressoTypesTransaction(t *testing.T) {
Expand Down

0 comments on commit dc5d378

Please sign in to comment.