Skip to content
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

API endpoint for manually relaying warp message #327

Merged
merged 62 commits into from
Jul 3, 2024
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
Show all changes
62 commits
Select commit Hold shift + click to select a range
315049b
Refactor application relayers
geoff-vball Jun 7, 2024
6254a6c
wip
geoff-vball Jun 7, 2024
021269f
Merge branch 'main' into gstuart/api-relay
geoff-vball Jun 7, 2024
ccd4ef5
Functions for relaying message from blockchain ID, warp message ID, a…
geoff-vball Jun 10, 2024
a6fb5cf
lint
geoff-vball Jun 10, 2024
d67e619
Fixes
geoff-vball Jun 10, 2024
96ecc68
WIP
geoff-vball Jun 11, 2024
7af931b
Merge branch 'main' into gstuart/api-relay
geoff-vball Jun 11, 2024
7703831
Add test for API
geoff-vball Jun 11, 2024
eb3e4a0
lint
geoff-vball Jun 11, 2024
d4042c6
Fix test
geoff-vball Jun 11, 2024
9081636
Fix test
geoff-vball Jun 11, 2024
2cc6522
Merge branch 'main' into gstuart/api-relay
geoff-vball Jun 12, 2024
818f650
small fixes
geoff-vball Jun 12, 2024
8325943
Add error messages
geoff-vball Jun 14, 2024
23a9b2a
Update relayer/relay_message_api_handler.go
geoff-vball Jun 14, 2024
a58649a
Merge branch 'main' into gstuart/api-relay
geoff-vball Jun 18, 2024
6dc2441
Review fixes
geoff-vball Jun 18, 2024
177c15f
Update main/main.go
geoff-vball Jun 18, 2024
cf3c779
Update main/main.go
geoff-vball Jun 18, 2024
664cd31
Update main/main.go
geoff-vball Jun 18, 2024
0e65039
Update main/main.go
geoff-vball Jun 18, 2024
fec26c6
Fix typo
geoff-vball Jun 18, 2024
56f4c38
Add txhash to SendMessage
geoff-vball Jun 19, 2024
7863281
Fix
geoff-vball Jun 20, 2024
039e5d7
Add endpoint for manual warp messages
geoff-vball Jun 20, 2024
e72a34b
lint
geoff-vball Jun 20, 2024
6322ac8
wip
geoff-vball Jun 20, 2024
6ed13b4
lint
geoff-vball Jun 20, 2024
d2b2ac5
Merge branch 'main' into gstuart/api-relay
geoff-vball Jun 25, 2024
358894b
Pass MessageCoordinator as param
geoff-vball Jun 25, 2024
3a67da1
Lint
geoff-vball Jun 25, 2024
53516b5
Fix
geoff-vball Jun 25, 2024
93e9a75
Refactor API
geoff-vball Jun 25, 2024
daac2cd
Add api folder
geoff-vball Jun 25, 2024
45657f7
Make message coordinator fields private
geoff-vball Jun 25, 2024
a6ed77a
Merge branch 'main' into gstuart/api-relay
geoff-vball Jun 26, 2024
a77d244
lint
geoff-vball Jun 26, 2024
14810a2
Remove unneeded fields
geoff-vball Jun 26, 2024
59ec4d4
Update main/main.go
geoff-vball Jun 26, 2024
214abb8
Update main/main.go
geoff-vball Jun 26, 2024
a39bdcf
Update relayer/message_coordinator.go
geoff-vball Jun 27, 2024
74fd902
Update api/relay_message.go
geoff-vball Jun 27, 2024
cdd5635
Update api/relay_message.go
geoff-vball Jun 27, 2024
f6e8e9c
Review fixes
geoff-vball Jun 27, 2024
753bf5b
Review fixes
geoff-vball Jun 27, 2024
1d823f5
fix
geoff-vball Jun 27, 2024
dba6fbe
Documentation
geoff-vball Jun 27, 2024
3ae8bf4
Fix test
geoff-vball Jun 27, 2024
7694982
Simplify API
geoff-vball Jun 27, 2024
570953c
Update api/relay_message.go
geoff-vball Jul 2, 2024
24e7694
Update README.md
geoff-vball Jul 2, 2024
abfb84e
Update api/relay_message.go
geoff-vball Jul 2, 2024
6995b64
Update README.md
geoff-vball Jul 2, 2024
713a80a
Update README.md
geoff-vball Jul 2, 2024
a68f7a4
Update README.md
geoff-vball Jul 2, 2024
4ade921
Update README.md
geoff-vball Jul 2, 2024
5468239
Review fixes
geoff-vball Jul 2, 2024
349e6c3
Fix test
geoff-vball Jul 2, 2024
343651b
review fixes
geoff-vball Jul 2, 2024
b4376e2
review fixes
geoff-vball Jul 2, 2024
f33e56f
Capitalize log messages
geoff-vball Jul 2, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -319,12 +319,12 @@ The relayer consists of the following components:
### API

#### `/relay`
- Used to manually relay a warp message. The body of the request must contain the following JSON:
- Used to manually relay a Warp message. The body of the request must contain the following JSON:
```json
{
"blockchain-id": "<cb58-encoding of blockchain ID>",
"message-id": "<Hex encoding of warp message ID>",
"block-num": <Integer representation of the block number that the message was sent in>
"message-id": "<Hex encoding of Warp message ID>",
"block-num": "<Integer representation of the block number that the message was sent in>"
}
```
- If successful, the endpoint will return the following JSON:
Expand All @@ -338,14 +338,14 @@ The relayer consists of the following components:
- Used to manually relay a warp message. The body of the request must contain the following JSON:
```json
{
"unsigned-message-bytes": "<byte array containing the unsigned warp message>",
"unsigned-message-bytes": "<Hex encoded byte array containing the unsigned warp message>",
"source-address": "<Hex encoding of address that sent the warp message>"
}
```
- If successful, the endpoint will return the following JSON:
```json
{
"transaction-hash": "<Transaction hash that includes the delivered warp message>",
"transaction-hash": "<Transaction hash that includes the delivered Warp message>",
}
```

Expand All @@ -358,7 +358,7 @@ The relayer consists of the following components:
"relayers-all": {
"status": "down",
"timestamp": "2024-06-01T05:06:07.685522Z",
"error": "<List of cb-58 encoded IDs for unhealth relayers>"
"error": "<List of cb-58 encoded IDs for unhealthy relayers>"
}
}
}
Expand Down
49 changes: 35 additions & 14 deletions api/relay_message.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,13 @@ import (
"math/big"
"net/http"

"github.com/ava-labs/avalanchego/ids"
"github.com/ava-labs/avalanchego/utils/logging"
"github.com/ava-labs/awm-relayer/relayer"
"github.com/ava-labs/awm-relayer/types"
relayerTypes "github.com/ava-labs/awm-relayer/types"

"github.com/ava-labs/avalanchego/ids"
"github.com/ethereum/go-ethereum/common"
"go.uber.org/zap"
)

const (
Expand All @@ -21,7 +22,7 @@ const (
type RelayMessageRequest struct {
// Required. cb58 encoding of the source blockchain ID for the message
BlockchainID string `json:"blockchain-id"`
// Required. Hex encoding of the warp message ID
// Required. cb58 encoding of the warp message ID
MessageID string `json:"message-id"`
// Required. Integer representation of the block number that the message was sent in
BlockNum string `json:"block-num"`
geoff-vball marked this conversation as resolved.
Show resolved Hide resolved
Expand All @@ -38,25 +39,27 @@ type ManualWarpMessageRequest struct {
SourceAddress string `json:"source-address"`
}

func HandleRelayMessage(messageCoordinator *relayer.MessageCoordinator) {
http.Handle(RelayAPIPath, relayAPIHandler(messageCoordinator))
func HandleRelayMessage(logger logging.Logger, messageCoordinator *relayer.MessageCoordinator) {
http.Handle(RelayAPIPath, relayAPIHandler(logger, messageCoordinator))
}

func HandleRelay(messageCoordinator *relayer.MessageCoordinator) {
http.Handle(RelayMessageAPIPath, relayMessageAPIHandler(messageCoordinator))
func HandleRelay(logger logging.Logger, messageCoordinator *relayer.MessageCoordinator) {
http.Handle(RelayMessageAPIPath, relayMessageAPIHandler(logger, messageCoordinator))
}

func relayMessageAPIHandler(messageCoordinator *relayer.MessageCoordinator) http.Handler {
func relayMessageAPIHandler(logger logging.Logger, messageCoordinator *relayer.MessageCoordinator) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
var req ManualWarpMessageRequest
err := json.NewDecoder(r.Body).Decode(&req)
if err != nil {
logger.Warn("could not decode request body")
http.Error(w, err.Error(), http.StatusBadRequest)
return
}

unsignedMessage, err := types.UnpackWarpMessage(req.UnsignedMessageBytes)
if err != nil {
logger.Warn("error unpacking warp message", zap.Error(err))
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
Expand All @@ -68,6 +71,7 @@ func relayMessageAPIHandler(messageCoordinator *relayer.MessageCoordinator) http

txHash, err := messageCoordinator.ProcessWarpMessage(warpMessageInfo)
if err != nil {
logger.Error("error processing message", zap.Error(err))
http.Error(w, "error processing message: "+err.Error(), http.StatusInternalServerError)
return
}
Expand All @@ -78,37 +82,50 @@ func relayMessageAPIHandler(messageCoordinator *relayer.MessageCoordinator) http
},
)
if err != nil {
http.Error(w, "error writing response: "+err.Error(), http.StatusInternalServerError)
logger.Error("error marshaling response", zap.Error(err))
http.Error(w, "error marshaling response: "+err.Error(), http.StatusInternalServerError)
return
}

_, _ = w.Write(resp)
_, err = w.Write(resp)
if err != nil {
logger.Error("error writing response", zap.Error(err))
}
})
}

func relayAPIHandler(messageCoordinator *relayer.MessageCoordinator) http.Handler {
func relayAPIHandler(logger logging.Logger, messageCoordinator *relayer.MessageCoordinator) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
var req RelayMessageRequest
err := json.NewDecoder(r.Body).Decode(&req)
if err != nil {
logger.Warn("could not decode request body")
http.Error(w, err.Error(), http.StatusBadRequest)
return
}

blockchainID, err := ids.FromString(req.BlockchainID)
if err != nil {
logger.Warn("invalid blockchainID", zap.String("blockchainID", req.BlockchainID))
http.Error(w, "invalid blockchainID: "+err.Error(), http.StatusBadRequest)
return
}
messageID := common.HexToHash(req.MessageID)
messageID, err := ids.FromString(req.MessageID)
if err != nil {
logger.Warn("invalid messageID", zap.String("messageID", req.MessageID))
http.Error(w, "invalid messageID: "+err.Error(), http.StatusBadRequest)
return
}
blockNum, ok := new(big.Int).SetString(req.BlockNum, 10)
if !ok {
logger.Warn("invalid blockNum", zap.String("blockNum", req.BlockNum))
http.Error(w, "invalid blockNum", http.StatusBadRequest)
return
}

txHash, err := messageCoordinator.ProcessMessageID(blockchainID, messageID, blockNum)
if err != nil {
logger.Error("error processing message", zap.Error(err))
http.Error(w, "error processing message: "+err.Error(), http.StatusInternalServerError)
return
}
Expand All @@ -119,10 +136,14 @@ func relayAPIHandler(messageCoordinator *relayer.MessageCoordinator) http.Handle
},
)
if err != nil {
http.Error(w, "error writing response: "+err.Error(), http.StatusInternalServerError)
logger.Error("error marshalling response", zap.Error(err))
http.Error(w, "error marshalling response: "+err.Error(), http.StatusInternalServerError)
return
}

_, _ = w.Write(resp)
_, err = w.Write(resp)
if err != nil {
logger.Error("error writing response", zap.Error(err))
}
})
}
2 changes: 1 addition & 1 deletion config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ func DisplayUsageText() {

// Validates the configuration
// Does not modify the public fields as derived from the configuration passed to the application,
// but does initialize private fields available through getters
// but does initialize private fields available through getters.
func (c *Config) Validate() error {
if len(c.SourceBlockchains) == 0 {
return errors.New("relayer not configured to relay from any subnets. A list of source subnets must be provided in the configuration file")
Expand Down
11 changes: 5 additions & 6 deletions main/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,6 @@ import (
"os"
"strings"

"github.com/ava-labs/awm-relayer/messages"
offchainregistry "github.com/ava-labs/awm-relayer/messages/off-chain-registry"
"github.com/ava-labs/awm-relayer/messages/teleporter"

"github.com/ava-labs/avalanchego/api/metrics"
"github.com/ava-labs/avalanchego/ids"
"github.com/ava-labs/avalanchego/message"
Expand All @@ -23,6 +19,9 @@ import (
"github.com/ava-labs/awm-relayer/api"
"github.com/ava-labs/awm-relayer/config"
"github.com/ava-labs/awm-relayer/database"
"github.com/ava-labs/awm-relayer/messages"
offchainregistry "github.com/ava-labs/awm-relayer/messages/off-chain-registry"
"github.com/ava-labs/awm-relayer/messages/teleporter"
"github.com/ava-labs/awm-relayer/peers"
"github.com/ava-labs/awm-relayer/relayer"
"github.com/ava-labs/awm-relayer/utils"
Expand Down Expand Up @@ -202,8 +201,8 @@ func main() {

// Each Listener goroutine will have an atomic bool that it can set to false to indicate an unrecoverable error
api.HandleHealthCheck(relayerHealth)
geoff-vball marked this conversation as resolved.
Show resolved Hide resolved
api.HandleRelay(messageCoordinator)
api.HandleRelayMessage(messageCoordinator)
api.HandleRelay(logger, messageCoordinator)
api.HandleRelayMessage(logger, messageCoordinator)

// start the health check server
go func() {
Expand Down
8 changes: 4 additions & 4 deletions relayer/message_coordinator.go
Original file line number Diff line number Diff line change
Expand Up @@ -186,14 +186,14 @@ func (mc *MessageCoordinator) ProcessWarpMessage(warpMessage *relayerTypes.WarpM
return appRelayer.ProcessMessage(handler)
}

func (mc *MessageCoordinator) ProcessMessageID(blockchainID ids.ID, messageID common.Hash, blockNum *big.Int) (common.Hash, error) {
func (mc *MessageCoordinator) ProcessMessageID(blockchainID ids.ID, messageID ids.ID, blockNum *big.Int) (common.Hash, error) {
ethClient, ok := mc.sourceClients[blockchainID]
if !ok {
mc.logger.Error("Source client not found", zap.String("blockchainID", blockchainID.String()))
return common.Hash{}, fmt.Errorf("source client not set for blockchain: %s", blockchainID.String())
}

warpMessage, err := FetchWarpMessageFromID(ethClient, messageID, blockNum)
warpMessage, err := FetchWarpMessage(ethClient, messageID, blockNum)
if err != nil {
mc.logger.Error("Failed to fetch warp from blockchain", zap.String("blockchainID", blockchainID.String()), zap.Error(err))
return common.Hash{}, fmt.Errorf("could not fetch warp message from ID: %w", err)
Expand Down Expand Up @@ -241,9 +241,9 @@ func (mc *MessageCoordinator) ProcessBlock(blockHeader *types.Header, ethClient
}
}

func FetchWarpMessageFromID(ethClient ethclient.Client, warpID common.Hash, blockNum *big.Int) (*relayerTypes.WarpMessageInfo, error) {
func FetchWarpMessage(ethClient ethclient.Client, warpID ids.ID, blockNum *big.Int) (*relayerTypes.WarpMessageInfo, error) {
logs, err := ethClient.FilterLogs(context.Background(), interfaces.FilterQuery{
Topics: [][]common.Hash{{relayerTypes.WarpPrecompileLogFilter}, nil, {warpID}},
Topics: [][]common.Hash{{relayerTypes.WarpPrecompileLogFilter}, nil, {common.Hash(warpID)}},
Addresses: []common.Address{warp.ContractAddress},
FromBlock: blockNum,
ToBlock: blockNum,
Expand Down
2 changes: 1 addition & 1 deletion tests/relay_message_api.go
geoff-vball marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ func RelayMessageAPI(network interfaces.LocalNetwork) {

reqBody := api.RelayMessageRequest{
BlockchainID: subnetAInfo.BlockchainID.String(),
MessageID: warpMessage.ID().Hex(),
MessageID: warpMessage.ID().String(),
BlockNum: receipt.BlockNumber.String(),
}

Expand Down