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

store incoming transactions in a database #1828

Merged
merged 6 commits into from
Mar 5, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
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
1 change: 1 addition & 0 deletions integration/obscurogateway/tengateway_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ func TestTenGateway(t *testing.T) {
VerboseFlag: false,
DBType: "sqlite",
TenChainID: 443,
StoreIncomingTxs: true,
}

tenGwContainer := container.NewWalletExtensionContainerFromConfig(tenGatewayConf, testlog.Logger())
Expand Down
1 change: 1 addition & 0 deletions tools/walletextension/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,5 @@ type Config struct {
DBType string
DBConnectionURL string
TenChainID int
StoreIncomingTxs bool
}
6 changes: 6 additions & 0 deletions tools/walletextension/main/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@ const (
tenChainIDName = "tenChainID"
tenChainIDDefault = 443
tenChainIDFlagUsage = "ChainID of Ten network that the gateway is communicating with"

storeIncomingTxs = "storeIncomingTxs"
storeIncomingTxsDefault = true
storeIncomingTxsUsage = "Flag to enable storing incoming transactions in the database for debugging purposes. Default: true"
)

func parseCLIArgs() config.Config {
Expand All @@ -70,6 +74,7 @@ func parseCLIArgs() config.Config {
dbType := flag.String(dbTypeFlagName, dbTypeFlagDefault, dbTypeFlagUsage)
dbConnectionURL := flag.String(dbConnectionURLFlagName, dbConnectionURLFlagDefault, dbConnectionURLFlagUsage)
tenChainID := flag.Int(tenChainIDName, tenChainIDDefault, tenChainIDFlagUsage)
storeIncomingTransactions := flag.Bool(storeIncomingTxs, storeIncomingTxsDefault, storeIncomingTxsUsage)
flag.Parse()

return config.Config{
Expand All @@ -84,5 +89,6 @@ func parseCLIArgs() config.Config {
DBType: *dbType,
DBConnectionURL: *dbConnectionURL,
TenChainID: *tenChainID,
StoreIncomingTxs: *storeIncomingTransactions,
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/*
This is a migration file for MariaDB that creates transactions table for storing incoming transactions
*/

CREATE TABLE IF NOT EXISTS ogdb.transactions (
id INT AUTO_INCREMENT PRIMARY KEY,
user_id varbinary(20),
tx TEXT,
tx_time DATETIME DEFAULT CURRENT_TIMESTAMP
Copy link
Collaborator

Choose a reason for hiding this comment

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

Wonder if it be possible to store the tx hash as well or is that going to be too expensive to figure out on the fly? Just thinking about being able to do lookups if investigating an issue.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

added tx_hash

);
15 changes: 15 additions & 0 deletions tools/walletextension/storage/database/mariadb/mariadb.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,3 +142,18 @@ func (m *MariaDB) GetAllUsers() ([]common.UserDB, error) {

return users, nil
}

func (m *MariaDB) StoreTransaction(rawTx string, userID []byte) error {
stmt, err := m.db.Prepare("INSERT INTO transactions(user_id, tx) VALUES (?, ?)")
if err != nil {
return err
}
defer stmt.Close()

_, err = stmt.Exec(userID, rawTx)
if err != nil {
return err
}

return nil
}
27 changes: 27 additions & 0 deletions tools/walletextension/storage/database/sqlite/sqlite.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,18 @@ func NewSqliteDatabase(dbPath string) (*Database, error) {
return nil, err
}

// create transactions table
_, err = db.Exec(`CREATE TABLE IF NOT EXISTS transactions (
id INTEGER PRIMARY KEY AUTOINCREMENT,
user_id binary(20),
tx TEXT,
tx_time TEXT DEFAULT (datetime('now'))
) ;`)

if err != nil {
return nil, err
}

return &Database{db: db}, nil
}

Expand Down Expand Up @@ -187,3 +199,18 @@ func createOrLoad(dbPath string) (string, error) {

return dbPath, nil
}

func (s *Database) StoreTransaction(rawTx string, userID []byte) error {
stmt, err := s.db.Prepare("INSERT INTO transactions(user_id, tx) VALUES (?, ?)")
if err != nil {
return err
}
defer stmt.Close()

_, err = stmt.Exec(userID, rawTx)
if err != nil {
return err
}

return nil
}
1 change: 1 addition & 0 deletions tools/walletextension/storage/storage.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ type Storage interface {
AddAccount(userID []byte, accountAddress []byte, signature []byte) error
GetAccounts(userID []byte) ([]common.AccountDB, error)
GetAllUsers() ([]common.UserDB, error)
StoreTransaction(rawTx string, userID []byte) error
}

func New(dbType string, dbConnectionURL, dbPath string) (Storage, error) {
Expand Down
11 changes: 11 additions & 0 deletions tools/walletextension/storage/storage_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ var tests = map[string]func(storage Storage, t *testing.T){
"testAddAndGetAccounts": testAddAndGetAccounts,
"testDeleteUser": testDeleteUser,
"testGetAllUsers": testGetAllUsers,
"testStoringNewTx": testStoringNewTx,
}

func TestSQLiteGatewayDB(t *testing.T) {
Expand Down Expand Up @@ -144,3 +145,13 @@ func testGetAllUsers(storage Storage, t *testing.T) {
t.Errorf("Expected user count to increase by 1. Got %d initially and %d after insert", len(initialUsers), len(afterInsertUsers))
}
}

func testStoringNewTx(storage Storage, t *testing.T) {
userID := []byte("userID")
rawTransaction := "0x0123456789"

err := storage.StoreTransaction(rawTransaction, userID)
if err != nil {
t.Fatal(err)
}
}
14 changes: 14 additions & 0 deletions tools/walletextension/wallet_extension.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,20 @@ func (w *WalletExtension) ProxyEthRequest(request *common.RPCRequest, conn userc
}
}

// check if user is sending a new transaction and if we should store it in the database for debugging purposes
if request.Method == rpc.SendRawTransaction && w.config.StoreIncomingTxs {
userIDBytes, err := common.GetUserIDbyte(hexUserID)
if err != nil {
w.Logger().Error(fmt.Errorf("error decoding string (%s), %w", hexUserID[2:], err).Error())
return nil, errors.New("error decoding userID. It should be in hex format")
}
err = w.storage.StoreTransaction(request.Params[0].(string), userIDBytes)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Are we 100% certain that the first param exists, can be cast to a string and will have "0x" as the first two characters so you can strip them off?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Things are checked in a function that calls that function, but added additional check there to avoid an edge case that might happen.

if err != nil {
w.Logger().Error(fmt.Errorf("error storing transaction in the database: %w", err).Error())
return nil, err
}
}

// get account manager for current user (if there is no users in the query parameters - use defaultUser for WE endpoints)
selectedAccountManager, err := w.userAccountManager.GetUserAccountManager(hexUserID)
if err != nil {
Expand Down
Loading