Skip to content

Commit

Permalink
move bits.go to bits folder; type defines for OpCode and EncodingForm…
Browse files Browse the repository at this point in the history
…at; add more func descriptions
  • Loading branch information
ws4charlie committed Oct 15, 2024
1 parent dd80da8 commit d022be1
Show file tree
Hide file tree
Showing 14 changed files with 271 additions and 251 deletions.
4 changes: 4 additions & 0 deletions pkg/math/bits.go → pkg/math/bits/bits.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ func SetBit(b *byte, position uint8) {
if position > 7 {
return
}

// Example: given b = 0b00000000 and position = 3
// step-1: shift value 1 to left by 3 times: 1 << 3 = 0b00001000
// step-2: make an OR operation with original byte to set the bit: 0b00000000 | 0b00001000 = 0b00001000
*b |= 1 << position
}

Expand Down
File renamed without changes.
20 changes: 11 additions & 9 deletions pkg/memo/codec.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,21 @@ import (
"fmt"
)

type EncodingFormat uint8

// Enum for non-EVM chain memo encoding format (2 bits)
const (
// EncodingFmtABI represents ABI encoding format
EncodingFmtABI uint8 = 0b0000
EncodingFmtABI EncodingFormat = 0b0000

// EncodingFmtCompactShort represents 'compact short' encoding format
EncodingFmtCompactShort uint8 = 0b0001
EncodingFmtCompactShort EncodingFormat = 0b0001

// EncodingFmtCompactLong represents 'compact long' encoding format
EncodingFmtCompactLong uint8 = 0b0010
EncodingFmtCompactLong EncodingFormat = 0b0010

// EncodingFmtInvalid represents invalid encoding format
EncodingFmtInvalid uint8 = 0b0011
EncodingFmtInvalid EncodingFormat = 0b0011
)

// Enum for length of bytes used to encode compact data
Expand All @@ -38,7 +40,7 @@ type Codec interface {
}

// GetLenBytes returns the number of bytes used to encode the length of the data
func GetLenBytes(encodingFmt uint8) (int, error) {
func GetLenBytes(encodingFmt EncodingFormat) (int, error) {
switch encodingFmt {
case EncodingFmtCompactShort:
return LenBytesShort, nil
Expand All @@ -50,13 +52,13 @@ func GetLenBytes(encodingFmt uint8) (int, error) {
}

// GetCodec returns the codec based on the encoding format
func GetCodec(encodingFormat uint8) (Codec, error) {
switch encodingFormat {
func GetCodec(encodingFmt EncodingFormat) (Codec, error) {
switch encodingFmt {
case EncodingFmtABI:
return NewCodecABI(), nil
case EncodingFmtCompactShort, EncodingFmtCompactLong:
return NewCodecCompact(encodingFormat)
return NewCodecCompact(encodingFmt)
default:
return nil, fmt.Errorf("invalid encoding format %d", encodingFormat)
return nil, fmt.Errorf("invalid encoding format %d", encodingFmt)
}
}
5 changes: 4 additions & 1 deletion pkg/memo/codec_compact.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ import (
var _ Codec = (*CodecCompact)(nil)

// CodecCompact is a coder/decoder for compact encoded memo fields
//
// This encoding format concatenates the memo fields into a single byte array
// with zero padding to minimize the total size of the memo.
type CodecCompact struct {
// lenBytes is the number of bytes used to encode the length of the data
lenBytes int
Expand All @@ -21,7 +24,7 @@ type CodecCompact struct {
}

// NewCodecCompact creates a new compact codec
func NewCodecCompact(encodingFmt uint8) (*CodecCompact, error) {
func NewCodecCompact(encodingFmt EncodingFormat) (*CodecCompact, error) {
lenBytes, err := GetLenBytes(encodingFmt)
if err != nil {
return nil, err
Expand Down
128 changes: 64 additions & 64 deletions pkg/memo/codec_compact_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,24 +12,24 @@ import (

func Test_NewCodecCompact(t *testing.T) {
tests := []struct {
name string
encodingFmt uint8
fail bool
name string
encodeFmt memo.EncodingFormat
fail bool
}{
{
name: "create codec compact successfully",
encodingFmt: memo.EncodingFmtCompactShort,
name: "create codec compact successfully",
encodeFmt: memo.EncodingFmtCompactShort,
},
{
name: "create codec compact failed on invalid encoding format",
encodingFmt: 0b11,
fail: true,
name: "create codec compact failed on invalid encoding format",
encodeFmt: 0b11,
fail: true,
},
}

for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
codec, err := memo.NewCodecCompact(tc.encodingFmt)
codec, err := memo.NewCodecCompact(tc.encodeFmt)
if tc.fail {
require.Error(t, err)
require.Nil(t, codec)
Expand Down Expand Up @@ -64,14 +64,14 @@ func Test_CodecCompact_PackArguments(t *testing.T) {
// test cases
tests := []struct {
name string
encodingFmt uint8
encodeFmt memo.EncodingFormat
args []memo.CodecArg
expectedLen int
errMsg string
}{
{
name: "pack arguments of [address, bytes, string] in compact-short format",
encodingFmt: memo.EncodingFmtCompactShort,
name: "pack arguments of [address, bytes, string] in compact-short format",
encodeFmt: memo.EncodingFmtCompactShort,
args: []memo.CodecArg{
memo.ArgReceiver(argAddress),
memo.ArgPayload(argBytes),
Expand All @@ -80,8 +80,8 @@ func Test_CodecCompact_PackArguments(t *testing.T) {
expectedLen: 20 + 1 + len(argBytes) + 1 + len([]byte(argString)),
},
{
name: "pack arguments of [string, address, bytes] in compact-long format",
encodingFmt: memo.EncodingFmtCompactLong,
name: "pack arguments of [string, address, bytes] in compact-long format",
encodeFmt: memo.EncodingFmtCompactLong,
args: []memo.CodecArg{
memo.ArgRevertAddress(argString),
memo.ArgReceiver(argAddress),
Expand All @@ -90,65 +90,65 @@ func Test_CodecCompact_PackArguments(t *testing.T) {
expectedLen: 2 + len([]byte(argString)) + 20 + 2 + len(argBytes),
},
{
name: "pack long string (> 255 bytes) with compact-long format",
encodingFmt: memo.EncodingFmtCompactLong,
name: "pack long string (> 255 bytes) with compact-long format",
encodeFmt: memo.EncodingFmtCompactLong,
args: []memo.CodecArg{
memo.ArgPayload([]byte(sample.StringRandom(sample.Rand(), 256))),
},
expectedLen: 2 + 256,
},
{
name: "pack long string (> 255 bytes) with compact-short format should fail",
encodingFmt: memo.EncodingFmtCompactShort,
name: "pack long string (> 255 bytes) with compact-short format should fail",
encodeFmt: memo.EncodingFmtCompactShort,
args: []memo.CodecArg{
memo.ArgPayload([]byte(sample.StringRandom(sample.Rand(), 256))),
},
errMsg: "exceeds 255 bytes",
},
{
name: "pack long string (> 65535 bytes) with compact-long format should fail",
encodingFmt: memo.EncodingFmtCompactLong,
name: "pack long string (> 65535 bytes) with compact-long format should fail",
encodeFmt: memo.EncodingFmtCompactLong,
args: []memo.CodecArg{
memo.ArgPayload([]byte(sample.StringRandom(sample.Rand(), 65536))),
},
errMsg: "exceeds 65535 bytes",
},
{
name: "pack empty byte array and string arguments",
encodingFmt: memo.EncodingFmtCompactShort,
name: "pack empty byte array and string arguments",
encodeFmt: memo.EncodingFmtCompactShort,
args: []memo.CodecArg{
memo.ArgPayload([]byte{}),
memo.ArgRevertAddress(""),
},
expectedLen: 2,
},
{
name: "failed to pack bytes argument if string is passed",
encodingFmt: memo.EncodingFmtCompactShort,
name: "failed to pack bytes argument if string is passed",
encodeFmt: memo.EncodingFmtCompactShort,
args: []memo.CodecArg{
memo.ArgPayload(argString), // expect bytes type, but passed string
},
errMsg: "argument is not of type []byte",
},
{
name: "failed to pack address argument if bytes is passed",
encodingFmt: memo.EncodingFmtCompactShort,
name: "failed to pack address argument if bytes is passed",
encodeFmt: memo.EncodingFmtCompactShort,
args: []memo.CodecArg{
memo.ArgReceiver(argBytes), // expect address type, but passed bytes
},
errMsg: "argument is not of type common.Address",
},
{
name: "failed to pack string argument if bytes is passed",
encodingFmt: memo.EncodingFmtCompactShort,
name: "failed to pack string argument if bytes is passed",
encodeFmt: memo.EncodingFmtCompactShort,
args: []memo.CodecArg{
memo.ArgRevertAddress(argBytes), // expect string type, but passed bytes
},
errMsg: "argument is not of type string",
},
{
name: "failed to pack unsupported argument type",
encodingFmt: memo.EncodingFmtCompactShort,
name: "failed to pack unsupported argument type",
encodeFmt: memo.EncodingFmtCompactShort,
args: []memo.CodecArg{
memo.NewArg("receiver", memo.ArgType("unknown"), nil),
},
Expand All @@ -160,7 +160,7 @@ func Test_CodecCompact_PackArguments(t *testing.T) {
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
// create a new compact codec and add arguments
codec, err := memo.NewCodecCompact(tc.encodingFmt)
codec, err := memo.NewCodecCompact(tc.encodeFmt)
require.NoError(t, err)
codec.AddArguments(tc.args...)

Expand All @@ -176,7 +176,7 @@ func Test_CodecCompact_PackArguments(t *testing.T) {
require.Equal(t, tc.expectedLen, len(packedData))

// calc expected data for comparison
expectedData := sample.CompactPack(tc.encodingFmt, tc.args...)
expectedData := sample.CompactPack(tc.encodeFmt, tc.args...)

// validate the packed data
require.True(t, bytes.Equal(expectedData, packedData), "compact encoded data mismatch")
Expand All @@ -192,15 +192,15 @@ func Test_CodecCompact_UnpackArguments(t *testing.T) {

// test cases
tests := []struct {
name string
encodingFmt uint8
data []byte
expected []memo.CodecArg
errMsg string
name string
encodeFmt memo.EncodingFormat
data []byte
expected []memo.CodecArg
errMsg string
}{
{
name: "unpack arguments of [address, bytes, string] in compact-short format",
encodingFmt: memo.EncodingFmtCompactShort,
name: "unpack arguments of [address, bytes, string] in compact-short format",
encodeFmt: memo.EncodingFmtCompactShort,
data: sample.CompactPack(
memo.EncodingFmtCompactShort,
memo.ArgReceiver(argAddress),
Expand All @@ -214,8 +214,8 @@ func Test_CodecCompact_UnpackArguments(t *testing.T) {
},
},
{
name: "unpack arguments of [string, address, bytes] in compact-long format",
encodingFmt: memo.EncodingFmtCompactLong,
name: "unpack arguments of [string, address, bytes] in compact-long format",
encodeFmt: memo.EncodingFmtCompactLong,
data: sample.CompactPack(
memo.EncodingFmtCompactLong,
memo.ArgRevertAddress(argString),
Expand All @@ -229,8 +229,8 @@ func Test_CodecCompact_UnpackArguments(t *testing.T) {
},
},
{
name: "unpack empty byte array and string argument",
encodingFmt: memo.EncodingFmtCompactShort,
name: "unpack empty byte array and string argument",
encodeFmt: memo.EncodingFmtCompactShort,
data: sample.CompactPack(
memo.EncodingFmtCompactShort,
memo.ArgPayload([]byte{}),
Expand All @@ -242,35 +242,35 @@ func Test_CodecCompact_UnpackArguments(t *testing.T) {
},
},
{
name: "failed to unpack address if data length < 20 bytes",
encodingFmt: memo.EncodingFmtCompactShort,
data: []byte{0x01, 0x02, 0x03, 0x04, 0x05},
name: "failed to unpack address if data length < 20 bytes",
encodeFmt: memo.EncodingFmtCompactShort,
data: []byte{0x01, 0x02, 0x03, 0x04, 0x05},
expected: []memo.CodecArg{
memo.ArgReceiver(argAddress),
},
errMsg: "expected address, got 5 bytes",
},
{
name: "failed to unpack string if data length < 1 byte",
encodingFmt: memo.EncodingFmtCompactShort,
data: []byte{},
name: "failed to unpack string if data length < 1 byte",
encodeFmt: memo.EncodingFmtCompactShort,
data: []byte{},
expected: []memo.CodecArg{
memo.ArgRevertAddress(argString),
},
errMsg: "expected 1 bytes to decode length",
},
{
name: "failed to unpack string if actual data is less than decoded length",
encodingFmt: memo.EncodingFmtCompactShort,
data: []byte{0x05, 0x0a, 0x0b, 0x0c, 0x0d}, // length = 5, but only 4 bytes provided
name: "failed to unpack string if actual data is less than decoded length",
encodeFmt: memo.EncodingFmtCompactShort,
data: []byte{0x05, 0x0a, 0x0b, 0x0c, 0x0d}, // length = 5, but only 4 bytes provided
expected: []memo.CodecArg{
memo.ArgPayload(argBytes),
},
errMsg: "expected 5 bytes, got 4",
},
{
name: "failed to unpack bytes argument if string is passed",
encodingFmt: memo.EncodingFmtCompactShort,
name: "failed to unpack bytes argument if string is passed",
encodeFmt: memo.EncodingFmtCompactShort,
data: sample.CompactPack(
memo.EncodingFmtCompactShort,
memo.ArgPayload(argBytes),
Expand All @@ -281,8 +281,8 @@ func Test_CodecCompact_UnpackArguments(t *testing.T) {
errMsg: "argument is not of type *[]byte",
},
{
name: "failed to unpack address argument if bytes is passed",
encodingFmt: memo.EncodingFmtCompactShort,
name: "failed to unpack address argument if bytes is passed",
encodeFmt: memo.EncodingFmtCompactShort,
data: sample.CompactPack(
memo.EncodingFmtCompactShort,
memo.ArgReceiver(argAddress),
Expand All @@ -293,8 +293,8 @@ func Test_CodecCompact_UnpackArguments(t *testing.T) {
errMsg: "argument is not of type *common.Address",
},
{
name: "failed to unpack string argument if address is passed",
encodingFmt: memo.EncodingFmtCompactShort,
name: "failed to unpack string argument if address is passed",
encodeFmt: memo.EncodingFmtCompactShort,
data: sample.CompactPack(
memo.EncodingFmtCompactShort,
memo.ArgRevertAddress(argString),
Expand All @@ -305,17 +305,17 @@ func Test_CodecCompact_UnpackArguments(t *testing.T) {
errMsg: "argument is not of type *string",
},
{
name: "failed to unpack unsupported argument type",
encodingFmt: memo.EncodingFmtCompactShort,
data: []byte{},
name: "failed to unpack unsupported argument type",
encodeFmt: memo.EncodingFmtCompactShort,
data: []byte{},
expected: []memo.CodecArg{
memo.NewArg("payload", memo.ArgType("unknown"), nil),
},
errMsg: "unsupported argument (payload) type",
},
{
name: "unpacking should fail if not all data is consumed",
encodingFmt: memo.EncodingFmtCompactShort,
name: "unpacking should fail if not all data is consumed",
encodeFmt: memo.EncodingFmtCompactShort,
data: func() []byte {
data := sample.CompactPack(
memo.EncodingFmtCompactShort,
Expand All @@ -337,7 +337,7 @@ func Test_CodecCompact_UnpackArguments(t *testing.T) {
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
// create a new compact codec and add arguments
codec, err := memo.NewCodecCompact(tc.encodingFmt)
codec, err := memo.NewCodecCompact(tc.encodeFmt)
require.NoError(t, err)

// add output arguments
Expand Down
Loading

0 comments on commit d022be1

Please sign in to comment.