From 417e8d9876f41125c131da3ef123a2b5aeffe7c8 Mon Sep 17 00:00:00 2001 From: claravanstaden Date: Thu, 10 Oct 2024 16:16:25 +0200 Subject: [PATCH 01/19] ofac --- relayer/config/config.go | 12 +++ relayer/ofac/ofac.go | 81 +++++++++++++++++++ relayer/relays/execution/config.go | 13 ++- relayer/relays/execution/main.go | 2 + relayer/relays/parachain/config.go | 11 ++- web/packages/test/config/execution-relay.json | 4 + web/packages/test/config/parachain-relay.json | 4 + 7 files changed, 120 insertions(+), 7 deletions(-) create mode 100644 relayer/ofac/ofac.go diff --git a/relayer/config/config.go b/relayer/config/config.go index 71a19a1caa..ea1de25fdc 100644 --- a/relayer/config/config.go +++ b/relayer/config/config.go @@ -18,6 +18,11 @@ type EthereumConfig struct { GasLimit uint64 `mapstructure:"gas-limit"` } +type OFACConfig struct { + Enabled bool `mapstructure:"enabled"` + ApiKey string `mapstructure:"apiKey"` +} + func (p ParachainConfig) Validate() error { if p.Endpoint == "" { return errors.New("[endpoint] is not set") @@ -41,3 +46,10 @@ func (p PolkadotConfig) Validate() error { } return nil } + +func (o OFACConfig) Validate() error { + if o.Enabled && o.ApiKey == "" { + return errors.New("OFAC is enabled but no [apiKey] set") + } + return nil +} diff --git a/relayer/ofac/ofac.go b/relayer/ofac/ofac.go new file mode 100644 index 0000000000..1485d68199 --- /dev/null +++ b/relayer/ofac/ofac.go @@ -0,0 +1,81 @@ +package ofac + +import ( + "encoding/json" + "fmt" + "io" + "net/http" +) + +type OFAC struct { + enabled bool + apiKey string +} + +type Response struct { + Identifications []struct { + Category string `json:"category"` + Name string `json:"name"` + Description string `json:"description"` + URL string `json:"url"` + } `json:"identifications"` +} + +func New(enabled bool, apiKey string) OFAC { + return OFAC{enabled, apiKey} +} + +func (o OFAC) IsBanned(source, destination string) (bool, error) { + if !o.enabled { + return false, nil + } + + isSourcedBanned, err := o.checkOFAC(source) + if err != nil { + return true, err + } + if isSourcedBanned { + return true, nil + } + + isDestinationBanned, err := o.checkOFAC(destination) + if err != nil { + return true, err + } + if isDestinationBanned { + return true, nil + } + + return false, nil +} + +func (o OFAC) checkOFAC(address string) (bool, error) { + client := &http.Client{} + + req, err := http.NewRequest("GET", fmt.Sprintf("https://public.chainalysis.com/api/v1/address/%s", address), nil) + if err != nil { + return true, err + } + + req.Header.Add("Accept", "application/json") + req.Header.Add("X-API-Key", o.apiKey) + + resp, err := client.Do(req) + if err != nil { + return true, err + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return true, err + } + + var response Response + err = json.Unmarshal(body, &response) + if err != nil { + return true, err + } + + return len(response.Identifications) > 0, nil +} diff --git a/relayer/relays/execution/config.go b/relayer/relays/execution/config.go index 70dd1d5cae..cdd8e57ee8 100644 --- a/relayer/relays/execution/config.go +++ b/relayer/relays/execution/config.go @@ -9,10 +9,11 @@ import ( ) type Config struct { - Source SourceConfig `mapstructure:"source"` - Sink SinkConfig `mapstructure:"sink"` - InstantVerification bool `mapstructure:"instantVerification"` - Schedule ScheduleConfig `mapstructure:"schedule"` + Source SourceConfig `mapstructure:"source"` + Sink SinkConfig `mapstructure:"sink"` + InstantVerification bool `mapstructure:"instantVerification"` + Schedule ScheduleConfig `mapstructure:"schedule"` + OFAC config.OFACConfig `mapstructure:"ofac"` } type ScheduleConfig struct { @@ -70,5 +71,9 @@ func (c Config) Validate() error { if err != nil { return fmt.Errorf("schedule config: %w", err) } + err = c.OFAC.Validate() + if err != nil { + return fmt.Errorf("ofac config: %w", err) + } return nil } diff --git a/relayer/relays/execution/main.go b/relayer/relays/execution/main.go index 099d263938..8ceea0da43 100644 --- a/relayer/relays/execution/main.go +++ b/relayer/relays/execution/main.go @@ -89,6 +89,8 @@ func (r *Relay) Start(ctx context.Context, eg *errgroup.Group) error { p := protocol.New(r.config.Source.Beacon.Spec, r.config.Sink.Parachain.HeaderRedundancy) + //ofacCheck := ofac.New(r.config.OFAC.Enabled, r.config.OFAC.ApiKey) + store := store.New(r.config.Source.Beacon.DataStore.Location, r.config.Source.Beacon.DataStore.MaxEntries, *p) store.Connect() diff --git a/relayer/relays/parachain/config.go b/relayer/relays/parachain/config.go index 97a9ebd3dd..b35e1b4bcd 100644 --- a/relayer/relays/parachain/config.go +++ b/relayer/relays/parachain/config.go @@ -8,9 +8,10 @@ import ( ) type Config struct { - Source SourceConfig `mapstructure:"source"` - Sink SinkConfig `mapstructure:"sink"` - Schedule ScheduleConfig `mapstructure:"schedule"` + Source SourceConfig `mapstructure:"source"` + Sink SinkConfig `mapstructure:"sink"` + Schedule ScheduleConfig `mapstructure:"schedule"` + OFAC config.OFACConfig `mapstructure:"ofac"` } type SourceConfig struct { @@ -94,6 +95,10 @@ func (c Config) Validate() error { if err != nil { return fmt.Errorf("relay config: %w", err) } + err = c.OFAC.Validate() + if err != nil { + return fmt.Errorf("ofac config: %w", err) + } return nil } diff --git a/web/packages/test/config/execution-relay.json b/web/packages/test/config/execution-relay.json index f94caa75c3..9effbe9f8a 100644 --- a/web/packages/test/config/execution-relay.json +++ b/web/packages/test/config/execution-relay.json @@ -34,5 +34,9 @@ "id": null, "totalRelayerCount": 3, "sleepInterval": 20 + }, + "ofac": { + "enabled": false, + "apiKey": "" } } diff --git a/web/packages/test/config/parachain-relay.json b/web/packages/test/config/parachain-relay.json index 8fd1c73cb3..31c1073fd7 100644 --- a/web/packages/test/config/parachain-relay.json +++ b/web/packages/test/config/parachain-relay.json @@ -29,5 +29,9 @@ "id": null, "totalRelayerCount": 3, "sleepInterval": 45 + }, + "ofac": { + "enabled": false, + "apiKey": "" } } From b14e01836d2e4b326c17f70c1926fae470ebb0fe Mon Sep 17 00:00:00 2001 From: claravanstaden Date: Mon, 14 Oct 2024 15:56:34 +0200 Subject: [PATCH 02/19] ofac --- relayer/chain/parachain/message.go | 115 ++++++++++++++++++++++++ relayer/chain/parachain/message_test.go | 26 ++++++ relayer/ofac/ofac.go | 8 +- relayer/relays/execution/main.go | 18 +++- 4 files changed, 164 insertions(+), 3 deletions(-) create mode 100644 relayer/chain/parachain/message_test.go diff --git a/relayer/chain/parachain/message.go b/relayer/chain/parachain/message.go index 5f3a29c4ce..c296ccebe7 100644 --- a/relayer/chain/parachain/message.go +++ b/relayer/chain/parachain/message.go @@ -125,3 +125,118 @@ func removeLeadingZeroHashForSlice(s []string) []string { func removeLeadingZeroHash(s string) string { return strings.Replace(s, "0x", "", 1) } + +type DestinationEnum uint8 + +const ( + DestinationAccountId32 DestinationEnum = iota + DestinationForeignAccountId32 + DestinationForeignAccountId20 +) + +type Destination struct { + Variant DestinationEnum + // Use pointers to handle variant fields, only one should be populated. + AccountId32 *types.H256 + ForeignAccountId32 *ForeignAccountId32 + ForeignAccountId20 *ForeignAccountId20 +} + +type AccountId32 struct { + ID [32]byte +} + +type ForeignAccountId32 struct { + ParaID uint32 + ID types.H256 + Fee types.U128 +} + +type ForeignAccountId20 struct { + ParaID uint32 + ID types.H160 + Fee types.U128 +} + +type RegisterToken struct { + Token types.H256 + Fee types.U128 +} + +type SendToken struct { + Token types.H256 + Destination Destination + Amount types.U128 + Fee types.U128 +} + +type SendNativeToken struct { + TokenID types.H256 + Destination Destination + Amount types.U128 + Fee types.U128 +} + +type InboundMessage struct { + Version types.U8 + ChainID types.U64 + Command types.U8 + CommandBytes types.Data +} + +type Envelope struct { + Gateway types.H256 + ChannelID types.H256 + Nonce types.U64 + MessageID types.H256 + Payload InboundMessage +} + +func GetDestination(input []byte) (string, error) { + var envelope = &Envelope{} + err := types.DecodeFromBytes(input, envelope) + if err != nil { + return "", fmt.Errorf("failed to decode message: %v", err) + } + + address := "" + switch envelope.Payload.Command { + case 0: + // Register token does not have a destination + break + case 1: + // Send token has destination + var command = &SendToken{} + err = types.DecodeFromBytes(input, command) + if err != nil { + return "", fmt.Errorf("failed to decode send token command: %v", err) + } + + switch command.Destination.Variant { + case 0: + address = command.Destination.AccountId32.Hex() + case 1: + address = command.Destination.ForeignAccountId32.ID.Hex() + case 2: + address = command.Destination.ForeignAccountId20.ID.Hex() + } + case 2: + // Send native token has destination + var command = &SendNativeToken{} + err = types.DecodeFromBytes(input, command) + if err != nil { + return "", fmt.Errorf("failed to decode send native token command: %v", err) + } + + switch command.Destination.Variant { + case 0: + address = command.Destination.AccountId32.Hex() + case 1: + address = command.Destination.ForeignAccountId32.ID.Hex() + case 2: + address = command.Destination.ForeignAccountId20.ID.Hex() + } + } + + return address, nil +} diff --git a/relayer/chain/parachain/message_test.go b/relayer/chain/parachain/message_test.go new file mode 100644 index 0000000000..f06bc0f230 --- /dev/null +++ b/relayer/chain/parachain/message_test.go @@ -0,0 +1,26 @@ +package parachain + +import ( + "fmt" + gethCommon "github.com/ethereum/go-ethereum/common" + "github.com/snowfork/go-substrate-rpc-client/v4/types" + assert "github.com/stretchr/testify/require" + "testing" +) + +func TestGetDestination(t *testing.T) { + s := "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000002e00a736aa00000000000087d1f7fdfee7f651fabc8bfcb6e086c278b77a7d00e40b54020000000000000000000000000000000000000000000000000000000000" + + value := types.U64(1115511) + + hex, err := types.Hex(value) + assert.NoError(t, err) + + fmt.Println(hex) + data := gethCommon.Hex2Bytes(s) + + destination, err := GetDestination(data) + assert.NoError(t, err) + + fmt.Println(destination) +} diff --git a/relayer/ofac/ofac.go b/relayer/ofac/ofac.go index 1485d68199..9003bd26f4 100644 --- a/relayer/ofac/ofac.go +++ b/relayer/ofac/ofac.go @@ -5,6 +5,8 @@ import ( "fmt" "io" "net/http" + + log "github.com/sirupsen/logrus" ) type OFAC struct { @@ -21,8 +23,8 @@ type Response struct { } `json:"identifications"` } -func New(enabled bool, apiKey string) OFAC { - return OFAC{enabled, apiKey} +func New(enabled bool, apiKey string) *OFAC { + return &OFAC{enabled, apiKey} } func (o OFAC) IsBanned(source, destination string) (bool, error) { @@ -35,6 +37,7 @@ func (o OFAC) IsBanned(source, destination string) (bool, error) { return true, err } if isSourcedBanned { + log.WithField("source", source).Warn("found ofac banned source address") return true, nil } @@ -43,6 +46,7 @@ func (o OFAC) IsBanned(source, destination string) (bool, error) { return true, err } if isDestinationBanned { + log.WithField("destination", destination).Warn("found ofac banned destination address") return true, nil } diff --git a/relayer/relays/execution/main.go b/relayer/relays/execution/main.go index 8ceea0da43..3900787284 100644 --- a/relayer/relays/execution/main.go +++ b/relayer/relays/execution/main.go @@ -4,6 +4,7 @@ import ( "context" "errors" "fmt" + "github.com/snowfork/snowbridge/relayer/ofac" "math/big" "sort" "time" @@ -34,6 +35,7 @@ type Relay struct { beaconHeader *header.Header writer *parachain.ParachainWriter headerCache *ethereum.HeaderCache + ofac *ofac.OFAC } func NewRelay( @@ -89,7 +91,7 @@ func (r *Relay) Start(ctx context.Context, eg *errgroup.Group) error { p := protocol.New(r.config.Source.Beacon.Spec, r.config.Sink.Parachain.HeaderRedundancy) - //ofacCheck := ofac.New(r.config.OFAC.Enabled, r.config.OFAC.ApiKey) + r.ofac = ofac.New(r.config.OFAC.Enabled, r.config.OFAC.ApiKey) store := store.New(r.config.Source.Beacon.DataStore.Location, r.config.Source.Beacon.DataStore.MaxEntries, *p) store.Connect() @@ -414,6 +416,20 @@ func (r *Relay) doSubmit(ctx context.Context, ev *contracts.GatewayOutboundMessa "channelID": types.H256(ev.ChannelID).Hex(), }) + destination, err := parachain.GetDestination(inboundMsg.EventLog.Data) + if err != nil { + return err + } + + banned, err := r.ofac.IsBanned(ev.Raw.Address.Hex(), destination) + if err != nil { + return err + } + if banned { + logger.Warn("found ofac banned address, skipping message") + return nil + } + nextBlockNumber := new(big.Int).SetUint64(ev.Raw.BlockNumber + 1) blockHeader, err := r.ethconn.Client().HeaderByNumber(ctx, nextBlockNumber) From df886a1935232ca80d9f49a38eed9c986279f8b2 Mon Sep 17 00:00:00 2001 From: claravanstaden Date: Mon, 14 Oct 2024 16:02:14 +0200 Subject: [PATCH 03/19] adds log --- relayer/relays/beacon/header/syncer/api/api.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/relayer/relays/beacon/header/syncer/api/api.go b/relayer/relays/beacon/header/syncer/api/api.go index 6b68b95cee..3968966087 100644 --- a/relayer/relays/beacon/header/syncer/api/api.go +++ b/relayer/relays/beacon/header/syncer/api/api.go @@ -5,10 +5,12 @@ import ( "encoding/json" "errors" "fmt" + log "github.com/sirupsen/logrus" "io" "net/http" "strconv" "strings" + "time" "github.com/ethereum/go-ethereum/common" "github.com/snowfork/snowbridge/relayer/relays/util" @@ -410,11 +412,17 @@ func (b *BeaconClient) GetBeaconState(stateIdOrSlot string) ([]byte, error) { } req.Header.Add("Accept", "application/octet-stream") + startTime := time.Now() res, err := b.httpClient.Do(req) + endTime := time.Now() if err != nil { return data, err } + duration := endTime.Sub(startTime) + + log.WithFields(log.Fields{"startTime": startTime.Format(time.UnixDate), "endTime": endTime.Format(time.UnixDate), "duration": duration.Seconds()}).Warn("beacon state download time") + if res.StatusCode != http.StatusOK { if res.StatusCode == 404 { return data, ErrNotFound From f3e5104a1884fe84c5db34f1e11d1358271b08ff Mon Sep 17 00:00:00 2001 From: claravanstaden Date: Mon, 14 Oct 2024 16:03:10 +0200 Subject: [PATCH 04/19] imports --- relayer/relays/beacon/header/syncer/api/api.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/relayer/relays/beacon/header/syncer/api/api.go b/relayer/relays/beacon/header/syncer/api/api.go index 3968966087..fa91a56667 100644 --- a/relayer/relays/beacon/header/syncer/api/api.go +++ b/relayer/relays/beacon/header/syncer/api/api.go @@ -5,7 +5,6 @@ import ( "encoding/json" "errors" "fmt" - log "github.com/sirupsen/logrus" "io" "net/http" "strconv" @@ -13,6 +12,7 @@ import ( "time" "github.com/ethereum/go-ethereum/common" + log "github.com/sirupsen/logrus" "github.com/snowfork/snowbridge/relayer/relays/util" ) From d0f307c2786f4f51f41c2eb3be3abf7086344239 Mon Sep 17 00:00:00 2001 From: claravanstaden Date: Mon, 14 Oct 2024 16:03:43 +0200 Subject: [PATCH 05/19] space --- relayer/relays/beacon/header/syncer/api/api.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/relayer/relays/beacon/header/syncer/api/api.go b/relayer/relays/beacon/header/syncer/api/api.go index fa91a56667..9aaf558cb4 100644 --- a/relayer/relays/beacon/header/syncer/api/api.go +++ b/relayer/relays/beacon/header/syncer/api/api.go @@ -412,17 +412,17 @@ func (b *BeaconClient) GetBeaconState(stateIdOrSlot string) ([]byte, error) { } req.Header.Add("Accept", "application/octet-stream") + startTime := time.Now() res, err := b.httpClient.Do(req) endTime := time.Now() + duration := endTime.Sub(startTime) + log.WithFields(log.Fields{"startTime": startTime.Format(time.UnixDate), "endTime": endTime.Format(time.UnixDate), "duration": duration.Seconds()}).Warn("beacon state download time") + if err != nil { return data, err } - duration := endTime.Sub(startTime) - - log.WithFields(log.Fields{"startTime": startTime.Format(time.UnixDate), "endTime": endTime.Format(time.UnixDate), "duration": duration.Seconds()}).Warn("beacon state download time") - if res.StatusCode != http.StatusOK { if res.StatusCode == 404 { return data, ErrNotFound From b52200304ff80d3b399f1b283c68b8535261365c Mon Sep 17 00:00:00 2001 From: claravanstaden Date: Tue, 15 Oct 2024 12:07:25 +0200 Subject: [PATCH 06/19] decode --- relayer/chain/parachain/message.go | 110 ++++++++++++++++-------- relayer/chain/parachain/message_test.go | 21 +++-- relayer/relays/execution/main.go | 28 +++--- 3 files changed, 100 insertions(+), 59 deletions(-) diff --git a/relayer/chain/parachain/message.go b/relayer/chain/parachain/message.go index c296ccebe7..0e5d4157cb 100644 --- a/relayer/chain/parachain/message.go +++ b/relayer/chain/parachain/message.go @@ -4,6 +4,7 @@ package parachain import ( + "errors" "fmt" "strings" @@ -126,20 +127,9 @@ func removeLeadingZeroHash(s string) string { return strings.Replace(s, "0x", "", 1) } -type DestinationEnum uint8 - -const ( - DestinationAccountId32 DestinationEnum = iota - DestinationForeignAccountId32 - DestinationForeignAccountId20 -) - type Destination struct { - Variant DestinationEnum - // Use pointers to handle variant fields, only one should be populated. - AccountId32 *types.H256 - ForeignAccountId32 *ForeignAccountId32 - ForeignAccountId20 *ForeignAccountId20 + Variant types.U8 + DestinationBytes types.Data } type AccountId32 struct { @@ -159,22 +149,18 @@ type ForeignAccountId20 struct { } type RegisterToken struct { - Token types.H256 + Token types.H160 Fee types.U128 } type SendToken struct { - Token types.H256 + Token types.H160 Destination Destination - Amount types.U128 - Fee types.U128 } type SendNativeToken struct { TokenID types.H256 Destination Destination - Amount types.U128 - Fee types.U128 } type InboundMessage struct { @@ -184,41 +170,48 @@ type InboundMessage struct { CommandBytes types.Data } -type Envelope struct { - Gateway types.H256 - ChannelID types.H256 - Nonce types.U64 - MessageID types.H256 - Payload InboundMessage -} - func GetDestination(input []byte) (string, error) { - var envelope = &Envelope{} - err := types.DecodeFromBytes(input, envelope) + var inboundMessage = &InboundMessage{} + err := types.DecodeFromBytes(input, inboundMessage) if err != nil { return "", fmt.Errorf("failed to decode message: %v", err) } address := "" - switch envelope.Payload.Command { + switch inboundMessage.Command { case 0: // Register token does not have a destination break case 1: // Send token has destination var command = &SendToken{} - err = types.DecodeFromBytes(input, command) + err = types.DecodeFromBytes(inboundMessage.CommandBytes, command) if err != nil { return "", fmt.Errorf("failed to decode send token command: %v", err) } switch command.Destination.Variant { case 0: - address = command.Destination.AccountId32.Hex() + account32 := &types.H256{} + err = types.DecodeFromBytes(command.Destination.DestinationBytes, account32) + if err != nil { + return "", fmt.Errorf("failed to decode destination: %v", err) + } + address = account32.Hex() case 1: - address = command.Destination.ForeignAccountId32.ID.Hex() + var account = &ForeignAccountId32{} + err = types.DecodeFromBytes(command.Destination.DestinationBytes, account) + if err != nil { + return "", fmt.Errorf("failed to decode foreign account: %v", err) + } + address = account.ID.Hex() case 2: - address = command.Destination.ForeignAccountId20.ID.Hex() + var account = &ForeignAccountId20{} + err = types.DecodeFromBytes(command.Destination.DestinationBytes, account) + if err != nil { + return "", fmt.Errorf("failed to decode foreign account: %v", err) + } + address = account.ID.Hex() } case 2: // Send native token has destination @@ -230,13 +223,56 @@ func GetDestination(input []byte) (string, error) { switch command.Destination.Variant { case 0: - address = command.Destination.AccountId32.Hex() + account32 := &types.H256{} + err = types.DecodeFromBytes(command.Destination.DestinationBytes, account32) + if err != nil { + return "", fmt.Errorf("failed to decode destination: %v", err) + } + address = account32.Hex() case 1: - address = command.Destination.ForeignAccountId32.ID.Hex() + var account = &ForeignAccountId32{} + err = types.DecodeFromBytes(command.Destination.DestinationBytes, account) + if err != nil { + return "", fmt.Errorf("failed to decode foreign account: %v", err) + } + address = account.ID.Hex() case 2: - address = command.Destination.ForeignAccountId20.ID.Hex() + var account = &ForeignAccountId20{} + err = types.DecodeFromBytes(command.Destination.DestinationBytes, account) + if err != nil { + return "", fmt.Errorf("failed to decode foreign account: %v", err) + } + address = account.ID.Hex() } } return address, nil } + +func decodeDestination(variant types.U8, destinationBytes []byte) (string, error) { + switch variant { + case 0: + account32 := &types.H256{} + err := types.DecodeFromBytes(destinationBytes, account32) + if err != nil { + return "", fmt.Errorf("failed to decode destination: %v", err) + } + return account32.Hex(), nil + case 1: + var account = &ForeignAccountId32{} + err := types.DecodeFromBytes(destinationBytes, account) + if err != nil { + return "", fmt.Errorf("failed to decode foreign account: %v", err) + } + return account.ID.Hex(), nil + case 2: + var account = &ForeignAccountId20{} + err := types.DecodeFromBytes(destinationBytes, account) + if err != nil { + return "", fmt.Errorf("failed to decode foreign account: %v", err) + } + return account.ID.Hex(), nil + } + + return "", errors.New("destination variant could not be matched") +} diff --git a/relayer/chain/parachain/message_test.go b/relayer/chain/parachain/message_test.go index f06bc0f230..ec425bf998 100644 --- a/relayer/chain/parachain/message_test.go +++ b/relayer/chain/parachain/message_test.go @@ -1,26 +1,29 @@ package parachain import ( - "fmt" gethCommon "github.com/ethereum/go-ethereum/common" - "github.com/snowfork/go-substrate-rpc-client/v4/types" assert "github.com/stretchr/testify/require" "testing" ) func TestGetDestination(t *testing.T) { - s := "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000002e00a736aa00000000000087d1f7fdfee7f651fabc8bfcb6e086c278b77a7d00e40b54020000000000000000000000000000000000000000000000000000000000" + registerTokenPayload := "00a736aa0000000000017746600a736aa000000000000774667629726ec1fabebcec0d9139bd1c8f72a2300e876481700000000000000000000007629726ec1fabebcec0d9139bd1c8f72a23008eaf04151687736326c9fea17e25fc5287613693c912909cb226aa4794f26a4800c16ff2862300000000000000000000e87648170000000000000000000000" + decodePayloadAndCompareDestinationAddress(t, registerTokenPayload, "") // register token does not have a destination - value := types.U64(1115511) + sendTokenPayload := "00a736aa000000000001774667629726ec1fabebcec0d9139bd1c8f72a23008eaf04151687736326c9fea17e25fc5287613693c912909cb226aa4794f26a4800c16ff2862300000000000000000000e87648170000000000000000000000" + bobAddress := "0x8eaf04151687736326c9fea17e25fc5287613693c912909cb226aa4794f26a48" + decodePayloadAndCompareDestinationAddress(t, sendTokenPayload, bobAddress) - hex, err := types.Hex(value) - assert.NoError(t, err) + sendTokenToPayload := "00a736aa000000000001774667629726ec1fabebcec0d9139bd1c8f72a2301d00700001cbd2d43530a44705ad088af313e18f80b53ef16b36177cd4b77b846f2a5f07c00286bee000000000000000000000000000064a7b3b6e00d000000000000000000e87648170000000000000000000000" + ferdieAddress := "0x1cbd2d43530a44705ad088af313e18f80b53ef16b36177cd4b77b846f2a5f07c" + decodePayloadAndCompareDestinationAddress(t, sendTokenToPayload, ferdieAddress) +} - fmt.Println(hex) - data := gethCommon.Hex2Bytes(s) +func decodePayloadAndCompareDestinationAddress(t *testing.T, payload, expectedAddress string) { + data := gethCommon.Hex2Bytes(payload) destination, err := GetDestination(data) assert.NoError(t, err) - fmt.Println(destination) + assert.Equal(t, expectedAddress, destination) } diff --git a/relayer/relays/execution/main.go b/relayer/relays/execution/main.go index 3900787284..94c4e70795 100644 --- a/relayer/relays/execution/main.go +++ b/relayer/relays/execution/main.go @@ -416,19 +416,21 @@ func (r *Relay) doSubmit(ctx context.Context, ev *contracts.GatewayOutboundMessa "channelID": types.H256(ev.ChannelID).Hex(), }) - destination, err := parachain.GetDestination(inboundMsg.EventLog.Data) - if err != nil { - return err - } - - banned, err := r.ofac.IsBanned(ev.Raw.Address.Hex(), destination) - if err != nil { - return err - } - if banned { - logger.Warn("found ofac banned address, skipping message") - return nil - } + log.WithField("data", common.BytesToHash(ev.Payload)).Info("Payload bytes is......") + + //destination, err := parachain.GetDestination(ev.Payload) + //if err != nil { + // return err + //} + + //banned, err := r.ofac.IsBanned(ev.Raw.Address.Hex(), destination) + //if err != nil { + // return err + //} + //if banned { + // logger.Warn("found ofac banned address, skipping message") + // return nil + //} nextBlockNumber := new(big.Int).SetUint64(ev.Raw.BlockNumber + 1) From 9db4e62de051af6bff5ebad0f662ca980b922323 Mon Sep 17 00:00:00 2001 From: claravanstaden Date: Tue, 15 Oct 2024 12:13:34 +0200 Subject: [PATCH 07/19] fix test --- relayer/chain/parachain/message_test.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/relayer/chain/parachain/message_test.go b/relayer/chain/parachain/message_test.go index ec425bf998..b87d31fafb 100644 --- a/relayer/chain/parachain/message_test.go +++ b/relayer/chain/parachain/message_test.go @@ -7,7 +7,7 @@ import ( ) func TestGetDestination(t *testing.T) { - registerTokenPayload := "00a736aa0000000000017746600a736aa000000000000774667629726ec1fabebcec0d9139bd1c8f72a2300e876481700000000000000000000007629726ec1fabebcec0d9139bd1c8f72a23008eaf04151687736326c9fea17e25fc5287613693c912909cb226aa4794f26a4800c16ff2862300000000000000000000e87648170000000000000000000000" + registerTokenPayload := "00a736aa000000000000774667629726ec1fabebcec0d9139bd1c8f72a2300e87648170000000000000000000000" decodePayloadAndCompareDestinationAddress(t, registerTokenPayload, "") // register token does not have a destination sendTokenPayload := "00a736aa000000000001774667629726ec1fabebcec0d9139bd1c8f72a23008eaf04151687736326c9fea17e25fc5287613693c912909cb226aa4794f26a4800c16ff2862300000000000000000000e87648170000000000000000000000" @@ -17,6 +17,8 @@ func TestGetDestination(t *testing.T) { sendTokenToPayload := "00a736aa000000000001774667629726ec1fabebcec0d9139bd1c8f72a2301d00700001cbd2d43530a44705ad088af313e18f80b53ef16b36177cd4b77b846f2a5f07c00286bee000000000000000000000000000064a7b3b6e00d000000000000000000e87648170000000000000000000000" ferdieAddress := "0x1cbd2d43530a44705ad088af313e18f80b53ef16b36177cd4b77b846f2a5f07c" decodePayloadAndCompareDestinationAddress(t, sendTokenToPayload, ferdieAddress) + + //sendNativeTokenPayload := "00a736aa0000000000022121cfe35065c0c33465fbada265f08e9613428a4b9eb4bb717cd7db2abf622e008eaf04151687736326c9fea17e25fc5287613693c912909cb226aa4794f26a480065cd1d00000000000000000000000000e87648170000000000000000000000" } func decodePayloadAndCompareDestinationAddress(t *testing.T, payload, expectedAddress string) { From fc90b21a79169e0f03c9f2c778a37200863b532d Mon Sep 17 00:00:00 2001 From: claravanstaden Date: Tue, 15 Oct 2024 12:13:56 +0200 Subject: [PATCH 08/19] refactor --- relayer/chain/parachain/message.go | 54 +++++------------------------- 1 file changed, 8 insertions(+), 46 deletions(-) diff --git a/relayer/chain/parachain/message.go b/relayer/chain/parachain/message.go index 0e5d4157cb..827fb0cca9 100644 --- a/relayer/chain/parachain/message.go +++ b/relayer/chain/parachain/message.go @@ -183,66 +183,28 @@ func GetDestination(input []byte) (string, error) { // Register token does not have a destination break case 1: - // Send token has destination + // Send token has a destination var command = &SendToken{} err = types.DecodeFromBytes(inboundMessage.CommandBytes, command) if err != nil { return "", fmt.Errorf("failed to decode send token command: %v", err) } - switch command.Destination.Variant { - case 0: - account32 := &types.H256{} - err = types.DecodeFromBytes(command.Destination.DestinationBytes, account32) - if err != nil { - return "", fmt.Errorf("failed to decode destination: %v", err) - } - address = account32.Hex() - case 1: - var account = &ForeignAccountId32{} - err = types.DecodeFromBytes(command.Destination.DestinationBytes, account) - if err != nil { - return "", fmt.Errorf("failed to decode foreign account: %v", err) - } - address = account.ID.Hex() - case 2: - var account = &ForeignAccountId20{} - err = types.DecodeFromBytes(command.Destination.DestinationBytes, account) - if err != nil { - return "", fmt.Errorf("failed to decode foreign account: %v", err) - } - address = account.ID.Hex() + address, err = decodeDestination(command.Destination.Variant, command.Destination.DestinationBytes) + if err != nil { + return "", fmt.Errorf("decode destination: %v", err) } case 2: - // Send native token has destination + // Send native token has a destination var command = &SendNativeToken{} err = types.DecodeFromBytes(input, command) if err != nil { return "", fmt.Errorf("failed to decode send native token command: %v", err) } - switch command.Destination.Variant { - case 0: - account32 := &types.H256{} - err = types.DecodeFromBytes(command.Destination.DestinationBytes, account32) - if err != nil { - return "", fmt.Errorf("failed to decode destination: %v", err) - } - address = account32.Hex() - case 1: - var account = &ForeignAccountId32{} - err = types.DecodeFromBytes(command.Destination.DestinationBytes, account) - if err != nil { - return "", fmt.Errorf("failed to decode foreign account: %v", err) - } - address = account.ID.Hex() - case 2: - var account = &ForeignAccountId20{} - err = types.DecodeFromBytes(command.Destination.DestinationBytes, account) - if err != nil { - return "", fmt.Errorf("failed to decode foreign account: %v", err) - } - address = account.ID.Hex() + address, err = decodeDestination(command.Destination.Variant, command.Destination.DestinationBytes) + if err != nil { + return "", fmt.Errorf("decode destination: %v", err) } } From a89995a10aa4425638b772901b267b0e12cc4516 Mon Sep 17 00:00:00 2001 From: claravanstaden Date: Tue, 15 Oct 2024 12:23:04 +0200 Subject: [PATCH 09/19] tests work --- relayer/chain/parachain/message.go | 2 +- relayer/chain/parachain/message_test.go | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/relayer/chain/parachain/message.go b/relayer/chain/parachain/message.go index 827fb0cca9..2ade512ddd 100644 --- a/relayer/chain/parachain/message.go +++ b/relayer/chain/parachain/message.go @@ -197,7 +197,7 @@ func GetDestination(input []byte) (string, error) { case 2: // Send native token has a destination var command = &SendNativeToken{} - err = types.DecodeFromBytes(input, command) + err = types.DecodeFromBytes(inboundMessage.CommandBytes, command) if err != nil { return "", fmt.Errorf("failed to decode send native token command: %v", err) } diff --git a/relayer/chain/parachain/message_test.go b/relayer/chain/parachain/message_test.go index b87d31fafb..67a4f7eeba 100644 --- a/relayer/chain/parachain/message_test.go +++ b/relayer/chain/parachain/message_test.go @@ -18,7 +18,8 @@ func TestGetDestination(t *testing.T) { ferdieAddress := "0x1cbd2d43530a44705ad088af313e18f80b53ef16b36177cd4b77b846f2a5f07c" decodePayloadAndCompareDestinationAddress(t, sendTokenToPayload, ferdieAddress) - //sendNativeTokenPayload := "00a736aa0000000000022121cfe35065c0c33465fbada265f08e9613428a4b9eb4bb717cd7db2abf622e008eaf04151687736326c9fea17e25fc5287613693c912909cb226aa4794f26a480065cd1d00000000000000000000000000e87648170000000000000000000000" + sendNativeTokenPayload := "00a736aa0000000000022121cfe35065c0c33465fbada265f08e9613428a4b9eb4bb717cd7db2abf622e008eaf04151687736326c9fea17e25fc5287613693c912909cb226aa4794f26a48065cd1d00000000000000000000000000e87648170000000000000000000000" + decodePayloadAndCompareDestinationAddress(t, sendNativeTokenPayload, bobAddress) } func decodePayloadAndCompareDestinationAddress(t *testing.T, payload, expectedAddress string) { From e9894eb212aba05240099eaaaee3e6fb1a46810c Mon Sep 17 00:00:00 2001 From: claravanstaden Date: Tue, 15 Oct 2024 17:36:37 +0200 Subject: [PATCH 10/19] ofac --- relayer/chain/parachain/message.go | 18 ++++++++++ relayer/chain/parachain/message_test.go | 18 ++++++++++ relayer/relays/execution/main.go | 33 +++++++++--------- relayer/relays/parachain/beefy-listener.go | 5 +++ relayer/relays/parachain/main.go | 4 +++ relayer/relays/parachain/scanner.go | 39 +++++++++++++++++++++- 6 files changed, 101 insertions(+), 16 deletions(-) diff --git a/relayer/chain/parachain/message.go b/relayer/chain/parachain/message.go index 2ade512ddd..d6a32102f3 100644 --- a/relayer/chain/parachain/message.go +++ b/relayer/chain/parachain/message.go @@ -170,6 +170,24 @@ type InboundMessage struct { CommandBytes types.Data } +type Envelope struct { + Gateway types.H160 + ChannelID [32]types.U8 + Nonce types.U64 + MessageID types.H256 + Payload types.Data +} + +func GetDestinationFromEnvelope(input []byte) (string, error) { + var envelope = &Envelope{} + err := types.DecodeFromBytes(input, envelope) + if err != nil { + return "", fmt.Errorf("failed to decode message: %v", err) + } + + return GetDestination(envelope.Payload) +} + func GetDestination(input []byte) (string, error) { var inboundMessage = &InboundMessage{} err := types.DecodeFromBytes(input, inboundMessage) diff --git a/relayer/chain/parachain/message_test.go b/relayer/chain/parachain/message_test.go index 67a4f7eeba..0b13d74083 100644 --- a/relayer/chain/parachain/message_test.go +++ b/relayer/chain/parachain/message_test.go @@ -1,11 +1,29 @@ package parachain import ( + "fmt" gethCommon "github.com/ethereum/go-ethereum/common" assert "github.com/stretchr/testify/require" "testing" ) +func TestGetDestinationFromEnvelope(t *testing.T) { + envelope := "00000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000006b00a736aa0000000000022121cfe35065c0c33465fbada265f08e9613428a4b9eb4bb717cd7db2abf622e008eaf04151687736326c9fea17e25fc5287613693c912909cb226aa4794f26a480065cd1d00000000000000000000000000e87648170000000000000000000000000000000000000000000000000000000000000000" + data := gethCommon.Hex2Bytes(envelope) + destination, err := GetDestinationFromEnvelope(data) + assert.NoError(t, err) + + assert.Equal(t, "0x8eaf04151687736326c9fea17e25fc5287613693c912909cb226aa4794f26a48", destination) +} + +func TestGetDestin(t *testing.T) { + envelope := "00000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000006b00a736aa0000000000022121cfe35065c0c33465fbada265f08e9613428a4b9eb4bb717cd7db2abf622e008eaf04151687736326c9fea17e25fc5287613693c912909cb226aa4794f26a480065cd1d00000000000000000000000000e87648170000000000000000000000000000000000000000000000000000000000000000" + data := gethCommon.Hex2Bytes(envelope) + + data2 := data[96:] + fmt.Println(gethCommon.Bytes2Hex(data2)) +} + func TestGetDestination(t *testing.T) { registerTokenPayload := "00a736aa000000000000774667629726ec1fabebcec0d9139bd1c8f72a2300e87648170000000000000000000000" decodePayloadAndCompareDestinationAddress(t, registerTokenPayload, "") // register token does not have a destination diff --git a/relayer/relays/execution/main.go b/relayer/relays/execution/main.go index 94c4e70795..4e2005a954 100644 --- a/relayer/relays/execution/main.go +++ b/relayer/relays/execution/main.go @@ -416,21 +416,24 @@ func (r *Relay) doSubmit(ctx context.Context, ev *contracts.GatewayOutboundMessa "channelID": types.H256(ev.ChannelID).Hex(), }) - log.WithField("data", common.BytesToHash(ev.Payload)).Info("Payload bytes is......") - - //destination, err := parachain.GetDestination(ev.Payload) - //if err != nil { - // return err - //} - - //banned, err := r.ofac.IsBanned(ev.Raw.Address.Hex(), destination) - //if err != nil { - // return err - //} - //if banned { - // logger.Warn("found ofac banned address, skipping message") - // return nil - //} + log.WithField("event", ev).Info("event data") + + destination, err := parachain.GetDestination(ev.Raw.Data[96:]) + if err != nil { + return err + } + if destination != "" { + banned, err := r.ofac.IsBanned(ev.Raw.Address.Hex(), destination) + if err != nil { + return err + } + if banned { + logger.Warn("found ofac banned address, skipping message") + //return nil + } else { + logger.Info("address is not banned, continuing") + } + } nextBlockNumber := new(big.Int).SetUint64(ev.Raw.BlockNumber + 1) diff --git a/relayer/relays/parachain/beefy-listener.go b/relayer/relays/parachain/beefy-listener.go index 41d0e5e292..04f687cb4e 100644 --- a/relayer/relays/parachain/beefy-listener.go +++ b/relayer/relays/parachain/beefy-listener.go @@ -17,6 +17,7 @@ import ( "github.com/snowfork/snowbridge/relayer/chain/relaychain" "github.com/snowfork/snowbridge/relayer/contracts" "github.com/snowfork/snowbridge/relayer/crypto/merkle" + "github.com/snowfork/snowbridge/relayer/ofac" log "github.com/sirupsen/logrus" ) @@ -28,6 +29,7 @@ type BeefyListener struct { beefyClientContract *contracts.BeefyClient relaychainConn *relaychain.Connection parachainConnection *parachain.Connection + ofac *ofac.OFAC paraID uint32 tasks chan<- *Task scanner *Scanner @@ -39,6 +41,7 @@ func NewBeefyListener( ethereumConn *ethereum.Connection, relaychainConn *relaychain.Connection, parachainConnection *parachain.Connection, + ofac *ofac.OFAC, tasks chan<- *Task, ) *BeefyListener { return &BeefyListener{ @@ -47,6 +50,7 @@ func NewBeefyListener( ethereumConn: ethereumConn, relaychainConn: relaychainConn, parachainConnection: parachainConnection, + ofac: ofac, tasks: tasks, } } @@ -81,6 +85,7 @@ func (li *BeefyListener) Start(ctx context.Context, eg *errgroup.Group) error { relayConn: li.relaychainConn, paraConn: li.parachainConnection, paraID: paraID, + ofac: li.ofac, } eg.Go(func() error { diff --git a/relayer/relays/parachain/main.go b/relayer/relays/parachain/main.go index d66da938fd..44f6d710e3 100644 --- a/relayer/relays/parachain/main.go +++ b/relayer/relays/parachain/main.go @@ -11,6 +11,7 @@ import ( "github.com/snowfork/snowbridge/relayer/chain/parachain" "github.com/snowfork/snowbridge/relayer/chain/relaychain" "github.com/snowfork/snowbridge/relayer/crypto/secp256k1" + "github.com/snowfork/snowbridge/relayer/ofac" log "github.com/sirupsen/logrus" ) @@ -34,6 +35,8 @@ func NewRelay(config *Config, keypair *secp256k1.Keypair) (*Relay, error) { ethereumConnWriter := ethereum.NewConnection(&config.Sink.Ethereum, keypair) ethereumConnBeefy := ethereum.NewConnection(&config.Source.Ethereum, keypair) + ofacClient := ofac.New(config.OFAC.Enabled, config.OFAC.ApiKey) + // channel for messages from beefy listener to ethereum writer var tasks = make(chan *Task, 1) @@ -52,6 +55,7 @@ func NewRelay(config *Config, keypair *secp256k1.Keypair) (*Relay, error) { ethereumConnBeefy, relaychainConn, parachainConn, + ofacClient, tasks, ) diff --git a/relayer/relays/parachain/scanner.go b/relayer/relays/parachain/scanner.go index 287ca93118..7ef3695ee3 100644 --- a/relayer/relays/parachain/scanner.go +++ b/relayer/relays/parachain/scanner.go @@ -16,6 +16,7 @@ import ( "github.com/snowfork/snowbridge/relayer/chain/parachain" "github.com/snowfork/snowbridge/relayer/chain/relaychain" "github.com/snowfork/snowbridge/relayer/contracts" + "github.com/snowfork/snowbridge/relayer/ofac" ) type Scanner struct { @@ -24,6 +25,7 @@ type Scanner struct { relayConn *relaychain.Connection paraConn *parachain.Connection paraID uint32 + ofac *ofac.OFAC tasks chan<- *Task } @@ -186,7 +188,9 @@ func (s *Scanner) findTasksImpl( if err != nil { return nil, fmt.Errorf("decode message error: %w", err) } - messages = append(messages, m) + if !s.IsBanned(m) { + messages = append(messages, m) + } } // For the outbound channel, the commitment hash is the merkle root of the messages @@ -464,3 +468,36 @@ func (s *Scanner) findLatestNonce(ctx context.Context) (uint64, error) { } return ethInboundNonce, err } + +func (s *Scanner) IsBanned(message OutboundQueueMessage) bool { + log.WithFields(log.Fields{ + "command": message.Command, + "params": message.Params, + }).Debug("Checking message for OFAC") + + switch message.Command { + + case 0: + // AgentExecute + log.WithFields(log.Fields{ + "params": common.Bytes2Hex(message.Params), + }).Debug("Found AgentExecute message") + case 6: + // TransferNativeFromAgent + log.WithFields(log.Fields{ + "params": common.Bytes2Hex(message.Params), + }).Debug("Found TransferNativeFromAgent message") + case 9: + // TransferNativeToken + log.WithFields(log.Fields{ + "params": common.Bytes2Hex(message.Params), + }).Debug("Found TransferNativeToken message") + case 11: + // MintForeignToken + log.WithFields(log.Fields{ + "params": common.Bytes2Hex(message.Params), + }).Debug("Found MintForeignToken message") + } + + return false +} From a3c706b143333b70e858b4a8da1002c60669e623 Mon Sep 17 00:00:00 2001 From: claravanstaden Date: Wed, 16 Oct 2024 07:55:39 +0200 Subject: [PATCH 11/19] ethereum side --- relayer/chain/parachain/message.go | 25 +++---------------------- relayer/chain/parachain/message_test.go | 21 ++------------------- relayer/relays/execution/main.go | 15 +++++++++------ 3 files changed, 14 insertions(+), 47 deletions(-) diff --git a/relayer/chain/parachain/message.go b/relayer/chain/parachain/message.go index d6a32102f3..6613897c5b 100644 --- a/relayer/chain/parachain/message.go +++ b/relayer/chain/parachain/message.go @@ -132,10 +132,6 @@ type Destination struct { DestinationBytes types.Data } -type AccountId32 struct { - ID [32]byte -} - type ForeignAccountId32 struct { ParaID uint32 ID types.H256 @@ -170,24 +166,6 @@ type InboundMessage struct { CommandBytes types.Data } -type Envelope struct { - Gateway types.H160 - ChannelID [32]types.U8 - Nonce types.U64 - MessageID types.H256 - Payload types.Data -} - -func GetDestinationFromEnvelope(input []byte) (string, error) { - var envelope = &Envelope{} - err := types.DecodeFromBytes(input, envelope) - if err != nil { - return "", fmt.Errorf("failed to decode message: %v", err) - } - - return GetDestination(envelope.Payload) -} - func GetDestination(input []byte) (string, error) { var inboundMessage = &InboundMessage{} err := types.DecodeFromBytes(input, inboundMessage) @@ -232,6 +210,7 @@ func GetDestination(input []byte) (string, error) { func decodeDestination(variant types.U8, destinationBytes []byte) (string, error) { switch variant { case 0: + // Account32 account32 := &types.H256{} err := types.DecodeFromBytes(destinationBytes, account32) if err != nil { @@ -239,6 +218,7 @@ func decodeDestination(variant types.U8, destinationBytes []byte) (string, error } return account32.Hex(), nil case 1: + // Account32 on destination parachain var account = &ForeignAccountId32{} err := types.DecodeFromBytes(destinationBytes, account) if err != nil { @@ -246,6 +226,7 @@ func decodeDestination(variant types.U8, destinationBytes []byte) (string, error } return account.ID.Hex(), nil case 2: + // Account20 var account = &ForeignAccountId20{} err := types.DecodeFromBytes(destinationBytes, account) if err != nil { diff --git a/relayer/chain/parachain/message_test.go b/relayer/chain/parachain/message_test.go index 0b13d74083..869f1afccb 100644 --- a/relayer/chain/parachain/message_test.go +++ b/relayer/chain/parachain/message_test.go @@ -1,29 +1,12 @@ package parachain import ( - "fmt" + "testing" + gethCommon "github.com/ethereum/go-ethereum/common" assert "github.com/stretchr/testify/require" - "testing" ) -func TestGetDestinationFromEnvelope(t *testing.T) { - envelope := "00000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000006b00a736aa0000000000022121cfe35065c0c33465fbada265f08e9613428a4b9eb4bb717cd7db2abf622e008eaf04151687736326c9fea17e25fc5287613693c912909cb226aa4794f26a480065cd1d00000000000000000000000000e87648170000000000000000000000000000000000000000000000000000000000000000" - data := gethCommon.Hex2Bytes(envelope) - destination, err := GetDestinationFromEnvelope(data) - assert.NoError(t, err) - - assert.Equal(t, "0x8eaf04151687736326c9fea17e25fc5287613693c912909cb226aa4794f26a48", destination) -} - -func TestGetDestin(t *testing.T) { - envelope := "00000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000006b00a736aa0000000000022121cfe35065c0c33465fbada265f08e9613428a4b9eb4bb717cd7db2abf622e008eaf04151687736326c9fea17e25fc5287613693c912909cb226aa4794f26a480065cd1d00000000000000000000000000e87648170000000000000000000000000000000000000000000000000000000000000000" - data := gethCommon.Hex2Bytes(envelope) - - data2 := data[96:] - fmt.Println(gethCommon.Bytes2Hex(data2)) -} - func TestGetDestination(t *testing.T) { registerTokenPayload := "00a736aa000000000000774667629726ec1fabebcec0d9139bd1c8f72a2300e87648170000000000000000000000" decodePayloadAndCompareDestinationAddress(t, registerTokenPayload, "") // register token does not have a destination diff --git a/relayer/relays/execution/main.go b/relayer/relays/execution/main.go index 4e2005a954..196c1dc1b4 100644 --- a/relayer/relays/execution/main.go +++ b/relayer/relays/execution/main.go @@ -416,22 +416,25 @@ func (r *Relay) doSubmit(ctx context.Context, ev *contracts.GatewayOutboundMessa "channelID": types.H256(ev.ChannelID).Hex(), }) - log.WithField("event", ev).Info("event data") - - destination, err := parachain.GetDestination(ev.Raw.Data[96:]) + destination, err := parachain.GetDestination(ev.Payload) if err != nil { return err } + + log.WithFields(log.Fields{ + "destination": destination, + "payload": common.Bytes2Hex(ev.Payload), + }).Info("extracted destination from message") if destination != "" { banned, err := r.ofac.IsBanned(ev.Raw.Address.Hex(), destination) if err != nil { return err } if banned { - logger.Warn("found ofac banned address, skipping message") - //return nil + log.Warn("found ofac banned address, skipping message") + return nil } else { - logger.Info("address is not banned, continuing") + log.Info("address is not banned, continuing") } } From 70040c77e92500a0ea6bbc20496496e58963478d Mon Sep 17 00:00:00 2001 From: claravanstaden Date: Wed, 16 Oct 2024 09:23:24 +0200 Subject: [PATCH 12/19] decode message --- relayer/relays/parachain/scanner.go | 97 +++++++++++++++++++++--- relayer/relays/parachain/scanner_test.go | 24 ++++++ 2 files changed, 112 insertions(+), 9 deletions(-) create mode 100644 relayer/relays/parachain/scanner_test.go diff --git a/relayer/relays/parachain/scanner.go b/relayer/relays/parachain/scanner.go index 7ef3695ee3..a5cbe6788d 100644 --- a/relayer/relays/parachain/scanner.go +++ b/relayer/relays/parachain/scanner.go @@ -3,7 +3,11 @@ package parachain import ( "bytes" "context" + "errors" "fmt" + "github.com/ethereum/go-ethereum/accounts/abi" + "reflect" + "strings" "github.com/snowfork/go-substrate-rpc-client/v4/scale" @@ -188,9 +192,9 @@ func (s *Scanner) findTasksImpl( if err != nil { return nil, fmt.Errorf("decode message error: %w", err) } - if !s.IsBanned(m) { - messages = append(messages, m) - } + //if !s.IsBanned(m) { + messages = append(messages, m) + //} } // For the outbound channel, the commitment hash is the merkle root of the messages @@ -469,19 +473,94 @@ func (s *Scanner) findLatestNonce(ctx context.Context) (uint64, error) { return ethInboundNonce, err } -func (s *Scanner) IsBanned(message OutboundQueueMessage) bool { +func GetDestination(message OutboundQueueMessage) (string, error) { log.WithFields(log.Fields{ "command": message.Command, "params": message.Params, }).Debug("Checking message for OFAC") switch message.Command { - case 0: // AgentExecute - log.WithFields(log.Fields{ - "params": common.Bytes2Hex(message.Params), - }).Debug("Found AgentExecute message") + log.Debug("Found AgentExecute message") + + uintTy, err := abi.NewType("uint256", "", nil) + if err != nil { + return "", err + } + bytesTy, err := abi.NewType("bytes", "", nil) + if err != nil { + return "", err + } + addressTy, err := abi.NewType("address", "", nil) + if err != nil { + return "", err + } + tupleTy, err := abi.NewType("tuple", "", []abi.ArgumentMarshaling{ + {Name: "AgentId", Type: "bytes32"}, + {Name: "Command", Type: "bytes"}, + }) + if err != nil { + return "", err + } + + argument := abi.Arguments{ + {Type: tupleTy}, + } + + // Decode the ABI-encoded byte payload + decodedTuple, err := argument.Unpack(message.Params) + if err != nil { + return "", fmt.Errorf("unpack tuple: %w", err) + } + + if len(decodedTuple) < 1 { + return "", fmt.Errorf("tuple could not be decoded") + } + + values := reflect.ValueOf(decodedTuple[0]) + commandBytes := values.FieldByName("Command").Bytes() + fmt.Println(common.Bytes2Hex(commandBytes)) + + argument = abi.Arguments{ + {Type: uintTy}, + {Type: bytesTy}, + } + + // Decode the ABI-encoded byte payload + decodedCommand, err := argument.Unpack(commandBytes) + if err != nil { + return "", fmt.Errorf("unpack command: %w", err) + } + + if len(decodedCommand) < 2 { + return "", errors.New("command could not be decoded") + } + + argument = abi.Arguments{ + { + Type: addressTy, + }, + { + Type: addressTy, + }, + { + Type: uintTy, + }, + } + + decodedTransferToken, err := argument.Unpack(decodedCommand[1].([]byte)) + if err != nil { + return "", err + } + + if len(decodedTransferToken) < 3 { + return "", errors.New("transfer token could not be decoded") + } + + address := decodedTransferToken[1].(common.Address) + + return strings.ToLower(address.String()), nil case 6: // TransferNativeFromAgent log.WithFields(log.Fields{ @@ -499,5 +578,5 @@ func (s *Scanner) IsBanned(message OutboundQueueMessage) bool { }).Debug("Found MintForeignToken message") } - return false + return "", nil } diff --git a/relayer/relays/parachain/scanner_test.go b/relayer/relays/parachain/scanner_test.go new file mode 100644 index 0000000000..60b067cbc4 --- /dev/null +++ b/relayer/relays/parachain/scanner_test.go @@ -0,0 +1,24 @@ +package parachain + +import ( + gethCommon "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/assert" + "testing" +) + +func TestGetDestination(t *testing.T) { + agentExecutePayload := "000000000000000000000000000000000000000000000000000000000000002081c5ab2571199e3188135178f3c2c8e2d268be1313d029b30f534fa579b69b79000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000060000000000000000000000000774667629726ec1fabebcec0d9139bd1c8f72a2300000000000000000000000044a57ee2f2fccb85fda2b0b18ebd0d8d2333700e000000000000000000000000000000000000000000000000000000003b9aca00" + decodePayloadAndCompareDestinationAddress(t, 0, agentExecutePayload, "0x44a57ee2f2fccb85fda2b0b18ebd0d8d2333700e") +} + +func decodePayloadAndCompareDestinationAddress(t *testing.T, command uint8, payload, expectedAddress string) { + data := gethCommon.Hex2Bytes(payload) + + destination, err := GetDestination(OutboundQueueMessage{ + Command: command, + Params: data, + }) + assert.NoError(t, err) + + assert.Equal(t, expectedAddress, destination) +} From e019378e5318857c874041d0ed66de90fb72d547 Mon Sep 17 00:00:00 2001 From: claravanstaden Date: Wed, 16 Oct 2024 14:48:03 +0200 Subject: [PATCH 13/19] parachain side --- relayer/ofac/ofac.go | 34 ++++---- relayer/relays/execution/main.go | 20 ++--- relayer/relays/parachain/scanner.go | 126 +++++++++++++++++----------- 3 files changed, 106 insertions(+), 74 deletions(-) diff --git a/relayer/ofac/ofac.go b/relayer/ofac/ofac.go index 9003bd26f4..257fec6299 100644 --- a/relayer/ofac/ofac.go +++ b/relayer/ofac/ofac.go @@ -32,28 +32,32 @@ func (o OFAC) IsBanned(source, destination string) (bool, error) { return false, nil } - isSourcedBanned, err := o.checkOFAC(source) - if err != nil { - return true, err - } - if isSourcedBanned { - log.WithField("source", source).Warn("found ofac banned source address") - return true, nil + if source != "" { + isSourcedBanned, err := o.isOFACListed(source) + if err != nil { + return true, err + } + if isSourcedBanned { + log.WithField("source", source).Warn("found ofac banned source address") + return true, nil + } } - isDestinationBanned, err := o.checkOFAC(destination) - if err != nil { - return true, err - } - if isDestinationBanned { - log.WithField("destination", destination).Warn("found ofac banned destination address") - return true, nil + if destination != "" { + isDestinationBanned, err := o.isOFACListed(destination) + if err != nil { + return true, err + } + if isDestinationBanned { + log.WithField("destination", destination).Warn("found ofac banned destination address") + return true, nil + } } return false, nil } -func (o OFAC) checkOFAC(address string) (bool, error) { +func (o OFAC) isOFACListed(address string) (bool, error) { client := &http.Client{} req, err := http.NewRequest("GET", fmt.Sprintf("https://public.chainalysis.com/api/v1/address/%s", address), nil) diff --git a/relayer/relays/execution/main.go b/relayer/relays/execution/main.go index 196c1dc1b4..2c360e7e2f 100644 --- a/relayer/relays/execution/main.go +++ b/relayer/relays/execution/main.go @@ -425,17 +425,15 @@ func (r *Relay) doSubmit(ctx context.Context, ev *contracts.GatewayOutboundMessa "destination": destination, "payload": common.Bytes2Hex(ev.Payload), }).Info("extracted destination from message") - if destination != "" { - banned, err := r.ofac.IsBanned(ev.Raw.Address.Hex(), destination) - if err != nil { - return err - } - if banned { - log.Warn("found ofac banned address, skipping message") - return nil - } else { - log.Info("address is not banned, continuing") - } + banned, err := r.ofac.IsBanned(ev.Raw.Address.Hex(), destination) + if err != nil { + return err + } + if banned { + log.Fatal("banned address found") + return errors.New("banned address found") + } else { + log.Info("address is not banned, continuing") } nextBlockNumber := new(big.Int).SetUint64(ev.Raw.BlockNumber + 1) diff --git a/relayer/relays/parachain/scanner.go b/relayer/relays/parachain/scanner.go index a5cbe6788d..998ba6bb88 100644 --- a/relayer/relays/parachain/scanner.go +++ b/relayer/relays/parachain/scanner.go @@ -192,9 +192,15 @@ func (s *Scanner) findTasksImpl( if err != nil { return nil, fmt.Errorf("decode message error: %w", err) } - //if !s.IsBanned(m) { + isBanned, err := s.IsBanned(m) + if err != nil { + return nil, fmt.Errorf("banned check: %w", err) + } + if isBanned { + log.Fatal("banned address found") + return nil, errors.New("banned address found") + } messages = append(messages, m) - //} } // For the outbound channel, the commitment hash is the merkle root of the messages @@ -473,6 +479,15 @@ func (s *Scanner) findLatestNonce(ctx context.Context) (uint64, error) { return ethInboundNonce, err } +func (s *Scanner) IsBanned(m OutboundQueueMessage) (bool, error) { + destination, err := GetDestination(m) + if err != nil { + return true, err + } + + return s.ofac.IsBanned(destination, "") +} + func GetDestination(message OutboundQueueMessage) (string, error) { log.WithFields(log.Fields{ "command": message.Command, @@ -481,7 +496,6 @@ func GetDestination(message OutboundQueueMessage) (string, error) { switch message.Command { case 0: - // AgentExecute log.Debug("Found AgentExecute message") uintTy, err := abi.NewType("uint256", "", nil) @@ -504,79 +518,95 @@ func GetDestination(message OutboundQueueMessage) (string, error) { return "", err } - argument := abi.Arguments{ + tupleArgument := abi.Arguments{ {Type: tupleTy}, } + commandArgument := abi.Arguments{ + {Type: uintTy}, + {Type: bytesTy}, + } + transferTokenArgument := abi.Arguments{ + {Type: addressTy}, + {Type: addressTy}, + {Type: uintTy}, + } // Decode the ABI-encoded byte payload - decodedTuple, err := argument.Unpack(message.Params) + decodedTuple, err := tupleArgument.Unpack(message.Params) if err != nil { return "", fmt.Errorf("unpack tuple: %w", err) } - if len(decodedTuple) < 1 { - return "", fmt.Errorf("tuple could not be decoded") + return "", fmt.Errorf("decoded tuple not found") } - values := reflect.ValueOf(decodedTuple[0]) - commandBytes := values.FieldByName("Command").Bytes() - fmt.Println(common.Bytes2Hex(commandBytes)) - - argument = abi.Arguments{ - {Type: uintTy}, - {Type: bytesTy}, - } + tuple := reflect.ValueOf(decodedTuple[0]) + commandBytes := tuple.FieldByName("Command").Bytes() - // Decode the ABI-encoded byte payload - decodedCommand, err := argument.Unpack(commandBytes) + decodedCommand, err := commandArgument.Unpack(commandBytes) if err != nil { return "", fmt.Errorf("unpack command: %w", err) } - if len(decodedCommand) < 2 { - return "", errors.New("command could not be decoded") + return "", errors.New("decoded command not found") } - argument = abi.Arguments{ - { - Type: addressTy, - }, - { - Type: addressTy, - }, - { - Type: uintTy, - }, - } - - decodedTransferToken, err := argument.Unpack(decodedCommand[1].([]byte)) + decodedTransferToken, err := transferTokenArgument.Unpack(decodedCommand[1].([]byte)) if err != nil { return "", err } - if len(decodedTransferToken) < 3 { - return "", errors.New("transfer token could not be decoded") + return "", errors.New("decode transfer token command") } - address := decodedTransferToken[1].(common.Address) - return strings.ToLower(address.String()), nil case 6: - // TransferNativeFromAgent - log.WithFields(log.Fields{ - "params": common.Bytes2Hex(message.Params), - }).Debug("Found TransferNativeFromAgent message") + log.Debug("Found TransferNativeFromAgent message") + return recipientFromTuple(message.Params, []abi.ArgumentMarshaling{ + {Name: "AgentId", Type: "bytes32"}, + {Name: "Recipient", Type: "address"}, + {Name: "Amount", Type: "uint256"}, + }) case 9: - // TransferNativeToken - log.WithFields(log.Fields{ - "params": common.Bytes2Hex(message.Params), - }).Debug("Found TransferNativeToken message") + log.Debug("Found TransferNativeToken message") + return recipientFromTuple(message.Params, []abi.ArgumentMarshaling{ + {Name: "AgentId", Type: "bytes32"}, + {Name: "Token", Type: "address"}, + {Name: "Recipient", Type: "address"}, + {Name: "Amount", Type: "uint256"}, + }) case 11: - // MintForeignToken - log.WithFields(log.Fields{ - "params": common.Bytes2Hex(message.Params), - }).Debug("Found MintForeignToken message") + log.Debug("Found MintForeignToken message") + return recipientFromTuple(message.Params, []abi.ArgumentMarshaling{ + {Name: "AgentId", Type: "bytes32"}, + {Name: "Recipient", Type: "address"}, + {Name: "Amount", Type: "uint256"}, + }) } return "", nil } + +func recipientFromTuple(messageBytes []byte, args []abi.ArgumentMarshaling) (string, error) { + tupleTy, err := abi.NewType("tuple", "", args) + if err != nil { + return "", err + } + + tupleArgument := abi.Arguments{ + {Type: tupleTy}, + } + + decodedTuple, err := tupleArgument.Unpack(messageBytes) + if err != nil { + return "", fmt.Errorf("unpack tuple: %w", err) + } + if len(decodedTuple) < 1 { + return "", fmt.Errorf("decoded tuple not found") + } + + values := reflect.ValueOf(decodedTuple[0]) + address := values.FieldByName("Recipient").Bytes() + + return strings.ToLower(common.Bytes2Hex(address)), nil +} From 50aba8257327ec7b23df63b34145edacce4f3823 Mon Sep 17 00:00:00 2001 From: claravanstaden Date: Thu, 17 Oct 2024 08:52:03 +0200 Subject: [PATCH 14/19] finish off relayers ofac --- relayer/relays/parachain/scanner.go | 119 ++++++++++++++--------- relayer/relays/parachain/scanner_test.go | 3 + 2 files changed, 75 insertions(+), 47 deletions(-) diff --git a/relayer/relays/parachain/scanner.go b/relayer/relays/parachain/scanner.go index 998ba6bb88..15838a0054 100644 --- a/relayer/relays/parachain/scanner.go +++ b/relayer/relays/parachain/scanner.go @@ -194,11 +194,12 @@ func (s *Scanner) findTasksImpl( } isBanned, err := s.IsBanned(m) if err != nil { - return nil, fmt.Errorf("banned check: %w", err) + //return nil, fmt.Errorf("banned check: %w", err) + log.WithError(err).Fatal("error checking banned address found") } if isBanned { log.Fatal("banned address found") - return nil, errors.New("banned address found") + //return nil, errors.New("banned address found") } messages = append(messages, m) } @@ -491,9 +492,21 @@ func (s *Scanner) IsBanned(m OutboundQueueMessage) (bool, error) { func GetDestination(message OutboundQueueMessage) (string, error) { log.WithFields(log.Fields{ "command": message.Command, - "params": message.Params, + "params": common.Bytes2Hex(message.Params), }).Debug("Checking message for OFAC") + address := "" + + bytes32Ty, err := abi.NewType("bytes32", "", nil) + if err != nil { + return "", err + } + addressTy, err := abi.NewType("address", "", nil) + if err != nil { + return "", err + } + uint256Ty, err := abi.NewType("uint256", "", nil) + switch message.Command { case 0: log.Debug("Found AgentExecute message") @@ -506,10 +519,6 @@ func GetDestination(message OutboundQueueMessage) (string, error) { if err != nil { return "", err } - addressTy, err := abi.NewType("address", "", nil) - if err != nil { - return "", err - } tupleTy, err := abi.NewType("tuple", "", []abi.ArgumentMarshaling{ {Name: "AgentId", Type: "bytes32"}, {Name: "Command", Type: "bytes"}, @@ -558,55 +567,71 @@ func GetDestination(message OutboundQueueMessage) (string, error) { if len(decodedTransferToken) < 3 { return "", errors.New("decode transfer token command") } - address := decodedTransferToken[1].(common.Address) - return strings.ToLower(address.String()), nil + + addressValue := decodedTransferToken[1].(common.Address) + address = addressValue.String() case 6: log.Debug("Found TransferNativeFromAgent message") - return recipientFromTuple(message.Params, []abi.ArgumentMarshaling{ - {Name: "AgentId", Type: "bytes32"}, - {Name: "Recipient", Type: "address"}, - {Name: "Amount", Type: "uint256"}, - }) + + if err != nil { + return "", err + } + arguments := abi.Arguments{ + {Type: bytes32Ty}, + {Type: addressTy}, + {Type: uint256Ty}, + } + + decodedMessage, err := arguments.Unpack(message.Params) + if err != nil { + return "", fmt.Errorf("unpack tuple: %w", err) + } + if len(decodedMessage) < 3 { + return "", fmt.Errorf("decoded message not found") + } + + addressValue := decodedMessage[1].(common.Address) + address = addressValue.String() case 9: log.Debug("Found TransferNativeToken message") - return recipientFromTuple(message.Params, []abi.ArgumentMarshaling{ - {Name: "AgentId", Type: "bytes32"}, - {Name: "Token", Type: "address"}, - {Name: "Recipient", Type: "address"}, - {Name: "Amount", Type: "uint256"}, - }) + + arguments := abi.Arguments{ + {Type: bytes32Ty}, + {Type: addressTy}, + {Type: addressTy}, + {Type: uint256Ty}, + } + + decodedMessage, err := arguments.Unpack(message.Params) + if err != nil { + return "", fmt.Errorf("unpack tuple: %w", err) + } + if len(decodedMessage) < 4 { + return "", fmt.Errorf("decoded message not found") + } + + addressValue := decodedMessage[2].(common.Address) + address = addressValue.String() case 11: log.Debug("Found MintForeignToken message") - return recipientFromTuple(message.Params, []abi.ArgumentMarshaling{ - {Name: "AgentId", Type: "bytes32"}, - {Name: "Recipient", Type: "address"}, - {Name: "Amount", Type: "uint256"}, - }) - } - - return "", nil -} -func recipientFromTuple(messageBytes []byte, args []abi.ArgumentMarshaling) (string, error) { - tupleTy, err := abi.NewType("tuple", "", args) - if err != nil { - return "", err - } + arguments := abi.Arguments{ + {Type: bytes32Ty}, + {Type: addressTy}, + {Type: uint256Ty}, + } - tupleArgument := abi.Arguments{ - {Type: tupleTy}, - } + decodedMessage, err := arguments.Unpack(message.Params) + if err != nil { + return "", fmt.Errorf("unpack tuple: %w", err) + } + if len(decodedMessage) < 3 { + return "", fmt.Errorf("decoded message not found") + } - decodedTuple, err := tupleArgument.Unpack(messageBytes) - if err != nil { - return "", fmt.Errorf("unpack tuple: %w", err) - } - if len(decodedTuple) < 1 { - return "", fmt.Errorf("decoded tuple not found") + addressValue := decodedMessage[1].(common.Address) + address = addressValue.String() } - values := reflect.ValueOf(decodedTuple[0]) - address := values.FieldByName("Recipient").Bytes() - - return strings.ToLower(common.Bytes2Hex(address)), nil + return strings.ToLower(address), nil } diff --git a/relayer/relays/parachain/scanner_test.go b/relayer/relays/parachain/scanner_test.go index 60b067cbc4..c6738a53b1 100644 --- a/relayer/relays/parachain/scanner_test.go +++ b/relayer/relays/parachain/scanner_test.go @@ -9,6 +9,9 @@ import ( func TestGetDestination(t *testing.T) { agentExecutePayload := "000000000000000000000000000000000000000000000000000000000000002081c5ab2571199e3188135178f3c2c8e2d268be1313d029b30f534fa579b69b79000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000060000000000000000000000000774667629726ec1fabebcec0d9139bd1c8f72a2300000000000000000000000044a57ee2f2fccb85fda2b0b18ebd0d8d2333700e000000000000000000000000000000000000000000000000000000003b9aca00" decodePayloadAndCompareDestinationAddress(t, 0, agentExecutePayload, "0x44a57ee2f2fccb85fda2b0b18ebd0d8d2333700e") + + mintForeignTokenPayload := "2121cfe35065c0c33465fbada265f08e9613428a4b9eb4bb717cd7db2abf622e00000000000000000000000090a987b944cb1dcce5564e5fdecd7a54d3de27fe000000000000000000000000000000000000000000000000000000003b9aca00" + decodePayloadAndCompareDestinationAddress(t, 11, mintForeignTokenPayload, "0x90a987b944cb1dcce5564e5fdecd7a54d3de27fe") } func decodePayloadAndCompareDestinationAddress(t *testing.T, command uint8, payload, expectedAddress string) { From 06c517a4c9c9d58080c5c9ff13d3e14ffa80d2f7 Mon Sep 17 00:00:00 2001 From: claravanstaden Date: Thu, 17 Oct 2024 08:59:07 +0200 Subject: [PATCH 15/19] revert testing change --- relayer/relays/parachain/scanner.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/relayer/relays/parachain/scanner.go b/relayer/relays/parachain/scanner.go index 15838a0054..362a6ecc15 100644 --- a/relayer/relays/parachain/scanner.go +++ b/relayer/relays/parachain/scanner.go @@ -199,7 +199,7 @@ func (s *Scanner) findTasksImpl( } if isBanned { log.Fatal("banned address found") - //return nil, errors.New("banned address found") + return nil, errors.New("banned address found") } messages = append(messages, m) } From 1e9558eccbc14a06e658fb86ac3c0733c6a79f61 Mon Sep 17 00:00:00 2001 From: claravanstaden Date: Thu, 17 Oct 2024 20:33:52 +0200 Subject: [PATCH 16/19] fixes --- relayer/chain/parachain/address.go | 33 ++++++++++ relayer/chain/parachain/address_test.go | 14 +++++ relayer/relays/execution/config.go | 3 +- relayer/relays/execution/main.go | 60 ++++++++++++++++--- relayer/relays/parachain/scanner.go | 2 +- web/packages/test/config/execution-relay.json | 3 +- 6 files changed, 105 insertions(+), 10 deletions(-) create mode 100644 relayer/chain/parachain/address.go create mode 100644 relayer/chain/parachain/address_test.go diff --git a/relayer/chain/parachain/address.go b/relayer/chain/parachain/address.go new file mode 100644 index 0000000000..fef1d256be --- /dev/null +++ b/relayer/chain/parachain/address.go @@ -0,0 +1,33 @@ +package parachain + +import ( + "encoding/hex" + "fmt" + "strings" + + "github.com/decred/base58" + "golang.org/x/crypto/blake2b" +) + +func SS58Encode(pubKeyHex string, ss58Prefix uint8) (string, error) { + if strings.HasPrefix(pubKeyHex, "0x") { + pubKeyHex = pubKeyHex[2:] + } + + pubKey, err := hex.DecodeString(pubKeyHex) + if err != nil { + return "", fmt.Errorf("failed to decode hex: %w", err) + } + + address := append([]byte{ss58Prefix}, pubKey...) + + hashInput := append([]byte("SS58PRE"), address...) + + hash := blake2b.Sum512(hashInput) + checksum := hash[:2] + + fullAddress := append(address, checksum...) + + ss58Addr := base58.Encode(fullAddress) + return ss58Addr, nil +} diff --git a/relayer/chain/parachain/address_test.go b/relayer/chain/parachain/address_test.go new file mode 100644 index 0000000000..d969a35299 --- /dev/null +++ b/relayer/chain/parachain/address_test.go @@ -0,0 +1,14 @@ +package parachain + +import ( + assert "github.com/stretchr/testify/require" + "testing" +) + +func TestSS58Prefix(t *testing.T) { + address := "0x8eaf04151687736326c9fea17e25fc5287613693c912909cb226aa4794f26a48" + + ss58Address, err := SS58Encode(address, 1) + assert.NoError(t, err) + assert.Equal(t, "A1k3praCLftTgBTb6aVavh3UNKwXN599Fqov17MkEy6bwCU", ss58Address) +} diff --git a/relayer/relays/execution/config.go b/relayer/relays/execution/config.go index cdd8e57ee8..55fcedf9f9 100644 --- a/relayer/relays/execution/config.go +++ b/relayer/relays/execution/config.go @@ -47,7 +47,8 @@ type ContractsConfig struct { } type SinkConfig struct { - Parachain beaconconf.ParachainConfig `mapstructure:"parachain"` + Parachain beaconconf.ParachainConfig `mapstructure:"parachain"` + SS58Prefix uint8 `mapstructure:"ss58Prefix"` } type ChannelID [32]byte diff --git a/relayer/relays/execution/main.go b/relayer/relays/execution/main.go index 2c360e7e2f..836dd18165 100644 --- a/relayer/relays/execution/main.go +++ b/relayer/relays/execution/main.go @@ -11,6 +11,7 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" + ethtypes "github.com/ethereum/go-ethereum/core/types" "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus" "github.com/snowfork/go-substrate-rpc-client/v4/types" @@ -36,6 +37,7 @@ type Relay struct { writer *parachain.ParachainWriter headerCache *ethereum.HeaderCache ofac *ofac.OFAC + chainID *big.Int } func NewRelay( @@ -107,11 +109,17 @@ func (r *Relay) Start(ctx context.Context, eg *errgroup.Group) error { ) r.beaconHeader = &beaconHeader + r.chainID, err = r.ethconn.Client().NetworkID(ctx) + if err != nil { + return err + } + log.WithFields(log.Fields{ "relayerId": r.config.Schedule.ID, "relayerCount": r.config.Schedule.TotalRelayerCount, "sleepInterval": r.config.Schedule.SleepInterval, - }).Info("decentralization config") + "chainId": r.chainID, + }).Info("relayer config") for { select { @@ -416,16 +424,17 @@ func (r *Relay) doSubmit(ctx context.Context, ev *contracts.GatewayOutboundMessa "channelID": types.H256(ev.ChannelID).Hex(), }) - destination, err := parachain.GetDestination(ev.Payload) + source, err := r.getTransactionSender(ctx, ev) if err != nil { return err } - log.WithFields(log.Fields{ - "destination": destination, - "payload": common.Bytes2Hex(ev.Payload), - }).Info("extracted destination from message") - banned, err := r.ofac.IsBanned(ev.Raw.Address.Hex(), destination) + destination, err := r.getTransactionDestination(ev) + if err != nil { + return err + } + + banned, err := r.ofac.IsBanned(source, destination) if err != nil { return err } @@ -505,3 +514,40 @@ func (r *Relay) isInFinalizedBlock(ctx context.Context, event *contracts.Gateway return r.beaconHeader.CheckHeaderFinalized(*blockHeader.ParentBeaconRoot, r.config.InstantVerification) } + +func (r *Relay) getTransactionSender(ctx context.Context, ev *contracts.GatewayOutboundMessageAccepted) (string, error) { + tx, _, err := r.ethconn.Client().TransactionByHash(ctx, ev.Raw.TxHash) + if err != nil { + return "", err + } + + sender, err := ethtypes.Sender(ethtypes.LatestSignerForChainID(r.chainID), tx) + if err != nil { + return "", fmt.Errorf("retrieve message sender: %w", err) + } + + log.WithFields(log.Fields{ + "sender": sender, + }).Debug("extracted sender from transaction") + + return sender.Hex(), nil +} + +func (r *Relay) getTransactionDestination(ev *contracts.GatewayOutboundMessageAccepted) (string, error) { + destination, err := parachain.GetDestination(ev.Payload) + if err != nil { + return "", fmt.Errorf("fetch execution header proof: %w", err) + } + + destinationSS58, err := parachain.SS58Encode(destination, r.config.Sink.SS58Prefix) + if err != nil { + return "", fmt.Errorf("ss58 encode: %w", err) + } + + log.WithFields(log.Fields{ + "destinationSS58": destinationSS58, + "destination": destination, + }).Debug("extracted destination from message") + + return destinationSS58, nil +} diff --git a/relayer/relays/parachain/scanner.go b/relayer/relays/parachain/scanner.go index 362a6ecc15..46b89dcf7e 100644 --- a/relayer/relays/parachain/scanner.go +++ b/relayer/relays/parachain/scanner.go @@ -486,7 +486,7 @@ func (s *Scanner) IsBanned(m OutboundQueueMessage) (bool, error) { return true, err } - return s.ofac.IsBanned(destination, "") + return s.ofac.IsBanned("", destination) // TODO the source will be fetched from Subscan in a follow-up PR } func GetDestination(message OutboundQueueMessage) (string, error) { diff --git a/web/packages/test/config/execution-relay.json b/web/packages/test/config/execution-relay.json index 9effbe9f8a..ca40fdeaab 100644 --- a/web/packages/test/config/execution-relay.json +++ b/web/packages/test/config/execution-relay.json @@ -27,7 +27,8 @@ "endpoint": "ws://127.0.0.1:11144", "maxWatchedExtrinsics": 8, "headerRedundancy": 20 - } + }, + "ss58Prefix": 1 }, "instantVerification": false, "schedule": { From 9363111b50c2cf4e9d3e631eef70de6307d869eb Mon Sep 17 00:00:00 2001 From: claravanstaden Date: Thu, 17 Oct 2024 20:45:40 +0200 Subject: [PATCH 17/19] return err --- relayer/relays/parachain/scanner.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/relayer/relays/parachain/scanner.go b/relayer/relays/parachain/scanner.go index 46b89dcf7e..98647137e4 100644 --- a/relayer/relays/parachain/scanner.go +++ b/relayer/relays/parachain/scanner.go @@ -194,8 +194,8 @@ func (s *Scanner) findTasksImpl( } isBanned, err := s.IsBanned(m) if err != nil { - //return nil, fmt.Errorf("banned check: %w", err) log.WithError(err).Fatal("error checking banned address found") + return nil, fmt.Errorf("banned check: %w", err) } if isBanned { log.Fatal("banned address found") From ee432a9e1a77faa721c3f7f584a4ab7ac93434fc Mon Sep 17 00:00:00 2001 From: claravanstaden Date: Thu, 17 Oct 2024 20:46:35 +0200 Subject: [PATCH 18/19] return early --- relayer/relays/execution/main.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/relayer/relays/execution/main.go b/relayer/relays/execution/main.go index 836dd18165..7f3aa1f873 100644 --- a/relayer/relays/execution/main.go +++ b/relayer/relays/execution/main.go @@ -539,6 +539,10 @@ func (r *Relay) getTransactionDestination(ev *contracts.GatewayOutboundMessageAc return "", fmt.Errorf("fetch execution header proof: %w", err) } + if destination == "" { + return "", nil + } + destinationSS58, err := parachain.SS58Encode(destination, r.config.Sink.SS58Prefix) if err != nil { return "", fmt.Errorf("ss58 encode: %w", err) From 5da080d7be68562edfd75b447a4148832db08649 Mon Sep 17 00:00:00 2001 From: claravanstaden Date: Thu, 17 Oct 2024 20:55:49 +0200 Subject: [PATCH 19/19] add log --- relayer/relays/parachain/scanner.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/relayer/relays/parachain/scanner.go b/relayer/relays/parachain/scanner.go index 98647137e4..58a8dabad9 100644 --- a/relayer/relays/parachain/scanner.go +++ b/relayer/relays/parachain/scanner.go @@ -633,5 +633,9 @@ func GetDestination(message OutboundQueueMessage) (string, error) { address = addressValue.String() } - return strings.ToLower(address), nil + destination := strings.ToLower(address) + + log.WithField("destination", destination).Debug("extracted destination from message") + + return destination, nil }