Skip to content

Commit

Permalink
Refactor UnmarshalText and MarshalText
Browse files Browse the repository at this point in the history
  • Loading branch information
thomaspanf committed Jul 23, 2024
1 parent 5895fce commit b669d2e
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 54 deletions.
8 changes: 1 addition & 7 deletions rocketpool-daemon/api/pdao/set-signalling-address.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import (

"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/gorilla/mux"
batch "github.com/rocket-pool/batch-query"
"github.com/rocket-pool/node-manager-core/api/server"
Expand Down Expand Up @@ -110,13 +109,8 @@ func (c *protocolDaoSetSignallingAddressContext) PrepareData(data *types.TxInfoD
return types.ResponseStatus_Error, fmt.Errorf("Voting must be initialized to set a signalling address. Use 'rocketpool pdao initialize-voting' to initialize voting first")
}

decodedSignature, err := hexutil.Decode(c.signature)
if err != nil {
return types.ResponseStatus_Error, fmt.Errorf("Failed to decode hex string: %w", err)
}

eip712Components := new(eip712.EIP712Components)
err = eip712Components.UnmarshalText(decodedSignature)
err := eip712Components.UnmarshalText([]byte(c.signature))
if err != nil {
return types.ResponseStatus_Error, fmt.Errorf("Failed to unmarshal signature: %w", err)
}
Expand Down
31 changes: 21 additions & 10 deletions shared/eip712/eip712.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (

"github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/crypto"
)

Expand All @@ -31,32 +32,42 @@ func (e *EIP712Components) String() string {
// MarshalText should never return an error
panic(err)
}
return fmt.Sprintf("%x", out)

return string(out)
}

// UnmarshalText verifies the length of a decoded EIP-712 signature and assigns the appropriate bytes to R/S/V
// UnmarshalText expects an EIP-712 signature as a []byte, decodes the signature, verifies the length,
// then assigns the appropriate bytes to R/S/V
func (e *EIP712Components) UnmarshalText(inp []byte) error {
if len(inp) != EIP712Length {
return fmt.Errorf("error decoding EIP-712 signature string: invalid length %d bytes (expected %d bytes)", len(inp), EIP712Length)
// Cast to string then decode
signatureString := string(inp)
decodedSignature, err := hexutil.Decode(signatureString)
if err != nil {
return fmt.Errorf("Failed to decode hex string: %w", err)
}

copy(e.R[:], inp[0:32])
copy(e.S[:], inp[32:64])
e.V = inp[64]
if len(decodedSignature) != EIP712Length {
return fmt.Errorf("Failed to unmarshal EIP-712 signature string: invalid length %d bytes (expected %d bytes)", len(decodedSignature), EIP712Length)
}

copy(e.R[:], decodedSignature[0:32])
copy(e.S[:], decodedSignature[32:64])
e.V = decodedSignature[64]

return nil
}

// MarshalText initializes an empty byte slice, copies fields R/S/V into signatureBytes then returns it
// MarshalText initializes an empty byte slice, copies fields R/S/V into signatureBytes,
// then returns the encoded signature as a []byte
func (e *EIP712Components) MarshalText() ([]byte, error) {
signatureBytes := make([]byte, EIP712Length)

copy(signatureBytes[0:32], e.R[:])
copy(signatureBytes[32:64], e.S[:])
signatureBytes[64] = e.V

return signatureBytes, nil
encodedSignature := hexutil.Encode(signatureBytes)

return []byte(encodedSignature), nil
}

// Validate recovers the address of a signer from a message and signature then
Expand Down
46 changes: 9 additions & 37 deletions shared/eip712/eip712_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,36 +5,23 @@ import (
"testing"

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
)

func TestUnmarshalAndMarshal(t *testing.T) {
signature := "0xba283b21f7168e53b082ad552d974591abe0f4db5b7032374abbcdcf09e0eadc2c0530ff4ac1d63e19c1ceca2d14b374c86b6c84f46bbd57747b48c21388c4e71c"
eip712Components := new(EIP712Components)

// Decode string
decoded, err := hexutil.Decode(signature)
if err != nil {
t.Fatalf("Failed to decode hex string: %v", err)
}

err = eip712Components.UnmarshalText(decoded)
err := eip712Components.UnmarshalText([]byte(signature))
if err != nil {
t.Fatalf("Failed to unmarshal signature: %v", err)
}

decoded, err = eip712Components.MarshalText()
if err != nil {
t.Fatalf("Failed to marshal signature: %v", err)
}

// Convert the encoded byte slice back to a hex string
encodedHexSig := hexutil.Encode(decoded)
// Convert the components back to a hex string
encodedHexSig := eip712Components.String()

if encodedHexSig != signature {
t.Fatalf("Expected %s but got %s", signature, decoded)
t.Fatalf("Expected %s but got %s", signature, encodedHexSig)
}

}

func TestUnmarshalInvalid712Hex(t *testing.T) {
Expand Down Expand Up @@ -62,18 +49,12 @@ func TestUnmarshalInvalidLength(t *testing.T) {
invalidLengthSignature := "0xba283b21f7168e53b082ad552d974591abe0f4db5b7032374abbcdcf09e0eadc" // 64 characters (32 bytes)
eip712Components := new(EIP712Components)

// Decode string
decoded, err := hexutil.Decode(invalidLengthSignature)
if err != nil {
t.Fatalf("Failed to decode hex string: %v", err)
}

err = eip712Components.UnmarshalText(decoded)
err := eip712Components.UnmarshalText([]byte(invalidLengthSignature))
if err == nil {
t.Fatal("Expected error for signature with invalid length but got none")
}

expectedErrMsg := fmt.Sprintf("error decoding EIP-712 signature string: invalid length %d bytes (expected %d bytes)", 32, EIP712Length)
expectedErrMsg := fmt.Sprintf("Failed to unmarshal EIP-712 signature string: invalid length %d bytes (expected %d bytes)", 32, EIP712Length)
if err.Error() != expectedErrMsg {
t.Fatalf("Expected error message: '%s' but got: '%s'", expectedErrMsg, err.Error())
}
Expand All @@ -82,13 +63,9 @@ func TestUnmarshalInvalidLength(t *testing.T) {
func TestValidateSuccess(t *testing.T) {
// Create a valid EIP-712 signature
signature := "0xba283b21f7168e53b082ad552d974591abe0f4db5b7032374abbcdcf09e0eadc2c0530ff4ac1d63e19c1ceca2d14b374c86b6c84f46bbd57747b48c21388c4e71c"
decoded, err := hexutil.Decode(signature)
if err != nil {
t.Fatalf("Failed to decode hex string: %v", err)
}

eip712Components := new(EIP712Components)
err = eip712Components.UnmarshalText(decoded)
err := eip712Components.UnmarshalText([]byte(signature))
if err != nil {
t.Fatalf("Failed to unmarshal signature: %v", err)
}
Expand All @@ -110,9 +87,8 @@ func TestValidateSuccess(t *testing.T) {
func TestValidateInvalidSignature(t *testing.T) {
// Create an invalid EIP-712 signature
invalidSignature := "0xba283b21f7168e53b082ad552d974591abe0f4db5b7032374abbcdcf09e0eadc2c0530ff4ac1d63e19c1ceca2d14b374c86b6c84f46bbd57747b48c21388c4e71f" // Last byte is invalid
decoded, _ := hexutil.Decode(invalidSignature)
eip712Components := new(EIP712Components)
err := eip712Components.UnmarshalText(decoded)
err := eip712Components.UnmarshalText([]byte(invalidSignature))
if err != nil {
t.Fatalf("Failed to unmarshal signature: %v", err)
}
Expand All @@ -133,13 +109,9 @@ func TestValidateInvalidSignature(t *testing.T) {
func TestValidateSignerMismatch(t *testing.T) {
// Create a valid EIP-712 signature
signature := "0xba283b21f7168e53b082ad552d974591abe0f4db5b7032374abbcdcf09e0eadc2c0530ff4ac1d63e19c1ceca2d14b374c86b6c84f46bbd57747b48c21388c4e71c"
decoded, err := hexutil.Decode(signature)
if err != nil {
t.Fatalf("Failed to decode hex string: %v", err)
}

eip712Components := new(EIP712Components)
err = eip712Components.UnmarshalText(decoded)
err := eip712Components.UnmarshalText([]byte(signature))
if err != nil {
t.Fatalf("Failed to unmarshal signature: %v", err)
}
Expand Down

0 comments on commit b669d2e

Please sign in to comment.