-
Notifications
You must be signed in to change notification settings - Fork 110
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: standard non-evm inbound memo (#2987)
* initiated memo package * add unit tests against memo fields version 0 * added memo unit tests * use separate file for memo header; add more unit tests * a few renaming and wrapped err message * add extra good-to-have check for memo fields validation * add changelog entry * fix nosec error * add two more unit tests for missed lines * remove redundant dependency github.com/test-go/testify v1.1.4 * enhance codec error message * a few renaming and move test constant to testutil pkg * corrected typo and improved unit tests * fix build * make receiver address optional * move bits.go to bits folder; type defines for OpCode and EncodingFormat; add more func descriptions * move legacy Bitcoin memo decoding to memo package * move sample functions ABIPack, CompactPack into memo pkg self; remove sample package reference from memo to minimize dependency * fix unit test compile error
- Loading branch information
1 parent
7b2bbe7
commit 250b90e
Showing
24 changed files
with
2,954 additions
and
70 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
package math | ||
|
||
import ( | ||
"math/bits" | ||
) | ||
|
||
// SetBit sets the bit at the given position (0-7) in the byte to 1 | ||
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 | ||
} | ||
|
||
// IsBitSet returns true if the bit at the given position (0-7) is set in the byte, false otherwise | ||
func IsBitSet(b byte, position uint8) bool { | ||
if position > 7 { | ||
return false | ||
} | ||
bitMask := byte(1 << position) | ||
return b&bitMask != 0 | ||
} | ||
|
||
// GetBits extracts the value of bits for a given mask | ||
// | ||
// Example: given b = 0b11011001 and mask = 0b11100000, the function returns 0b110 | ||
func GetBits(b byte, mask byte) byte { | ||
extracted := b & mask | ||
|
||
// get the number of trailing zero bits | ||
trailingZeros := bits.TrailingZeros8(mask) | ||
|
||
// remove trailing zeros | ||
return extracted >> trailingZeros | ||
} | ||
|
||
// SetBits sets the value to the bits specified in the mask | ||
// | ||
// Example: given b = 0b00100001 and mask = 0b11100000, and value = 0b110, the function returns 0b11000001 | ||
func SetBits(b byte, mask byte, value byte) byte { | ||
// get the number of trailing zero bits in the mask | ||
trailingZeros := bits.TrailingZeros8(mask) | ||
|
||
// shift the value left by the number of trailing zeros | ||
valueShifted := value << trailingZeros | ||
|
||
// clear the bits in 'b' that correspond to the mask | ||
bCleared := b &^ mask | ||
|
||
// Set the bits by ORing the cleared 'b' with the shifted value | ||
return bCleared | valueShifted | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,171 @@ | ||
package math_test | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/stretchr/testify/require" | ||
zetabits "github.com/zeta-chain/node/pkg/math/bits" | ||
) | ||
|
||
func TestSetBit(t *testing.T) { | ||
tests := []struct { | ||
name string | ||
initial byte | ||
position uint8 | ||
expected byte | ||
}{ | ||
{ | ||
name: "set bit at position 0", | ||
initial: 0b00001000, | ||
position: 0, | ||
expected: 0b00001001, | ||
}, | ||
{ | ||
name: "set bit at position 7", | ||
initial: 0b00001000, | ||
position: 7, | ||
expected: 0b10001000, | ||
}, | ||
{ | ||
name: "out of range bit position (no effect)", | ||
initial: 0b00000000, | ||
position: 8, // Out of range | ||
expected: 0b00000000, | ||
}, | ||
} | ||
|
||
for _, tt := range tests { | ||
t.Run(tt.name, func(t *testing.T) { | ||
b := tt.initial | ||
zetabits.SetBit(&b, tt.position) | ||
require.Equal(t, tt.expected, b) | ||
}) | ||
} | ||
} | ||
|
||
func TestIsBitSet(t *testing.T) { | ||
tests := []struct { | ||
name string | ||
b byte | ||
position uint8 | ||
expected bool | ||
}{ | ||
{ | ||
name: "bit 0 set", | ||
b: 0b00000001, | ||
position: 0, | ||
expected: true, | ||
}, | ||
{ | ||
name: "bit 7 set", | ||
b: 0b10000000, | ||
position: 7, | ||
expected: true, | ||
}, | ||
{ | ||
name: "bit 2 not set", | ||
b: 0b00000001, | ||
position: 2, | ||
expected: false, | ||
}, | ||
{ | ||
name: "bit out of range", | ||
b: 0b00000001, | ||
position: 8, // Position out of range | ||
expected: false, | ||
}, | ||
} | ||
|
||
for _, tt := range tests { | ||
t.Run(tt.name, func(t *testing.T) { | ||
result := zetabits.IsBitSet(tt.b, tt.position) | ||
require.Equal(t, tt.expected, result) | ||
}) | ||
} | ||
} | ||
|
||
func TestGetBits(t *testing.T) { | ||
tests := []struct { | ||
name string | ||
b byte | ||
mask byte | ||
expected byte | ||
}{ | ||
{ | ||
name: "extract upper 3 bits", | ||
b: 0b11011001, | ||
mask: 0b11100000, | ||
expected: 0b110, | ||
}, | ||
{ | ||
name: "extract middle 3 bits", | ||
b: 0b11011001, | ||
mask: 0b00011100, | ||
expected: 0b110, | ||
}, | ||
{ | ||
name: "extract lower 3 bits", | ||
b: 0b11011001, | ||
mask: 0b00000111, | ||
expected: 0b001, | ||
}, | ||
{ | ||
name: "extract no bits", | ||
b: 0b11011001, | ||
mask: 0b00000000, | ||
expected: 0b000, | ||
}, | ||
{ | ||
name: "extract all bits", | ||
b: 0b11111111, | ||
mask: 0b11111111, | ||
expected: 0b11111111, | ||
}, | ||
} | ||
|
||
for _, tt := range tests { | ||
t.Run(tt.name, func(t *testing.T) { | ||
result := zetabits.GetBits(tt.b, tt.mask) | ||
require.Equal(t, tt.expected, result) | ||
}) | ||
} | ||
} | ||
|
||
func TestSetBits(t *testing.T) { | ||
tests := []struct { | ||
name string | ||
b byte | ||
mask byte | ||
value byte | ||
expected byte | ||
}{ | ||
{ | ||
name: "set upper 3 bits", | ||
b: 0b00100001, | ||
mask: 0b11100000, | ||
value: 0b110, | ||
expected: 0b11000001, | ||
}, | ||
{ | ||
name: "set middle 3 bits", | ||
b: 0b00100001, | ||
mask: 0b00011100, | ||
value: 0b101, | ||
expected: 0b00110101, | ||
}, | ||
{ | ||
name: "set lower 3 bits", | ||
b: 0b11111100, | ||
mask: 0b00000111, | ||
value: 0b101, | ||
expected: 0b11111101, | ||
}, | ||
} | ||
|
||
for _, tt := range tests { | ||
t.Run(tt.name, func(t *testing.T) { | ||
result := zetabits.SetBits(tt.b, tt.mask, tt.value) | ||
require.Equal(t, tt.expected, result) | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
package memo | ||
|
||
// ArgType is the enum for types supported by the codec | ||
type ArgType string | ||
|
||
// Define all the types supported by the codec | ||
const ( | ||
ArgTypeBytes ArgType = "bytes" | ||
ArgTypeString ArgType = "string" | ||
ArgTypeAddress ArgType = "address" | ||
) | ||
|
||
// CodecArg represents a codec argument | ||
type CodecArg struct { | ||
Name string | ||
Type ArgType | ||
Arg interface{} | ||
} | ||
|
||
// NewArg create a new codec argument | ||
func NewArg(name string, argType ArgType, arg interface{}) CodecArg { | ||
return CodecArg{ | ||
Name: name, | ||
Type: argType, | ||
Arg: arg, | ||
} | ||
} | ||
|
||
// ArgReceiver wraps the receiver address in a CodecArg | ||
func ArgReceiver(arg interface{}) CodecArg { | ||
return NewArg("receiver", ArgTypeAddress, arg) | ||
} | ||
|
||
// ArgPayload wraps the payload in a CodecArg | ||
func ArgPayload(arg interface{}) CodecArg { | ||
return NewArg("payload", ArgTypeBytes, arg) | ||
} | ||
|
||
// ArgRevertAddress wraps the revert address in a CodecArg | ||
func ArgRevertAddress(arg interface{}) CodecArg { | ||
return NewArg("revertAddress", ArgTypeString, arg) | ||
} | ||
|
||
// ArgAbortAddress wraps the abort address in a CodecArg | ||
func ArgAbortAddress(arg interface{}) CodecArg { | ||
return NewArg("abortAddress", ArgTypeAddress, arg) | ||
} | ||
|
||
// ArgRevertMessage wraps the revert message in a CodecArg | ||
func ArgRevertMessage(arg interface{}) CodecArg { | ||
return NewArg("revertMessage", ArgTypeBytes, arg) | ||
} |
Oops, something went wrong.