-
Notifications
You must be signed in to change notification settings - Fork 19
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
integrate ACP-118 #408
integrate ACP-118 #408
Changes from 10 commits
c46fc41
650c987
a9c7768
9db9153
557262a
b56e5d3
adb8fb2
f399cff
fa3dbc0
c771ca9
fa60e03
0108081
cf689e5
b186d1c
95797af
b8735b0
0be46eb
e3cefff
79132a1
b5cff9e
2f337c9
bce634d
811c97a
30a718d
9f81123
e9eea93
29cac30
7fd79dc
58af3de
e1edf7e
70666da
77262bc
ec5b830
0498f4a
440a52d
91c5016
47cfef6
b87bcc1
5852f6c
7f9488c
0648123
ae43d72
ca06934
6cd8245
b04df21
3d7707d
2ba7b61
576a375
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -16,17 +16,17 @@ import ( | |
"github.com/ava-labs/avalanchego/ids" | ||
"github.com/ava-labs/avalanchego/message" | ||
"github.com/ava-labs/avalanchego/proto/pb/p2p" | ||
"github.com/ava-labs/avalanchego/proto/pb/sdk" | ||
"github.com/ava-labs/avalanchego/subnets" | ||
"github.com/ava-labs/avalanchego/utils/constants" | ||
"github.com/ava-labs/avalanchego/utils/crypto/bls" | ||
"github.com/ava-labs/avalanchego/utils/logging" | ||
"github.com/ava-labs/avalanchego/utils/set" | ||
avalancheWarp "github.com/ava-labs/avalanchego/vms/platformvm/warp" | ||
"github.com/ava-labs/awm-relayer/peers" | ||
"github.com/ava-labs/awm-relayer/utils" | ||
coreEthMsg "github.com/ava-labs/coreth/plugin/evm/message" | ||
msg "github.com/ava-labs/subnet-evm/plugin/evm/message" | ||
"go.uber.org/zap" | ||
"google.golang.org/protobuf/proto" | ||
) | ||
|
||
type blsSignatureBuf [bls.SignatureLen]byte | ||
|
@@ -40,9 +40,6 @@ const ( | |
) | ||
|
||
var ( | ||
codec = msg.Codec | ||
coreEthCodec = coreEthMsg.Codec | ||
|
||
// Errors | ||
errNotEnoughSignatures = errors.New("failed to collect a threshold of signatures") | ||
errNotEnoughConnectedStake = errors.New("failed to connect to a threshold of stake") | ||
|
@@ -76,6 +73,7 @@ func NewSignatureAggregator( | |
|
||
func (s *SignatureAggregator) CreateSignedMessage( | ||
unsignedMessage *avalancheWarp.UnsignedMessage, | ||
justification []byte, | ||
inputSigningSubnet ids.ID, | ||
quorumPercentage uint64, | ||
) (*avalancheWarp.Message, error) { | ||
|
@@ -122,19 +120,9 @@ func (s *SignatureAggregator) CreateSignedMessage( | |
return nil, errNotEnoughConnectedStake | ||
} | ||
|
||
// TODO: remove this special handling and replace with ACP-118 interface once available | ||
var reqBytes []byte | ||
if sourceSubnet == constants.PrimaryNetworkID { | ||
req := coreEthMsg.MessageSignatureRequest{ | ||
MessageID: unsignedMessage.ID(), | ||
} | ||
reqBytes, err = coreEthMsg.RequestToBytes(coreEthCodec, req) | ||
} else { | ||
req := msg.MessageSignatureRequest{ | ||
MessageID: unsignedMessage.ID(), | ||
} | ||
reqBytes, err = msg.RequestToBytes(codec, req) | ||
} | ||
reqBytes, err := proto.Marshal( | ||
&sdk.SignatureRequest{Message: unsignedMessage.Bytes()}, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We should add justification bytes here as well as the API. In the API they should be hex encoded and since their meaning is VM specific we don't need to do any processing to them either just like with the message. We should only pass the non-zero fields since the ACP-118 spec but in the API layer we should do validation that at least one of I would also rename our API to use There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. addressed in 557262a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This isn't done yet. I added the justification everywhere (in the API) except for right here 😅 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. last piece addressed in 29cac30 |
||
) | ||
if err != nil { | ||
msg := "Failed to marshal request bytes" | ||
s.logger.Error( | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -24,8 +24,11 @@ const ( | |
|
||
// Defines a request interface for signature aggregation for a raw unsigned message. | ||
type AggregateSignatureRequest struct { | ||
// Required: either Message or Justification must be provided | ||
// Required. hex-encoded message, optionally prefixed with "0x". | ||
feuGeneA marked this conversation as resolved.
Show resolved
Hide resolved
|
||
UnsignedMessage string `json:"unsigned-message"` | ||
Message string `json:"message"` | ||
// hex-encoded justification, optionally prefixed with "0x". | ||
Justification string `json:"justification"` | ||
// Optional hex or cb58 encoded signing subnet ID. If omitted will default to the subnetID of the source blockchain | ||
SigningSubnetID string `json:"signing-subnet-id"` | ||
// Optional. Integer from 0 to 100 representing the percentage of the quorum that is required to sign the message | ||
|
@@ -65,6 +68,15 @@ func writeJSONError( | |
} | ||
} | ||
|
||
func isEmptyOrZeroes(bytes []byte) bool { | ||
for _, b := range bytes { | ||
if b != 0 { | ||
return false | ||
} | ||
} | ||
return true | ||
} | ||
|
||
func signatureAggregationAPIHandler(logger logging.Logger, aggregator *aggregator.SignatureAggregator) http.Handler { | ||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { | ||
var req AggregateSignatureRequest | ||
|
@@ -77,25 +89,48 @@ func signatureAggregationAPIHandler(logger logging.Logger, aggregator *aggregato | |
} | ||
var decodedMessage []byte | ||
decodedMessage, err = hex.DecodeString( | ||
strings.TrimPrefix(req.UnsignedMessage, "0x"), | ||
strings.TrimPrefix(req.Message, "0x"), | ||
) | ||
if err != nil { | ||
msg := "Could not decode message" | ||
logger.Warn( | ||
msg, | ||
zap.String("msg", req.UnsignedMessage), | ||
zap.String("msg", req.Message), | ||
zap.Error(err), | ||
) | ||
writeJSONError(logger, w, msg) | ||
return | ||
} | ||
unsignedMessage, err := types.UnpackWarpMessage(decodedMessage) | ||
message, err := types.UnpackWarpMessage(decodedMessage) | ||
if err != nil { | ||
msg := "Error unpacking warp message" | ||
logger.Warn(msg, zap.Error(err)) | ||
writeJSONError(logger, w, msg) | ||
return | ||
} | ||
|
||
justification, err := hex.DecodeString( | ||
strings.TrimPrefix(req.Justification, "0x"), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we have There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This doesn't decode to an There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
) | ||
if err != nil { | ||
msg := "Could not decode justification" | ||
logger.Warn( | ||
msg, | ||
zap.String("justification", req.Justification), | ||
zap.Error(err), | ||
) | ||
writeJSONError(logger, w, msg) | ||
return | ||
} | ||
|
||
if isEmptyOrZeroes(message.Bytes()) || isEmptyOrZeroes(justification) { | ||
writeJSONError( | ||
logger, | ||
w, | ||
"Must provide either message or justification", | ||
) | ||
} | ||
|
||
quorumPercentage := req.QuorumPercentage | ||
if quorumPercentage == 0 { | ||
quorumPercentage = QuorumPercentage | ||
|
@@ -122,7 +157,8 @@ func signatureAggregationAPIHandler(logger logging.Logger, aggregator *aggregato | |
} | ||
|
||
signedMessage, err := aggregator.CreateSignedMessage( | ||
unsignedMessage, | ||
message, | ||
justification, | ||
signingSubnetID, | ||
quorumPercentage, | ||
) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
wasn't too clear to me what this
justification
field is meant for, and why it's always emptyThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Justification field is part of ACP-118 It's unused for now but is meant to be potentially extra data that would explain why the data in the message field should be signed. It's unused for now though so that's why it's always empty
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a reason we can't just pass in
nil
here? Allocating a slice that's never assigned to seems odd.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
addressed in 6cd8245