Wallet database isolated by the network id

Wallet database refactored so that every query ensures isolation by the network id.
Network id provided when database object is created, thus it is transparent to other parts
of the wallet module.

Additionally every uniqueness index is changed to ensure that it doesn't prevent adding
object with same id but from a different network.
This commit is contained in:
Dmitry 2019-08-08 11:15:07 +03:00 committed by Dmitry Shulyak
parent 494cb5bb33
commit a67184adbd
6 changed files with 56 additions and 42 deletions

View File

@ -305,9 +305,9 @@ func (b *StatusBackend) permissionsService() gethnode.ServiceConstructor {
} }
} }
func (b *StatusBackend) walletService() gethnode.ServiceConstructor { func (b *StatusBackend) walletService(network uint64) gethnode.ServiceConstructor {
return func(*gethnode.ServiceContext) (gethnode.Service, error) { return func(*gethnode.ServiceContext) (gethnode.Service, error) {
return wallet.NewService(wallet.NewDB(b.appDB)), nil return wallet.NewService(wallet.NewDB(b.appDB, network)), nil
} }
} }
@ -328,7 +328,7 @@ func (b *StatusBackend) startNode(config *params.NodeConfig) (err error) {
services = appendIf(b.appDB != nil && b.multiaccountsDB != nil, services, b.accountsService()) services = appendIf(b.appDB != nil && b.multiaccountsDB != nil, services, b.accountsService())
services = appendIf(config.BrowsersConfig.Enabled, services, b.browsersService()) services = appendIf(config.BrowsersConfig.Enabled, services, b.browsersService())
services = appendIf(config.PermissionsConfig.Enabled, services, b.permissionsService()) services = appendIf(config.PermissionsConfig.Enabled, services, b.permissionsService())
services = appendIf(config.WalletConfig.Enabled, services, b.walletService()) services = appendIf(config.WalletConfig.Enabled, services, b.walletService(config.NetworkID))
manager := b.accountManager.GetManager() manager := b.accountManager.GetManager()
if manager == nil { if manager == nil {

View File

@ -34,7 +34,7 @@ func _0001_app_down_sql() ([]byte, error) {
) )
} }
var __0001_app_up_sql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x9c\x54\x4d\x73\x9b\x30\x14\xbc\xeb\x57\xbc\xa3\x3d\xc3\x3f\xc8\x09\xdb\xb2\xa3\x29\x15\x2d\x88\x26\x39\x31\x32\x28\x36\x13\xbe\x8a\x44\x13\xff\xfb\x8e\x40\xe2\x23\xa1\xa4\xed\x0d\x49\xef\xad\x76\xf7\x69\xd9\x07\xd8\x65\x18\x98\xbb\xf3\x30\x90\x23\x50\x9f\x01\x7e\x24\x21\x0b\x41\x0a\xa5\xb2\xf2\x22\x61\x83\xd4\xad\x16\xf0\xc3\x0d\xf6\xf7\x6e\x00\xdf\x02\xf2\xd5\x0d\x9e\xe0\x0b\x7e\x72\xd0\x2f\x9e\xb7\x02\x76\x9e\xbf\x43\x5b\x78\x20\xec\xde\x8f\x18\x04\xfe\x03\x39\xdc\x21\xb4\x02\xce\x93\xa4\x6a\x4b\xa5\xc1\x79\x9a\x36\x42\xca\x65\xfc\x57\x9e\xe7\x42\xc1\xce\xf7\x3d\xec\x52\x07\x25\x57\x3e\x59\x75\xbc\x18\x7e\x64\x0e\x92\xaa\x6a\xf8\xc5\xae\xea\xf6\xfc\x22\x6e\x1d\x2f\x07\xd5\x5c\x5d\xcd\x7e\xc9\x0b\x5b\x92\x54\x79\xd5\x74\xdf\x7f\x66\x1e\x51\xf2\x3d\xc2\x40\xe8\x01\x3f\x42\x5b\x66\x3f\x5b\x11\xf7\x8c\x62\xcb\xda\xa7\x13\x2d\xfd\xd9\x16\x1e\xee\x71\x80\x87\xe5\xdd\x1a\x9c\x16\xb4\x0c\xa6\x4f\x06\xa8\x6e\xb1\x6e\xe9\xb9\xa9\x5e\xa5\x68\xb4\xa5\x59\xda\x09\x9b\x5b\x39\x68\xef\x9a\x68\xe4\x79\x0e\x52\x59\x21\xa4\xe2\x45\x0d\x51\x78\x22\x27\x8a\x0f\xb0\x23\x27\x42\x99\x83\x52\x5e\xd7\xd6\x69\x38\xe0\xa3\x1b\x79\x0c\x9e\x79\x2e\x85\x83\xae\x99\xb6\xfb\x46\xca\x54\xbc\x41\x44\xc3\xbe\x93\xd0\x15\x2b\xd7\x18\xc7\x06\x0f\x36\xc8\x6c\xc5\x56\xc1\x48\xd5\xd6\xf4\xd3\x3b\xfa\x01\x26\x27\xaa\x95\x6d\xc6\x9e\x2d\x04\xf8\x88\x03\x4c\xf7\x78\x44\xdf\xe8\x7d\x5f\x6b\xf0\x30\xc3\xb0\x77\xc3\xbd\x7b\xc0\xe8\x13\x37\xb5\x7c\x6d\xe5\xe8\xda\xc4\xcc\x7f\x93\x59\x8b\xa6\xc8\xa4\xcc\xaa\x52\x03\x6a\xe0\x78\x69\x16\x63\xd9\xfb\x93\xa9\xd8\xa1\x7d\xa6\xb5\x63\xbb\xe9\xb7\x97\xa5\xae\x11\x54\x0d\x2f\xe5\x73\xff\x74\xae\x5c\x5e\x87\x28\xf6\x0f\xd6\xf9\x10\xd1\x91\xda\x39\x7f\x89\x67\x2d\x93\xb7\xf5\x66\xf2\x27\x45\x99\x8a\x66\xa1\xa2\x11\x89\xc8\x6a\x65\xca\xf2\xea\x62\xbe\x66\xbf\x9b\x65\x1b\xec\xbd\xf3\x89\xe7\x55\xf2\x22\x37\xfd\xfe\x07\x1b\x1c\xb4\xf7\x69\xc8\x02\x97\x50\x66\xd3\x67\x95\xc7\x55\xd9\xc1\x0d\x49\x34\x51\xed\xb0\x1c\xb3\xb9\xfd\xec\xcd\xf4\xf7\xbf\x37\x71\x1e\xc2\xb6\x38\x8b\xc6\x84\xcc\xde\xb2\x98\x47\x9b\x2a\x53\x3a\x09\x82\xe0\x69\x17\xcc\x21\x95\x47\xd7\x0b\xf1\xff\xfd\x7f\x63\x55\xc5\x03\xed\xf5\x31\xcf\xa9\x8f\x67\xf2\x56\x26\xd0\xfd\x32\xde\x0f\xa8\xef\x58\x1a\x91\x3d\xf9\xab\x21\x15\xbc\xae\xb3\xf2\xa2\x67\x64\x18\xf6\x94\x2d\x23\x3b\x2b\x73\xe8\x4c\xae\xd6\x13\xfb\x1d\x00\x00\xff\xff\xee\x99\x61\xca\xe3\x06\x00\x00") var __0001_app_up_sql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xa4\x54\x5d\x93\x9a\x30\x14\x7d\xcf\xaf\xb8\x8f\x3a\xc3\x3f\xd8\x27\xd4\xe8\x66\x4a\x43\xcb\x47\x77\xf7\x89\x89\x90\x55\x46\x0c\x34\x89\x75\xfd\xf7\x9d\x00\x01\x74\x11\xbb\xd3\x37\x92\x9c\x1c\xce\x39\xf7\xde\x2c\x03\xec\x46\x18\x22\x77\xe1\x61\x20\x6b\xa0\x7e\x04\xf8\x95\x84\x51\x08\x8a\x6b\x9d\x8b\x9d\x82\x19\xd2\x97\x8a\xc3\x2f\x37\x58\x3e\xbb\x01\xfc\x08\xc8\x77\x37\x78\x83\x6f\xf8\xcd\x41\x7f\x58\x71\xe2\xb0\xf0\xfc\x05\x9a\xc3\x0b\x89\x9e\xfd\x38\x82\xc0\x7f\x21\xab\x27\x84\x26\xc8\x59\x9a\x96\x27\xa1\x0d\x39\xcb\x32\xc9\x95\x1a\xe7\x3f\xb3\xa2\xe0\x1a\x16\xbe\xef\x61\x97\x3a\x28\xdd\xb3\xc1\xaa\xd6\x15\xe1\xd7\xc8\x41\x4a\x97\x92\xed\xec\xaa\x3a\x6d\x0f\xfc\x52\xeb\x72\x50\xc5\xf4\xbe\xdd\x17\xec\x68\x21\x69\x59\x94\xb2\xfe\xbe\xaf\x3c\xa6\xe4\x67\x8c\x81\xd0\x15\x7e\x85\x93\xc8\x7f\x9f\x78\xd2\x28\x4a\xac\x6a\x9f\x0e\xbc\x34\x67\x73\x78\x79\xc6\x01\xee\x96\x4f\x53\x74\xc6\xd0\x38\x99\x39\xe9\xa8\xea\xc5\x74\xa4\x5b\x59\x9e\x15\x97\x26\xd2\x3c\xab\x8d\x5d\x47\xd9\x79\xaf\x2f\xd1\xd8\xf3\x1c\xa4\xf3\x23\x57\x9a\x1d\x2b\x88\xc3\x0d\xd9\x50\xbc\x82\x05\xd9\x10\x1a\x39\x28\x63\x55\x65\x93\x86\x15\x5e\xbb\xb1\x17\xc1\x3b\x2b\x14\x77\xd0\x3e\x37\x71\x5f\x88\xc8\xf8\x07\xc4\x34\x6c\x6e\x12\x3a\x11\xe5\x94\xe2\xa4\xe5\x83\x19\x6a\xb7\x12\xeb\xa0\x97\x6a\x31\x4d\xf5\xd6\x7e\x80\xc9\x86\x1a\x67\xb3\xfe\xce\x1c\x02\xbc\xc6\x01\xa6\x4b\xdc\xb3\xcf\xcc\xbe\x6f\x3c\x78\x38\xc2\xb0\x74\xc3\xa5\xbb\xc2\xe8\x41\x9a\xc6\xbe\x89\xb2\x4f\x6d\x10\xe6\xd7\x6c\x56\x5c\x1e\x73\xa5\xf2\x52\x18\x42\x43\x9c\x8c\xd5\xa2\x87\xdd\x9e\x0c\xcd\x76\xd7\xaf\xbc\xd6\x6a\x67\xcd\xf6\xb8\xd5\x29\x81\x5a\x32\xa1\xde\x9b\xd6\x11\x5c\x9f\x4b\x79\x30\x05\xe8\x0a\xdb\xb4\xc4\xb0\x16\x4c\xed\xbb\x79\xed\xb7\x6f\x27\xb9\x3f\xd9\x16\x87\xe4\xce\x25\xfd\xd1\x8e\xa9\xe2\x22\xe3\x72\x04\x21\x79\xca\xf3\x4a\xb7\xb0\xa2\xdc\xb5\x5f\x57\xaf\xd2\x78\x5a\xbd\x1b\xc7\x4a\xb8\xee\x91\xa2\x4c\x0f\x6a\x08\x6b\x20\x9f\x32\x74\xd0\xd2\xa7\x61\x14\xb8\x26\x88\x76\x74\x6d\x6c\x49\xc5\xa5\x1d\xe1\xfa\xbb\xa5\xb3\xf3\x3e\x33\x9c\x4e\x0b\x70\xfa\x7f\xcd\x1f\xf5\x60\xa3\xee\x3f\x8b\x22\x4e\xc7\x2d\x97\x9f\xe1\x83\xd1\xbf\x4f\xc9\x59\x56\xbf\x01\xdd\x03\xb0\x76\xbd\x70\x34\x8c\x5a\xeb\xa8\xfb\xdb\x70\xef\x5e\x6e\x94\x3e\xe2\x68\x50\x0f\xb3\xb3\xef\x68\xa2\xcb\xe4\x6b\x39\x4e\x77\xf1\xbd\x38\xd5\x45\xa4\x50\x3f\x9c\x13\xfd\xd7\x6a\x9f\xee\x40\x0b\xfa\xa7\x1e\x3c\xb2\xaa\xca\xc5\x2e\x79\x2f\x65\xd2\x5a\xee\x1c\x8f\x26\x69\xdb\xb0\x97\x73\xdb\x91\x7f\x03\x00\x00\xff\xff\xd0\x65\x6e\xd9\x13\x08\x00\x00")
func _0001_app_up_sql() ([]byte, error) { func _0001_app_up_sql() ([]byte, error) {
return bindata_read( return bindata_read(

View File

@ -44,7 +44,8 @@ FOREIGN KEY(dapp_name) REFERENCES dapps(name) ON DELETE CASCADE
CREATE TABLE IF NOT EXISTS transfers ( CREATE TABLE IF NOT EXISTS transfers (
hash VARCHAR UNIQUE, network_id UNSIGNED BIGINT NOT NULL,
hash VARCHAR NOT NULL,
address VARCHAR NOT NULL, address VARCHAR NOT NULL,
blk_hash VARCHAR NOT NULL, blk_hash VARCHAR NOT NULL,
tx BLOB, tx BLOB,
@ -52,21 +53,25 @@ sender VARCHAR NOT NULL,
receipt BLOB, receipt BLOB,
log BLOB, log BLOB,
type VARCHAR NOT NULL, type VARCHAR NOT NULL,
FOREIGN KEY(blk_hash) REFERENCES blocks(hash) ON DELETE CASCADE, FOREIGN KEY(network_id,blk_hash) REFERENCES blocks(network_id,hash) ON DELETE CASCADE,
CONSTRAINT unique_transfer_on_hash_address UNIQUE (hash,address) CONSTRAINT unique_transfer_per_address_per_network UNIQUE (hash,address,network_id)
); );
CREATE TABLE IF NOT EXISTS blocks ( CREATE TABLE IF NOT EXISTS blocks (
hash VARCHAR PRIMARY KEY, network_id UNSIGNED BIGINT NOT NULL,
number BIGINT UNIQUE NOT NULL, hash VARCHAR NOT NULL,
number BIGINT NOT NULL,
timestamp UNSIGNED BIGINT NOT NULL, timestamp UNSIGNED BIGINT NOT NULL,
head BOOL DEFAULT FALSE head BOOL DEFAULT FALSE,
) WITHOUT ROWID; CONSTRAINT unique_block_per_network UNIQUE (network_id,hash)
CONSTRAINT unique_block_number_per_network UNIQUE (network_id,number)
);
CREATE TABLE IF NOT EXISTS accounts_to_blocks ( CREATE TABLE IF NOT EXISTS accounts_to_blocks (
network_id UNSIGNED BIGINT NOT NULL,
address VARCHAR NOT NULL, address VARCHAR NOT NULL,
blk_number BIGINT NOT NULL, blk_number BIGINT NOT NULL,
sync INT, sync INT,
FOREIGN KEY(blk_number) REFERENCES blocks(number) ON DELETE CASCADE, FOREIGN KEY(network_id,blk_number) REFERENCES blocks(network_id,number) ON DELETE CASCADE,
CONSTRAINT unique_mapping_on_address_block_number UNIQUE (address,blk_number) CONSTRAINT unique_mapping_for_account_to_block_per_network UNIQUE (address,blk_number,network_id)
); );

View File

@ -96,13 +96,14 @@ func (blob *JSONBlob) Value() (driver.Value, error) {
return json.Marshal(blob.data) return json.Marshal(blob.data)
} }
func NewDB(db *sql.DB) *Database { func NewDB(db *sql.DB, network uint64) *Database {
return &Database{db} return &Database{db: db, network: network}
} }
// Database sql wrapper for operations with wallet objects. // Database sql wrapper for operations with wallet objects.
type Database struct { type Database struct {
db *sql.DB db *sql.DB
network uint64
} }
// Close closes database. // Close closes database.
@ -130,21 +131,21 @@ func (db Database) ProcessTranfers(transfers []Transfer, accounts []common.Addre
if err != nil { if err != nil {
return return
} }
err = insertHeaders(tx, added) err = insertHeaders(tx, db.network, added)
if err != nil { if err != nil {
return return
} }
err = insertTransfers(tx, transfers) err = insertTransfers(tx, db.network, transfers)
if err != nil { if err != nil {
return return
} }
err = updateAccounts(tx, accounts, added, option) err = updateAccounts(tx, db.network, accounts, added, option)
return return
} }
// GetTransfersByAddress loads transfers for a given address between two blocks. // GetTransfersByAddress loads transfers for a given address between two blocks.
func (db *Database) GetTransfersByAddress(address common.Address, start, end *big.Int) (rst []Transfer, err error) { func (db *Database) GetTransfersByAddress(address common.Address, start, end *big.Int) (rst []Transfer, err error) {
query := newTransfersQuery().FilterAddress(address).FilterStart(start).FilterEnd(end) query := newTransfersQuery().FilterNetwork(db.network).FilterAddress(address).FilterStart(start).FilterEnd(end)
rows, err := db.db.Query(query.String(), query.Args()...) rows, err := db.db.Query(query.String(), query.Args()...)
if err != nil { if err != nil {
return return
@ -155,7 +156,7 @@ func (db *Database) GetTransfersByAddress(address common.Address, start, end *bi
// GetTransfers load transfers transfer betweeen two blocks. // GetTransfers load transfers transfer betweeen two blocks.
func (db *Database) GetTransfers(start, end *big.Int) (rst []Transfer, err error) { func (db *Database) GetTransfers(start, end *big.Int) (rst []Transfer, err error) {
query := newTransfersQuery().FilterStart(start).FilterEnd(end) query := newTransfersQuery().FilterNetwork(db.network).FilterStart(start).FilterEnd(end)
rows, err := db.db.Query(query.String(), query.Args()...) rows, err := db.db.Query(query.String(), query.Args()...)
if err != nil { if err != nil {
return return
@ -174,7 +175,7 @@ func (db *Database) SaveHeaders(headers []*types.Header) (err error) {
if err != nil { if err != nil {
return return
} }
insert, err = tx.Prepare("INSERT INTO blocks(number, hash, timestamp) VALUES (?, ?, ?)") insert, err = tx.Prepare("INSERT INTO blocks(network_id, number, hash, timestamp) VALUES (?, ?, ?, ?)")
if err != nil { if err != nil {
return return
} }
@ -187,7 +188,7 @@ func (db *Database) SaveHeaders(headers []*types.Header) (err error) {
}() }()
for _, h := range headers { for _, h := range headers {
_, err = insert.Exec((*SQLBigInt)(h.Number), h.Hash(), h.Time) _, err = insert.Exec(db.network, (*SQLBigInt)(h.Number), h.Hash(), h.Time)
if err != nil { if err != nil {
return return
} }
@ -204,7 +205,7 @@ func (db *Database) SaveSyncedHeader(address common.Address, header *types.Heade
if err != nil { if err != nil {
return return
} }
insert, err = tx.Prepare("INSERT INTO accounts_to_blocks(address, blk_number, sync) VALUES (?,?,?)") insert, err = tx.Prepare("INSERT INTO accounts_to_blocks(network_id, address, blk_number, sync) VALUES (?, ?,?,?)")
if err != nil { if err != nil {
return return
} }
@ -215,7 +216,7 @@ func (db *Database) SaveSyncedHeader(address common.Address, header *types.Heade
_ = tx.Rollback() _ = tx.Rollback()
} }
}() }()
_, err = insert.Exec(address, (*SQLBigInt)(header.Number), option) _, err = insert.Exec(db.network, address, (*SQLBigInt)(header.Number), option)
if err != nil { if err != nil {
return return
} }
@ -225,7 +226,7 @@ func (db *Database) SaveSyncedHeader(address common.Address, header *types.Heade
// HeaderExists checks if header with hash exists in db. // HeaderExists checks if header with hash exists in db.
func (db *Database) HeaderExists(hash common.Hash) (bool, error) { func (db *Database) HeaderExists(hash common.Hash) (bool, error) {
var val sql.NullBool var val sql.NullBool
err := db.db.QueryRow("SELECT EXISTS (SELECT hash FROM blocks WHERE hash = ?)", hash).Scan(&val) err := db.db.QueryRow("SELECT EXISTS (SELECT hash FROM blocks WHERE hash = ? AND network_id = ?)", hash, db.network).Scan(&val)
if err != nil { if err != nil {
return false, err return false, err
} }
@ -235,7 +236,7 @@ func (db *Database) HeaderExists(hash common.Hash) (bool, error) {
// GetHeaderByNumber selects header using block number. // GetHeaderByNumber selects header using block number.
func (db *Database) GetHeaderByNumber(number *big.Int) (header *DBHeader, err error) { func (db *Database) GetHeaderByNumber(number *big.Int) (header *DBHeader, err error) {
header = &DBHeader{Hash: common.Hash{}, Number: new(big.Int)} header = &DBHeader{Hash: common.Hash{}, Number: new(big.Int)}
err = db.db.QueryRow("SELECT hash,number FROM blocks WHERE number = ?", (*SQLBigInt)(number)).Scan(&header.Hash, (*SQLBigInt)(header.Number)) err = db.db.QueryRow("SELECT hash,number FROM blocks WHERE number = ? AND network_id = ?", (*SQLBigInt)(number), db.network).Scan(&header.Hash, (*SQLBigInt)(header.Number))
if err == nil { if err == nil {
return header, nil return header, nil
} }
@ -247,7 +248,7 @@ func (db *Database) GetHeaderByNumber(number *big.Int) (header *DBHeader, err er
func (db *Database) GetLastHead() (header *DBHeader, err error) { func (db *Database) GetLastHead() (header *DBHeader, err error) {
header = &DBHeader{Hash: common.Hash{}, Number: new(big.Int)} header = &DBHeader{Hash: common.Hash{}, Number: new(big.Int)}
err = db.db.QueryRow("SELECT hash,number FROM blocks WHERE head = 1 AND number = (SELECT MAX(number) FROM blocks)").Scan(&header.Hash, (*SQLBigInt)(header.Number)) err = db.db.QueryRow("SELECT hash,number FROM blocks WHERE network_id = $1 AND head = 1 AND number = (SELECT MAX(number) FROM blocks WHERE network_id = $1)", db.network).Scan(&header.Hash, (*SQLBigInt)(header.Number))
if err == nil { if err == nil {
return header, nil return header, nil
} }
@ -261,8 +262,8 @@ func (db *Database) GetLastHead() (header *DBHeader, err error) {
func (db *Database) GetLatestSynced(address common.Address, option SyncOption) (header *DBHeader, err error) { func (db *Database) GetLatestSynced(address common.Address, option SyncOption) (header *DBHeader, err error) {
header = &DBHeader{Hash: common.Hash{}, Number: new(big.Int)} header = &DBHeader{Hash: common.Hash{}, Number: new(big.Int)}
err = db.db.QueryRow(` err = db.db.QueryRow(`
SELECT blocks.hash, blk_number FROM accounts_to_blocks JOIN blocks ON blk_number = blocks.number WHERE address = $1 AND blk_number SELECT blocks.hash, blk_number FROM accounts_to_blocks JOIN blocks ON blk_number = blocks.number WHERE blocks.network_id = $1 AND address = $2 AND blk_number
= (SELECT MAX(blk_number) FROM accounts_to_blocks WHERE address = $1 AND sync & $2 = $2)`, address, option).Scan(&header.Hash, (*SQLBigInt)(header.Number)) = (SELECT MAX(blk_number) FROM accounts_to_blocks WHERE network_id = $1 AND address = $2 AND sync & $3 = $3)`, db.network, address, option).Scan(&header.Hash, (*SQLBigInt)(header.Number))
if err == nil { if err == nil {
return header, nil return header, nil
} }
@ -291,13 +292,13 @@ func deleteHeaders(creator statementCreator, headers []*DBHeader) error {
return nil return nil
} }
func insertHeaders(creator statementCreator, headers []*DBHeader) error { func insertHeaders(creator statementCreator, network uint64, headers []*DBHeader) error {
insert, err := creator.Prepare("INSERT OR IGNORE INTO blocks(hash, number, timestamp, head) VALUES (?, ?, ?, ?)") insert, err := creator.Prepare("INSERT OR IGNORE INTO blocks(network_id, hash, number, timestamp, head) VALUES (?, ?, ?, ?, ?)")
if err != nil { if err != nil {
return err return err
} }
for _, h := range headers { for _, h := range headers {
_, err = insert.Exec(h.Hash, (*SQLBigInt)(h.Number), h.Timestamp, h.Head) _, err = insert.Exec(network, h.Hash, (*SQLBigInt)(h.Number), h.Timestamp, h.Head)
if err != nil { if err != nil {
return err return err
} }
@ -305,13 +306,13 @@ func insertHeaders(creator statementCreator, headers []*DBHeader) error {
return nil return nil
} }
func insertTransfers(creator statementCreator, transfers []Transfer) error { func insertTransfers(creator statementCreator, network uint64, transfers []Transfer) error {
insert, err := creator.Prepare("INSERT OR IGNORE INTO transfers(hash, blk_hash, address, tx, sender, receipt, log, type) VALUES (?, ?, ?, ?, ?, ?, ?, ?)") insert, err := creator.Prepare("INSERT OR IGNORE INTO transfers(network_id, hash, blk_hash, address, tx, sender, receipt, log, type) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)")
if err != nil { if err != nil {
return err return err
} }
for _, t := range transfers { for _, t := range transfers {
_, err = insert.Exec(t.ID, t.BlockHash, t.Address, &JSONBlob{t.Transaction}, t.From, &JSONBlob{t.Receipt}, &JSONBlob{t.Log}, t.Type) _, err = insert.Exec(network, t.ID, t.BlockHash, t.Address, &JSONBlob{t.Transaction}, t.From, &JSONBlob{t.Receipt}, &JSONBlob{t.Log}, t.Type)
if err != nil { if err != nil {
return err return err
} }
@ -319,18 +320,18 @@ func insertTransfers(creator statementCreator, transfers []Transfer) error {
return nil return nil
} }
func updateAccounts(creator statementCreator, accounts []common.Address, headers []*DBHeader, option SyncOption) error { func updateAccounts(creator statementCreator, network uint64, accounts []common.Address, headers []*DBHeader, option SyncOption) error {
update, err := creator.Prepare("UPDATE accounts_to_blocks SET sync=sync|? WHERE address=? AND blk_number=?") update, err := creator.Prepare("UPDATE accounts_to_blocks SET sync=sync|? WHERE address=? AND blk_number=? AND network_id=?")
if err != nil { if err != nil {
return err return err
} }
insert, err := creator.Prepare("INSERT OR IGNORE INTO accounts_to_blocks(address,blk_number,sync) VALUES(?,?,?)") insert, err := creator.Prepare("INSERT OR IGNORE INTO accounts_to_blocks(network_id,address,blk_number,sync) VALUES(?,?,?,?)")
if err != nil { if err != nil {
return err return err
} }
for _, acc := range accounts { for _, acc := range accounts {
for _, h := range headers { for _, h := range headers {
rst, err := update.Exec(option, acc, (*SQLBigInt)(h.Number)) rst, err := update.Exec(option, acc, (*SQLBigInt)(h.Number), network)
if err != nil { if err != nil {
return err return err
} }
@ -341,7 +342,7 @@ func updateAccounts(creator statementCreator, accounts []common.Address, headers
if affected > 0 { if affected > 0 {
continue continue
} }
_, err = insert.Exec(acc, (*SQLBigInt)(h.Number), option) _, err = insert.Exec(network, acc, (*SQLBigInt)(h.Number), option)
if err != nil { if err != nil {
return err return err
} }

View File

@ -17,7 +17,7 @@ func setupTestDB(t *testing.T) (*Database, func()) {
require.NoError(t, err) require.NoError(t, err)
db, err := appdatabase.InitializeDB(tmpfile.Name(), "wallet-tests") db, err := appdatabase.InitializeDB(tmpfile.Name(), "wallet-tests")
require.NoError(t, err) require.NoError(t, err)
return NewDB(db), func() { return NewDB(db, 1777), func() {
require.NoError(t, db.Close()) require.NoError(t, db.Close())
require.NoError(t, os.Remove(tmpfile.Name())) require.NoError(t, os.Remove(tmpfile.Name()))
} }

View File

@ -51,6 +51,14 @@ func (q *transfersQuery) FilterEnd(end *big.Int) *transfersQuery {
return q return q
} }
func (q *transfersQuery) FilterNetwork(network uint64) *transfersQuery {
q.andOrWhere()
q.added = true
q.buf.WriteString(" blocks.network_id = ?")
q.args = append(q.args, network)
return q
}
func (q *transfersQuery) FilterAddress(address common.Address) *transfersQuery { func (q *transfersQuery) FilterAddress(address common.Address) *transfersQuery {
q.andOrWhere() q.andOrWhere()
q.added = true q.added = true