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

feat(webhook): add webhook #2538

Merged
merged 38 commits into from
May 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
6074411
add models and endpoint, lacking logic
shampoobera Apr 29, 2024
31aab47
just stuff
shampoobera Apr 29, 2024
b5e989a
just stuff
shampoobera Apr 29, 2024
715a453
made general db interface
shampoobera Apr 29, 2024
e2a6214
cleanup
shampoobera Apr 29, 2024
cd41cbc
trying to test
shampoobera Apr 29, 2024
444428b
trying to test
shampoobera Apr 29, 2024
18c0d51
trying ot fix test
shampoobera Apr 29, 2024
799f646
remove interface{} from gorm models, start tests, rework db interface
shampoobera Apr 29, 2024
c22d3c9
add signature
shampoobera Apr 30, 2024
6e0d109
secret
shampoobera Apr 30, 2024
9af0630
look away for now
shampoobera Apr 30, 2024
b5a29e1
finish db test
shampoobera Apr 30, 2024
496d67a
finish tests
golangisfun123 Apr 30, 2024
df7ffc6
add auth
golangisfun123 Apr 30, 2024
0b7b3e9
remove debugging log
golangisfun123 Apr 30, 2024
8b8297a
comments and nits
golangisfun123 Apr 30, 2024
f8a833b
lint
golangisfun123 Apr 30, 2024
d4ac8d6
appsecret and appid
golangisfun123 May 1, 2024
01f8b57
resolve comments
golangisfun123 May 1, 2024
7f81c14
swagger, lint
golangisfun123 May 1, 2024
1c55e8b
feat(synapse-interface): maintenance aggregator using PAUSED_CHAINS (…
bigboydiamonds Apr 30, 2024
a5a3120
Publish
bigboydiamonds Apr 30, 2024
a7e239e
Exempt gh pages (#2541)
trajan0x May 1, 2024
7d2117a
Deploy: `FastBridge` to Scroll (#2525)
ChiTimesChi May 1, 2024
4c7538c
Publish
ChiTimesChi May 1, 2024
6fec3a5
fix: update `forge-std` to 1.8.1, remove `ds-test`, use `solhint` for…
ChiTimesChi May 1, 2024
200eb8b
Publish
ChiTimesChi May 1, 2024
5dc99e4
chore: remove submodules from `contracts-rfq` (#2547)
ChiTimesChi May 1, 2024
1a3000a
Publish
ChiTimesChi May 1, 2024
b40e602
gogenerate
golangisfun123 May 1, 2024
f241759
Revert "gogenerate"
golangisfun123 May 1, 2024
d9e99a0
im dumb
golangisfun123 May 1, 2024
d7963fa
generate
golangisfun123 May 1, 2024
652b099
tidy
golangisfun123 May 1, 2024
d390ea0
update swagger doc
golangisfun123 May 1, 2024
8c215e4
[goreleaser]
trajan0x May 1, 2024
498a067
[goreleaser]
golangisfun123 May 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
14 changes: 9 additions & 5 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,21 @@
"editor.defaultFormatter": "dbaeumer.vscode-eslint"
},
"[typescriptreact]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"eslint.workingDirectories": [
{ "directory": "packages/contracts", "changeProcessCWD": true }
{
"directory": "packages/contracts",
"changeProcessCWD": true
}
],
"eslint.nodePath": "./node_modules/eslint/bin/",
"eslint.format.enable": true,
"editorconfig.generateAuto": false,
"files.trimTrailingWhitespace": true,
"solidity.packageDefaultDependenciesContractsDirectory": "contracts",
"solidity.packageDefaultDependenciesDirectory": "lib",
"solidity.compileUsingRemoteVersion": "v0.8.17",
"solidity.formatter": "prettier"
}
"solidity.compileUsingRemoteVersion": "v0.8.17+commit.8df45f5f",
"solidity.formatter": "prettier",
"solidity.defaultCompiler": "remote"
}
93 changes: 93 additions & 0 deletions contrib/screener-api/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,29 @@ package client

import (
"context"
"crypto/hmac"
"crypto/sha256"
"encoding/hex"
"fmt"
"strings"
"time"

"github.com/dubonzi/otelresty"
"github.com/go-resty/resty/v2"
"github.com/google/uuid"
"github.com/synapsecns/sanguine/core/ginhelper"
"github.com/synapsecns/sanguine/core/metrics"
)

var (
// BlacklistEndpoint is the endpoint for blacklisting an address.
BlacklistEndpoint = "/api/data/sync/"
)

// ScreenerClient is an interface for the Screener API.
type ScreenerClient interface {
ScreenAddress(ctx context.Context, ruleset, address string) (blocked bool, err error)
BlacklistAddress(ctx context.Context, appsecret string, appid string, body BlackListBody) (string, error)
}

type clientImpl struct {
Expand All @@ -37,6 +49,7 @@ type blockedResponse struct {
Blocked bool `json:"risk"`
}

// ScreenAddress checks if an address is blocked by the screener.
func (c clientImpl) ScreenAddress(ctx context.Context, ruleset, address string) (bool, error) {
var blockedRes blockedResponse
resp, err := c.rClient.R().
Expand All @@ -54,6 +67,54 @@ func (c clientImpl) ScreenAddress(ctx context.Context, ruleset, address string)
return blockedRes.Blocked, nil
}

// BlackListBody is the json payload that represents a blacklisted address.
type BlackListBody struct {
TypeReq string `json:"typereq"`
ID string `json:"id"`
Data string `json:"data"`
Address string `json:"address"`
Network string `json:"network"`
Tag string `json:"tag"`
Remark string `json:"remark"`
}
Comment on lines +70 to +79
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tip

Codebase Verification

The expanded search for validation logic within the BlacklistAddress method has provided a clear view of the method's implementation. From the output, it is evident that the method primarily focuses on generating a signature, setting up HTTP headers, and making a POST request. There is no explicit validation logic for the fields of BlackListBody such as ID, Address, or Network.

Given this information, it appears that the initial review comment pointing out the need for validation of these fields is justified. The method does not currently include any checks to ensure that the values of these fields meet expected formats, which could lead to potential issues if invalid data is processed.

Conclusion:

  • The BlacklistAddress method lacks validation for the fields of BlackListBody. This could lead to processing of invalid data, which is a significant concern for any system dealing with network addresses and identifiers.

Recommendation:

  • Implement validation logic within the BlacklistAddress method to check the formats of ID, Address, and Network fields before proceeding with the business logic.
Analysis chain

Validate the fields of BlackListBody to ensure they meet expected formats, especially for fields like ID, Address, and Network.

Scripts Executed

The following scripts were executed for the analysis:


Script:

#!/bin/bash
# Description: Check for validation logic for `BlackListBody` fields in the `BlacklistAddress` method.

# Search for validation logic in the `BlacklistAddress` method.
ast-grep --lang go --pattern $'func (c clientImpl) BlacklistAddress($_, $_, $_, $_) $_ {
  $$$
  if $_ {
    $$$
  }
  $$$
}' contrib/screener-api/client/client.go

Length of output: 164



Script:

#!/bin/bash
# Description: Broaden the search for any validation logic related to `BlackListBody` in the `BlacklistAddress` method.

# Search for any validation logic in the `BlacklistAddress` method.
ast-grep --lang go --pattern $'func (c clientImpl) BlacklistAddress($_, $_, $_, $_) $_ {
  $$$
}' contrib/screener-api/client/client.go

Length of output: 2612


type blacklistResponse struct {
Status string `json:"status"`
Error string `json:"error"`
}

func (c clientImpl) BlacklistAddress(ctx context.Context, appsecret string, appid string, body BlackListBody) (string, error) {
var blacklistRes blacklistResponse

nonce := strings.ReplaceAll(uuid.New().String(), "-", "")[:32]
timestamp := fmt.Sprintf("%d", time.Now().Unix())
queryString := ""

signature := GenerateSignature(appsecret, appid, timestamp, nonce, queryString, body)

resp, err := c.rClient.R().
SetContext(ctx).
SetHeader("Content-Type", "application/json").
SetHeader("appid", appid).
SetHeader("timestamp", timestamp).
SetHeader("nonce", nonce).
SetHeader("queryString", queryString).
SetHeader("signature", signature).
SetResult(&blacklistRes).
SetBody(body).
Post(BlacklistEndpoint)

if err != nil {
return resp.Status(), fmt.Errorf("error from server: %s: %w", resp.String(), err)
}

if resp.IsError() {
return resp.Status(), fmt.Errorf("error from server: %s", resp.String())
}

return blacklistRes.Status, nil
}

// NewNoOpClient creates a new no-op client for the Screener API.
// it returns false for every address.
func NewNoOpClient() (ScreenerClient, error) {
Expand All @@ -66,4 +127,36 @@ func (n noOpClient) ScreenAddress(_ context.Context, _, _ string) (bool, error)
return false, nil
}

func (n noOpClient) BlacklistAddress(_ context.Context, _ string, _ string, _ BlackListBody) (string, error) {
return "", nil
}

// GenerateSignature generates a signature for the request.
func GenerateSignature(secret string,
appid string,
timestamp string,
nonce string,
queryString string,
body BlackListBody,
) string {
key := []byte(secret)

// Concatenate the body.
message := fmt.Sprintf(
"%s%s%s%s%s%s%s",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

poor use of %s, just create a concat(...string) method that does this

appid,
timestamp,
nonce,
"POST",
BlacklistEndpoint,
queryString,
body,
)

h := hmac.New(sha256.New, key)
h.Write([]byte(message))

return strings.ToLower(hex.EncodeToString(h.Sum(nil)))
}

var _ ScreenerClient = noOpClient{}
4 changes: 4 additions & 0 deletions contrib/screener-api/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ import "time"

// Config is the configuration for the screener.
type Config struct {
// AppSecret is the app secret
AppSecret string `yaml:"app-secret"`
// AppID is the app id
AppID string `yaml:"app-id"`
// TRMKey is the api key for trmlabs
TRMKey string `yaml:"trm-key"`
// Rules of [caller_type]->risk_type
Expand Down
27 changes: 26 additions & 1 deletion contrib/screener-api/db/db.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,29 @@ package db
import (
"context"
"errors"
"github.com/synapsecns/sanguine/contrib/screener-api/trmlabs"
"time"

"github.com/synapsecns/sanguine/contrib/screener-api/trmlabs"
)

// BlacklistedAddressWriterDB provides methods to write blacklisted addresses to the database.
type BlacklistedAddressWriterDB interface {
golangisfun123 marked this conversation as resolved.
Show resolved Hide resolved
PutBlacklistedAddress(ctx context.Context, body BlacklistedAddress) error
DeleteBlacklistedAddress(ctx context.Context, id string) error
UpdateBlacklistedAddress(ctx context.Context, id string, body BlacklistedAddress) error
}

// BlacklistedAddressReaderDB provides methods to read blacklisted addresses from the database.
type BlacklistedAddressReaderDB interface {
golangisfun123 marked this conversation as resolved.
Show resolved Hide resolved
GetBlacklistedAddress(ctx context.Context, address string) (*BlacklistedAddress, error)
}

// BlacklistedAddressDB is the interface for reading and writing blacklisted addresses to the database.
type BlacklistedAddressDB interface {
golangisfun123 marked this conversation as resolved.
Show resolved Hide resolved
BlacklistedAddressWriterDB
BlacklistedAddressReaderDB
}

// RuleWriterDB is the interface for writing rules to the database.
type RuleWriterDB interface {
PutAddressIndicators(ctx context.Context, address string, riskIndicator []trmlabs.AddressRiskIndicator) error
Expand All @@ -24,5 +43,11 @@ type RuleDB interface {
RuleReaderDB
}

// DB is the general database interface for the screener-api.
type DB interface {
BlacklistedAddressDB
RuleDB
}

// ErrNoAddressNotCached is returned when an address is not cached.
var ErrNoAddressNotCached = errors.New("address not cached")
57 changes: 53 additions & 4 deletions contrib/screener-api/db/db_test.go
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
package db_test

import (
"time"

"github.com/brianvoe/gofakeit/v6"
"github.com/synapsecns/sanguine/contrib/screener-api/db"
"github.com/synapsecns/sanguine/contrib/screener-api/trmlabs"
"time"
"gorm.io/gorm"
)

func (d *DBSuite) TestEmpty() {
d.RunOnAllDBs(func(testDB db.RuleDB) {
d.RunOnAllDBs(func(testDB db.DB) {
testAddress := gofakeit.BitcoinAddress()

// 5 mins ago
Expand All @@ -28,8 +30,8 @@ func (d *DBSuite) TestEmpty() {
})
}

func (d *DBSuite) TestAdressUpdate() {
d.RunOnAllDBs(func(testDB db.RuleDB) {
func (d *DBSuite) TestAddressUpdate() {
d.RunOnAllDBs(func(testDB db.DB) {
testAddress := gofakeit.BitcoinAddress()

// 5 mins ago
Expand Down Expand Up @@ -64,3 +66,50 @@ func (d *DBSuite) TestAdressUpdate() {
d.Require().Error(err, db.ErrNoAddressNotCached)
})
}

func (d *DBSuite) TestBlacklist() {
d.RunOnAllDBs(func(testDB db.DB) {
testAddress := gofakeit.BitcoinAddress()

blacklistBody := db.BlacklistedAddress{
TypeReq: "create",
ID: "testId",
Address: testAddress,
Network: "bitcoin",
Tag: "testTag",
Remark: "testRemark",
}

// blacklist the address
err := testDB.PutBlacklistedAddress(d.GetTestContext(), blacklistBody)
d.Require().NoError(err)
blacklistedAddress, err := testDB.GetBlacklistedAddress(d.GetTestContext(), blacklistBody.Address)
d.Require().NoError(err)
d.Require().NotNil(blacklistedAddress)

// update the address
blacklistBody.TypeReq = "update"
blacklistBody.Remark = "testRemarkUpdated"
err = testDB.UpdateBlacklistedAddress(d.GetTestContext(), blacklistBody.ID, blacklistBody)
d.Require().NoError(err)

// check to make sure it updated
blacklistedAddress, err = testDB.GetBlacklistedAddress(d.GetTestContext(), blacklistBody.Address)
d.Require().NoError(err)
d.Require().NotNil(blacklistedAddress)
d.Require().Equal("testRemarkUpdated", blacklistedAddress.Remark)

// check for non blacklisted address
res, err := testDB.GetBlacklistedAddress(d.GetTestContext(), gofakeit.BitcoinAddress())
d.Require().EqualError(err, gorm.ErrRecordNotFound.Error())
d.Require().Nil(res)

// delete it
err = testDB.DeleteBlacklistedAddress(d.GetTestContext(), blacklistBody.ID)
d.Require().NoError(err)

// delete nonexistent
err = testDB.DeleteBlacklistedAddress(d.GetTestContext(), "NonexistentId")
d.Require().NoError(err)
})
}
19 changes: 17 additions & 2 deletions contrib/screener-api/db/models.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,27 @@ import (
"encoding/json"
"errors"
"fmt"
"github.com/synapsecns/sanguine/contrib/screener-api/trmlabs"
"gorm.io/gorm/schema"
"strings"
"time"

"github.com/synapsecns/sanguine/contrib/screener-api/trmlabs"
"gorm.io/gorm/schema"
)

// BlacklistedAddress is a blacklisted address.
type BlacklistedAddress struct {
CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"`

TypeReq string `gorm:"column:typereq" json:"typereq"`
ID string `gorm:"column:id;primary_key" json:"id"`
Data string `gorm:"column:data" json:"data"`
Address string `gorm:"column:address" json:"address"`
Network string `gorm:"column:network" json:"network"`
Tag string `gorm:"column:tag" json:"tag"`
Remark string `gorm:"column:remark" json:"remark"`
}
Comment on lines +18 to +30
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ensure consistent use of Go's convention for initialisms in variable names.

- ID      string `gorm:"column:id;primary_key" json:"id"`
+ ID      string `gorm:"column:ID;primary_key" json:"ID"`

The field ID should be consistently referred to in both the struct tag and the code to align with Go's convention for initialisms.


Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
// BlacklistedAddress is a blacklisted address.
type BlacklistedAddress struct {
CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"`
TypeReq string `gorm:"column:typereq" json:"typereq"`
ID string `gorm:"column:id;primary_key" json:"id"`
Data string `gorm:"column:data" json:"data"`
Address string `gorm:"column:address" json:"address"`
Network string `gorm:"column:network" json:"network"`
Tag string `gorm:"column:tag" json:"tag"`
Remark string `gorm:"column:remark" json:"remark"`
}
// BlacklistedAddress is a blacklisted address.
type BlacklistedAddress struct {
CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"`
TypeReq string `gorm:"column:typereq" json:"typereq"`
ID string `gorm:"column:ID;primary_key" json:"ID"`
Data string `gorm:"column:data" json:"data"`
Address string `gorm:"column:address" json:"address"`
Network string `gorm:"column:network" json:"network"`
Tag string `gorm:"column:tag" json:"tag"`
Remark string `gorm:"column:remark" json:"remark"`
}


Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a descriptive comment for the AddressIndicators struct.

+ // AddressIndicators represents the risk indicators associated with an address.

It's a good practice to provide comments for exported types to improve code readability and maintainability.


Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
// AddressIndicators represents the risk indicators associated with an address.

Add a descriptive comment for the addressRiskIndicators type.

+ // addressRiskIndicators defines a list of risk indicators for an address.

This comment will help other developers understand the purpose of this type at a glance.


Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
// addressRiskIndicators defines a list of risk indicators for an address.

Add a descriptive comment for the ToTRMLabs method.

+ // ToTRMLabs converts address risk indicators to a format used by TRMLabs.

Adding a descriptive comment for this exported method will enhance code readability and maintainability.


Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
// ToTRMLabs converts address risk indicators to a format used by TRMLabs.

Add a descriptive comment for the MakeRecord function.

+ // MakeRecord creates a new AddressIndicators record with the specified address and risk indicators.

Documenting public functions helps other developers understand their purpose and usage quickly.


Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
// MakeRecord creates a new AddressIndicators record with the specified address and risk indicators.

// AddressIndicators is the address indicators for a given address.
type AddressIndicators struct {
CreatedAt time.Time
Expand Down
Loading
Loading