From 14b29696a3194a4dc7019882c13bef8d9fc4f943 Mon Sep 17 00:00:00 2001 From: Dustin Brickwood Date: Tue, 24 Apr 2018 13:12:58 -0400 Subject: [PATCH] modified write accounts --- shyftDb/postgres_setup/create_tables.psql | 16 +- shyftdb/shyft_database_util.go | 224 ++++++++++++---------- 2 files changed, 130 insertions(+), 110 deletions(-) diff --git a/shyftDb/postgres_setup/create_tables.psql b/shyftDb/postgres_setup/create_tables.psql index d501365a54..59f9730587 100644 --- a/shyftDb/postgres_setup/create_tables.psql +++ b/shyftDb/postgres_setup/create_tables.psql @@ -5,14 +5,18 @@ CREATE TABLE IF NOT EXISTS blocks ( ); CREATE TABLE IF NOT EXISTS txs ( - txHash text, - to_addr text, - from_addr text, - blockhash text, + txHash text primary key, + to_addr text references accounts(addr), + from_addr text references accounts(addr), + blockhash text references blocks(hash), amount numeric, gasprice numeric, gas numeric, nonce numeric, - data bytea, - block text references blocks(hash) + data bytea +); + +CREATE TABLE IF NOT EXISTS accounts ( + addr text primary key unique, + balance numeric ); \ No newline at end of file diff --git a/shyftdb/shyft_database_util.go b/shyftdb/shyft_database_util.go index f86381a83b..344f8fd71a 100644 --- a/shyftdb/shyft_database_util.go +++ b/shyftdb/shyft_database_util.go @@ -1,16 +1,12 @@ package shyftdb import ( - "bytes" - "encoding/gob" "encoding/json" "fmt" "math/big" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/log" - "github.com/syndtr/goleveldb/leveldb" "database/sql" @@ -62,17 +58,22 @@ type ShyftTxEntryPretty struct { } type ShyftAccountEntry struct { - Balance *big.Int + Balance string Txs []string } +type ShyftSenderEntry struct { + Address string + Balance *big.Int +} + //WriteBlock writes to block info to sql db func WriteBlock(sqldb *sql.DB, block *types.Block) error { coinbase := block.Header().Coinbase.String() number := block.Header().Number.String() sqlStatement := `INSERT INTO blocks(hash, coinbase, number) VALUES(($1), ($2), ($3)) RETURNING number` - qerr := sqldb.QueryRow(sqlStatement, block.Header().Hash().Hex(), coinbase, number).Scan(&number) //.Scan(&fun) + qerr := sqldb.QueryRow(sqlStatement, block.Header().Hash().Hex(), coinbase, number).Scan(&number) if qerr != nil { panic(qerr) } @@ -80,7 +81,7 @@ func WriteBlock(sqldb *sql.DB, block *types.Block) error { if block.Transactions().Len() > 0 { for _, tx := range block.Transactions() { WriteTransactions(sqldb, tx, block.Header().Hash()) - //tx_bytes[i] = tx.Hash().Bytes() + WriteFromBalance(sqldb, tx) } } return nil @@ -118,127 +119,142 @@ func WriteTransactions(sqldb *sql.DB, tx *types.Transaction, blockHash common.Ha return nil } -//WriteAccountBalances(db, tx) +//WriteSenderBalance writes senders balance to accounts db +func WriteFromBalance(sqldb *sql.DB, tx *types.Transaction) error { + sender := ShyftSenderEntry{ + Address: tx.From().Hex(), + Balance: tx.Value(), + } + + addr := sender.Address + balance := sender.Balance.String() + fmt.Println("++++++++++++++++++++++", addr) + fmt.Println("++++++++++++++++++++++", balance) + sqlStatement := `INSERT INTO accounts(addr, balance) VALUES(($1), ($2)) RETURNING addr` + qerr := sqldb.QueryRow(sqlStatement, addr, balance).Scan(&addr) + if qerr != nil { + panic(qerr) + } + return nil +} + +// key := append([]byte("acc-")[:], tx.From().Hash().Bytes()[:]...) +// // The from (sender) addr must have balance. If it fails to retrieve there is a bigger issue. +// retrievedData, err := db.Get(key, nil) +// if err != nil { +// log.Crit("From MUST have eth and no record found", "err", err) +// } +// var decodedData ShyftAccountEntry +// d := gob.NewDecoder(bytes.NewBuffer(retrievedData)) +// if err := d.Decode(&decodedData); err != nil { +// log.Crit("Failed to decode From data:", "err", err) +// } +// decodedData.Balance.Sub(decodedData.Balance, tx.Value()) +// decodedData.Txs = append(decodedData.Txs, tx.Hash().String()) +// // Encode updated data +// var encodedData bytes.Buffer +// encoder := gob.NewEncoder(&encodedData) +// if err := encoder.Encode(decodedData); err != nil { +// log.Crit("Faild to encode From Account data", "err", err) +// } +// if err := db.Put(key, encodedData.Bytes(), nil); err != nil { +// log.Crit("Could not write the From account data", "err", err) +// } + +// func WriteToBalance(db *leveldb.DB, tx *types.Transaction) { +// key := append([]byte("acc-")[:], tx.To().Hash().Bytes()[:]...) +// var txs []string -// func WriteFromBalance(db *leveldb.DB, tx *types.Transaction) { -// key := append([]byte("acc-")[:], tx.From().Hash().Bytes()[:]...) -// // The from (sender) addr must have balance. If it fails to retrieve there is a bigger issue. // retrievedData, err := db.Get(key, nil) // if err != nil { -// log.Crit("From MUST have eth and no record found", "err", err) +// accData := ShyftAccountEntry{ +// Balance: tx.Value(), +// Txs: append(txs, tx.Hash().String()), +// } +// var encodedData bytes.Buffer +// encoder := gob.NewEncoder(&encodedData) +// if err := encoder.Encode(accData); err != nil { +// log.Crit("Faild to encode To Account data", "err", err) +// } +// if err := db.Put(key, encodedData.Bytes(), nil); err != nil { +// log.Crit("Could not write the TO account's first tx", "err", err) +// } // } // var decodedData ShyftAccountEntry // d := gob.NewDecoder(bytes.NewBuffer(retrievedData)) // if err := d.Decode(&decodedData); err != nil { -// log.Crit("Failed to decode From data:", "err", err) +// log.Crit("Failed to decode To account data:", "err", err) // } -// decodedData.Balance.Sub(decodedData.Balance, tx.Value()) +// decodedData.Balance.Add(decodedData.Balance, tx.Value()) // decodedData.Txs = append(decodedData.Txs, tx.Hash().String()) // // Encode updated data // var encodedData bytes.Buffer // encoder := gob.NewEncoder(&encodedData) // if err := encoder.Encode(decodedData); err != nil { -// log.Crit("Faild to encode From Account data", "err", err) +// log.Crit("Faild to encode To Account data", "err", err) // } // if err := db.Put(key, encodedData.Bytes(), nil); err != nil { -// log.Crit("Could not write the From account data", "err", err) +// log.Crit("Could not write the To account data", "err", err) // } // } -func WriteToBalance(db *leveldb.DB, tx *types.Transaction) { - key := append([]byte("acc-")[:], tx.To().Hash().Bytes()[:]...) - var txs []string - - retrievedData, err := db.Get(key, nil) - if err != nil { - accData := ShyftAccountEntry{ - Balance: tx.Value(), - Txs: append(txs, tx.Hash().String()), - } - var encodedData bytes.Buffer - encoder := gob.NewEncoder(&encodedData) - if err := encoder.Encode(accData); err != nil { - log.Crit("Faild to encode To Account data", "err", err) - } - if err := db.Put(key, encodedData.Bytes(), nil); err != nil { - log.Crit("Could not write the TO account's first tx", "err", err) - } - } - var decodedData ShyftAccountEntry - d := gob.NewDecoder(bytes.NewBuffer(retrievedData)) - if err := d.Decode(&decodedData); err != nil { - log.Crit("Failed to decode To account data:", "err", err) - } - decodedData.Balance.Add(decodedData.Balance, tx.Value()) - decodedData.Txs = append(decodedData.Txs, tx.Hash().String()) - // Encode updated data - var encodedData bytes.Buffer - encoder := gob.NewEncoder(&encodedData) - if err := encoder.Encode(decodedData); err != nil { - log.Crit("Faild to encode To Account data", "err", err) - } - if err := db.Put(key, encodedData.Bytes(), nil); err != nil { - log.Crit("Could not write the To account data", "err", err) - } -} - // @NOTE: This function is extremely complex and requires heavy testing and knowdlege of edge cases: // uncle blocks, account balance updates based on reorgs, diverges that get dropped. // Reason for this is because the accounts are not deterministic like the block and tx hashes. // @TODO: Calculate reward if there are uncles // @TODO: Calculate mining reward (most likely retrieve higher up in the operations) // @TODO: Calculate reorg -func WriteMinerReward(db *leveldb.DB, block *types.Block) { - var totalGas *big.Int - var txs []string - key := append([]byte("acc-")[:], block.Coinbase().Hash().Bytes()[:]...) - for _, tx := range block.Transactions() { - totalGas.Add(totalGas, new(big.Int).Mul(tx.GasPrice(), new(big.Int).SetUint64(tx.Gas()))) - } - retrievedData, err := db.Get(key, nil) - if err != nil { - // Assume time this account has had a tx - // Balacne is exclusively minerreward + total gas from the block b/c no prior evm activity - // Txs would be empty because they have not had any transactions on the EVM - // @TODO: Calc mining reward - //balance := totalGas.Add(totalGas, MINING_REWARD) - balance := totalGas - accData := ShyftAccountEntry{ - Balance: balance, - Txs: txs, - } - var encodedData bytes.Buffer - encoder := gob.NewEncoder(&encodedData) - if err := encoder.Encode(accData); err != nil { - log.Crit("Faild to encode Miner Account data", "err", err) - } - if err := db.Put(key, encodedData.Bytes(), nil); err != nil { - log.Crit("Could not write the miner's first tx", "err", err) - } - } else { - // The account has already have previous data stored due to activity in the EVM - // Decode the data to update balance - var decodedData ShyftAccountEntry - d := gob.NewDecoder(bytes.NewBuffer(retrievedData)) - if err := d.Decode(&decodedData); err != nil { - log.Crit("Failed to decode miner data:", "err", err) - } - // Write new balance - // @TODO: Calc mining reward - // decodedData.Balance.Add(decodedData.Balance, totalGas.Add(totalGas, MINING_REWARD))) - decodedData.Balance.Add(decodedData.Balance, totalGas) - // Encode the data to be written back to the db - var encodedData bytes.Buffer - encoder := gob.NewEncoder(&encodedData) - if err := encoder.Encode(decodedData); err != nil { - log.Crit("Faild to encode Miner Account data", "err", err) - } - // Write newly encoded data back to the db - if err := db.Put(key, encodedData.Bytes(), nil); err != nil { - log.Crit("Could not update miner account data", "err", err) - } - } -} +// func WriteMinerReward(db *leveldb.DB, block *types.Block) { +// var totalGas *big.Int +// var txs []string +// key := append([]byte("acc-")[:], block.Coinbase().Hash().Bytes()[:]...) +// for _, tx := range block.Transactions() { +// totalGas.Add(totalGas, new(big.Int).Mul(tx.GasPrice(), new(big.Int).SetUint64(tx.Gas()))) +// } +// retrievedData, err := db.Get(key, nil) +// if err != nil { +// // Assume time this account has had a tx +// // Balacne is exclusively minerreward + total gas from the block b/c no prior evm activity +// // Txs would be empty because they have not had any transactions on the EVM +// // @TODO: Calc mining reward +// //balance := totalGas.Add(totalGas, MINING_REWARD) +// balance := totalGas +// accData := ShyftAccountEntry{ +// Balance: balance, +// Txs: txs, +// } +// var encodedData bytes.Buffer +// encoder := gob.NewEncoder(&encodedData) +// if err := encoder.Encode(accData); err != nil { +// log.Crit("Faild to encode Miner Account data", "err", err) +// } +// if err := db.Put(key, encodedData.Bytes(), nil); err != nil { +// log.Crit("Could not write the miner's first tx", "err", err) +// } +// } else { +// // The account has already have previous data stored due to activity in the EVM +// // Decode the data to update balance +// var decodedData ShyftAccountEntry +// d := gob.NewDecoder(bytes.NewBuffer(retrievedData)) +// if err := d.Decode(&decodedData); err != nil { +// log.Crit("Failed to decode miner data:", "err", err) +// } +// // Write new balance +// // @TODO: Calc mining reward +// // decodedData.Balance.Add(decodedData.Balance, totalGas.Add(totalGas, MINING_REWARD))) +// decodedData.Balance.Add(decodedData.Balance, totalGas) +// // Encode the data to be written back to the db +// var encodedData bytes.Buffer +// encoder := gob.NewEncoder(&encodedData) +// if err := encoder.Encode(decodedData); err != nil { +// log.Crit("Faild to encode Miner Account data", "err", err) +// } +// // Write newly encoded data back to the db +// if err := db.Put(key, encodedData.Bytes(), nil); err != nil { +// log.Crit("Could not update miner account data", "err", err) +// } +// } +// } /////////// // Getters