diff --git a/node/hack/query/send_req.go b/node/hack/query/send_req.go index 6dd95de0d2..08518005fb 100644 --- a/node/hack/query/send_req.go +++ b/node/hack/query/send_req.go @@ -348,7 +348,9 @@ func sendQueryAndGetRsp(queryRequest *query.QueryRequest, sk *ecdsa.PrivateKey, var isMatchingResponse bool switch m := msg.Message.(type) { case *gossipv1.GossipMessage_SignedQueryResponse: - logger.Info("query response received", zap.Any("response", m.SignedQueryResponse)) + logger.Info("query response received", zap.Any("response", m.SignedQueryResponse), + zap.String("responseBytes", hexutil.Encode(m.SignedQueryResponse.QueryResponse)), + zap.String("sigBytes", hexutil.Encode(m.SignedQueryResponse.Signature))) var response query.QueryResponsePublication err := response.Unmarshal(m.SignedQueryResponse.QueryResponse) if err != nil { diff --git a/node/pkg/query/request.go b/node/pkg/query/request.go index 79b25361a3..b2c6f33279 100644 --- a/node/pkg/query/request.go +++ b/node/pkg/query/request.go @@ -112,6 +112,7 @@ func (queryRequest *QueryRequest) Marshal() ([]byte, error) { buf := new(bytes.Buffer) + vaa.MustWrite(buf, binary.BigEndian, uint8(1)) // version vaa.MustWrite(buf, binary.BigEndian, queryRequest.Nonce) // uint32 vaa.MustWrite(buf, binary.BigEndian, uint8(len(queryRequest.PerChainQueries))) @@ -134,6 +135,15 @@ func (queryRequest *QueryRequest) Unmarshal(data []byte) error { // UnmarshalFromReader deserializes the binary representation of a query request from an existing reader func (queryRequest *QueryRequest) UnmarshalFromReader(reader *bytes.Reader) error { + var version uint8 + if err := binary.Read(reader, binary.BigEndian, &version); err != nil { + return fmt.Errorf("failed to read message version: %w", err) + } + + if version != 1 { + return fmt.Errorf("unsupported message version: %d", version) + } + if err := binary.Read(reader, binary.BigEndian, &queryRequest.Nonce); err != nil { return fmt.Errorf("failed to read request nonce: %w", err) } @@ -207,6 +217,13 @@ func (perChainQuery *PerChainQueryRequest) Marshal() ([]byte, error) { if err != nil { return nil, err } + + // Write the length of the query to facilitate on-chain parsing. + if len(queryBuf) > math.MaxUint32 { + return nil, fmt.Errorf("query too long") + } + vaa.MustWrite(buf, binary.BigEndian, uint32(len(queryBuf))) + buf.Write(queryBuf) return buf.Bytes(), nil } @@ -233,6 +250,12 @@ func (perChainQuery *PerChainQueryRequest) UnmarshalFromReader(reader *bytes.Rea return err } + // Skip the query length. + var queryLength uint32 + if err := binary.Read(reader, binary.BigEndian, &queryLength); err != nil { + return fmt.Errorf("failed to read query length: %w", err) + } + switch queryType { case EthCallQueryRequestType: q := EthCallQueryRequest{} diff --git a/node/pkg/query/response.go b/node/pkg/query/response.go index b644ea9633..326195b981 100644 --- a/node/pkg/query/response.go +++ b/node/pkg/query/response.go @@ -97,12 +97,21 @@ func (msg *QueryResponsePublication) Marshal() ([]byte, error) { buf := new(bytes.Buffer) + vaa.MustWrite(buf, binary.BigEndian, uint8(1)) // version + // Source // TODO: support writing off-chain and on-chain requests // Here, unset represents an off-chain request vaa.MustWrite(buf, binary.BigEndian, vaa.ChainIDUnset) buf.Write(msg.Request.Signature[:]) + + // Write the length of the request to facilitate on-chain parsing. + if len(msg.Request.QueryRequest) > math.MaxUint32 { + return nil, fmt.Errorf("request too long") + } + vaa.MustWrite(buf, binary.BigEndian, uint32(len(msg.Request.QueryRequest))) + buf.Write(msg.Request.QueryRequest) // Per chain responses @@ -122,6 +131,15 @@ func (msg *QueryResponsePublication) Marshal() ([]byte, error) { func (msg *QueryResponsePublication) Unmarshal(data []byte) error { reader := bytes.NewReader(data[:]) + var version uint8 + if err := binary.Read(reader, binary.BigEndian, &version); err != nil { + return fmt.Errorf("failed to read message version: %w", err) + } + + if version != 1 { + return fmt.Errorf("unsupported message version: %d", version) + } + // Request requestChain := vaa.ChainID(0) if err := binary.Read(reader, binary.BigEndian, &requestChain); err != nil { @@ -139,6 +157,12 @@ func (msg *QueryResponsePublication) Unmarshal(data []byte) error { } signedQueryRequest.Signature = signature[:] + // Skip the query length. + queryRequestLen := uint32(0) + if err := binary.Read(reader, binary.BigEndian, &queryRequestLen); err != nil { + return fmt.Errorf("failed to read length of query request: %w", err) + } + queryRequest := QueryRequest{} err := queryRequest.UnmarshalFromReader(reader) if err != nil { @@ -260,6 +284,12 @@ func (perChainResponse *PerChainQueryResponse) Marshal() ([]byte, error) { if err != nil { return nil, err } + + // Write the length of the response to facilitate on-chain parsing. + if len(respBuf) > math.MaxUint32 { + return nil, fmt.Errorf("response is too long") + } + vaa.MustWrite(buf, binary.BigEndian, uint32(len(respBuf))) buf.Write(respBuf) return buf.Bytes(), nil } @@ -286,6 +316,12 @@ func (perChainResponse *PerChainQueryResponse) UnmarshalFromReader(reader *bytes return err } + // Skip the response length. + var respLength uint32 + if err := binary.Read(reader, binary.BigEndian, &respLength); err != nil { + return fmt.Errorf("failed to read response length: %w", err) + } + switch queryType { case EthCallQueryRequestType: r := EthCallQueryResponse{}