mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-20 10:52:25 +00:00
signer/storage rework db_storage to support postgres sql and potentially other sql databases
This commit is contained in:
parent
bee2249e21
commit
24d0f347a6
2 changed files with 58 additions and 34 deletions
|
|
@ -20,6 +20,7 @@ import (
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
|
|
||||||
|
|
@ -32,19 +33,21 @@ import (
|
||||||
type DBStorage struct {
|
type DBStorage struct {
|
||||||
driverName string
|
driverName string
|
||||||
dataSourceName string
|
dataSourceName string
|
||||||
|
tableName string
|
||||||
db *sql.DB
|
db *sql.DB
|
||||||
key []byte
|
key []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
// KPS is the structure to hold a row of our credentials database
|
// DBRow is the structure to hold a row of our configuration database
|
||||||
type KPS struct {
|
// table schemas for all three tables (kps, js, config) are the same
|
||||||
|
type DBRow struct {
|
||||||
id int
|
id int
|
||||||
address string
|
key string
|
||||||
json string
|
val string
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewDBStorage create new database backed storage
|
// NewDBStorage create new database backed storage
|
||||||
func NewDBStorage(key []byte, driverName, dataSourceName string) (*DBStorage, error) {
|
func NewDBStorage(key []byte, driverName, dataSourceName, tableName string) (*DBStorage, error) {
|
||||||
// sql.Open only validates the input, but didn't create a connection
|
// sql.Open only validates the input, but didn't create a connection
|
||||||
db, err := sql.Open(driverName, dataSourceName)
|
db, err := sql.Open(driverName, dataSourceName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -67,6 +70,7 @@ func NewDBStorage(key []byte, driverName, dataSourceName string) (*DBStorage, er
|
||||||
return &DBStorage{
|
return &DBStorage{
|
||||||
driverName: driverName,
|
driverName: driverName,
|
||||||
dataSourceName: dataSourceName,
|
dataSourceName: dataSourceName,
|
||||||
|
tableName: tableName,
|
||||||
db: db,
|
db: db,
|
||||||
key: key,
|
key: key,
|
||||||
}, nil
|
}, nil
|
||||||
|
|
@ -84,7 +88,8 @@ func (s *DBStorage) Put(key, value string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
creds := StoredCredential{Iv: iv, CipherText: ciphertext}
|
creds := StoredCredential{Iv: iv, CipherText: ciphertext}
|
||||||
_, exist, err := s.queryRow("SELECT * FROM kps WHERE address = ?", key)
|
sql := s.formatSQL(getSQL)
|
||||||
|
_, exist, err := s.queryRow(sql, key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Warn("Failed to execute SQL", "err", err)
|
log.Warn("Failed to execute SQL", "err", err)
|
||||||
return
|
return
|
||||||
|
|
@ -97,16 +102,19 @@ func (s *DBStorage) Put(key, value string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if !exist {
|
if !exist {
|
||||||
s.exec("INSERT INTO kps (address, json) VALUES (?, ?)", key, raw)
|
sql = s.formatSQL(insertSQL)
|
||||||
|
s.exec(sql, key, raw)
|
||||||
} else {
|
} else {
|
||||||
s.exec("UPDATE kps SET json = ? WHERE address = ?", raw, key)
|
sql = s.formatSQL(updateSQL)
|
||||||
|
s.exec(sql, raw, key)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get returns the previously stored value, or an error if it does not exist or
|
// Get returns the previously stored value, or an error if it does not exist or
|
||||||
// key is of 0-length.
|
// key is of 0-length.
|
||||||
func (s *DBStorage) Get(key string) (string, error) {
|
func (s *DBStorage) Get(key string) (string, error) {
|
||||||
kps, exist, err := s.queryRow("SELECT * FROM kps WHERE address = ?", key)
|
sql := s.formatSQL(getSQL)
|
||||||
|
row, exist, err := s.queryRow(sql, key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Warn("Failed to execute SQL", "err", err)
|
log.Warn("Failed to execute SQL", "err", err)
|
||||||
return "", err
|
return "", err
|
||||||
|
|
@ -117,7 +125,7 @@ func (s *DBStorage) Get(key string) (string, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
cred := StoredCredential{}
|
cred := StoredCredential{}
|
||||||
if err = json.Unmarshal([]byte(kps.json), &cred); err != nil {
|
if err = json.Unmarshal([]byte(row.val), &cred); err != nil {
|
||||||
log.Warn("Failed to unmarshall stored json", "err", err)
|
log.Warn("Failed to unmarshall stored json", "err", err)
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
@ -133,7 +141,8 @@ func (s *DBStorage) Get(key string) (string, error) {
|
||||||
|
|
||||||
// Del removes a key-value pair. If the key doesn't exist, the method is a noop.
|
// Del removes a key-value pair. If the key doesn't exist, the method is a noop.
|
||||||
func (s *DBStorage) Del(key string) {
|
func (s *DBStorage) Del(key string) {
|
||||||
s.exec("DELETE FROM kps WHERE address = ?", key)
|
sql := s.formatSQL(deleteSQL)
|
||||||
|
s.exec(sql, key)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *DBStorage) exec(query string, args ...interface{}) {
|
func (s *DBStorage) exec(query string, args ...interface{}) {
|
||||||
|
|
@ -143,31 +152,46 @@ func (s *DBStorage) exec(query string, args ...interface{}) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *DBStorage) queryRow(query string, args ...interface{}) (*KPS, bool, error) {
|
func (s *DBStorage) queryRow(query string, args ...interface{}) (*DBRow, bool, error) {
|
||||||
kps := KPS{}
|
row := DBRow{}
|
||||||
err := s.db.QueryRow(query, args...).Scan(&kps.id, &kps.address, &kps.json)
|
err := s.db.QueryRow(query, args...).Scan(&row.id, &row.key, &row.val)
|
||||||
if err != nil && err != sql.ErrNoRows {
|
if err != nil && err != sql.ErrNoRows {
|
||||||
return nil, false, err
|
return nil, false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if kps.id == 0 {
|
if row.id == 0 {
|
||||||
return nil, false, nil
|
return nil, false, nil
|
||||||
}
|
}
|
||||||
return &kps, true, nil
|
return &row, true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
getSQL string = "SELECT * FROM tableName WHERE key = ?"
|
||||||
|
updateSQL string = "UPDATE tableName SET val = ? WHERE key = ?"
|
||||||
|
insertSQL string = "INSERT INTO tableName (key, val) VALUES (?, ?)"
|
||||||
|
deleteSQL string = "DELETE FROM tableName WHERE key = ?"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (s *DBStorage) formatSQL(sql string) string {
|
||||||
|
switch s.driverName {
|
||||||
|
case "postgres":
|
||||||
|
params := strings.Count(sql, "?")
|
||||||
|
for i := 1; i <= params; i++ {
|
||||||
|
sql = strings.Replace(sql, "?", fmt.Sprintf("$%d", i), 1)
|
||||||
|
}
|
||||||
|
case "goracle":
|
||||||
|
params := strings.Count(sql, "?")
|
||||||
|
for i := 1; i <= params; i++ {
|
||||||
|
sql = strings.Replace(sql, "?", fmt.Sprintf(":v%d", i), 1)
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
// for MS SQL Server / MySQL / SQLite
|
||||||
|
}
|
||||||
|
|
||||||
|
return strings.ReplaceAll(sql, "tableName", s.tableName)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close sql.DB
|
// Close sql.DB
|
||||||
func (s *DBStorage) Close() {
|
func (s *DBStorage) Close() {
|
||||||
s.db.Close()
|
s.db.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
|
||||||
// "root:900406.mysql@tcp(localhost:3306)/adv_database"
|
|
||||||
db, err := sql.Open("mysql", "server=localhost;user id=root;password=900406.mysql;port=3306;database=adv_database")
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println("failure")
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
fmt.Println("success")
|
|
||||||
defer db.Close()
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -18,8 +18,8 @@ func init() {
|
||||||
key = "AES256Key-32Characters1234567890"
|
key = "AES256Key-32Characters1234567890"
|
||||||
tmpDir, _ := ioutil.TempDir("", "eth-encrypted-db-storge-test")
|
tmpDir, _ := ioutil.TempDir("", "eth-encrypted-db-storge-test")
|
||||||
fmt.Println(tmpDir)
|
fmt.Println(tmpDir)
|
||||||
ds, _ = NewDBStorage([]byte(key), "sqlite3", filepath.Join(tmpDir, "test.db"))
|
ds, _ = NewDBStorage([]byte(key), "sqlite3", filepath.Join(tmpDir, "test.db"), "kps")
|
||||||
ds.exec("CREATE TABLE IF NOT EXISTS kps (id INTEGER PRIMARY KEY, address TEXT, json TEXT)")
|
ds.exec("CREATE TABLE IF NOT EXISTS kps (id INTEGER PRIMARY KEY, key TEXT, val TEXT)")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestDBStorage(t *testing.T) {
|
func TestDBStorage(t *testing.T) {
|
||||||
|
|
@ -55,10 +55,10 @@ func TestSwappedKeysForDBStorage(t *testing.T) {
|
||||||
|
|
||||||
// now make a modified copy
|
// now make a modified copy
|
||||||
swap := func() {
|
swap := func() {
|
||||||
creds1, _, _ := ds.queryRow("SELECT * FROM kps WHERE address = 'k1'")
|
creds1, _, _ := ds.queryRow("SELECT * FROM kps WHERE key = 'k1'")
|
||||||
creds2, _, _ := ds.queryRow("SELECT * FROM kps WHERE address = 'k2'")
|
creds2, _, _ := ds.queryRow("SELECT * FROM kps WHERE key = 'k2'")
|
||||||
ds.exec("UPDATE kps SET json = ? WHERE address = ?", creds1.json, "k2")
|
ds.exec("UPDATE kps SET val = ? WHERE key = ?", creds1.val, "k2")
|
||||||
ds.exec("UPDATE kps SET json = ? WHERE address = ?", creds2.json, "k1")
|
ds.exec("UPDATE kps SET val = ? WHERE key = ?", creds2.val, "k1")
|
||||||
}
|
}
|
||||||
swap()
|
swap()
|
||||||
if v, _ := ds.Get("k1"); v != "" {
|
if v, _ := ds.Get("k1"); v != "" {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue