diff --git a/pkg/core/transaction.go b/pkg/core/transaction.go index 0aa900ab..585b4935 100644 --- a/pkg/core/transaction.go +++ b/pkg/core/transaction.go @@ -9,5 +9,5 @@ type Transaction struct { GasLimit int64 GasPrice int64 Receipt - Value int64 + Value string } diff --git a/pkg/geth/block_to_core_block.go b/pkg/geth/block_to_core_block.go index 8cc806e8..ebed70ca 100644 --- a/pkg/geth/block_to_core_block.go +++ b/pkg/geth/block_to_core_block.go @@ -76,7 +76,7 @@ func transToCoreTrans(transaction *types.Transaction, from *common.Address) core From: strings.ToLower(addressToHex(from)), GasLimit: transaction.Gas().Int64(), GasPrice: transaction.GasPrice().Int64(), - Value: transaction.Value().Int64(), + Value: transaction.Value().String(), Data: data, } } diff --git a/pkg/geth/block_to_core_block_test.go b/pkg/geth/block_to_core_block_test.go index 22c0276b..6dc03ec5 100644 --- a/pkg/geth/block_to_core_block_test.go +++ b/pkg/geth/block_to_core_block_test.go @@ -246,7 +246,7 @@ var _ = Describe("Conversion of GethBlock to core.Block", func() { Expect(coreTransaction.From).To(Equal("0x0000000000000000000000000000000000000123")) Expect(coreTransaction.GasLimit).To(Equal(gethTransaction.Gas().Int64())) Expect(coreTransaction.GasPrice).To(Equal(gethTransaction.GasPrice().Int64())) - Expect(coreTransaction.Value).To(Equal(gethTransaction.Value().Int64())) + Expect(coreTransaction.Value).To(Equal(gethTransaction.Value().String())) Expect(coreTransaction.Nonce).To(Equal(gethTransaction.Nonce())) coreReceipt := coreTransaction.Receipt diff --git a/pkg/repositories/postgres.go b/pkg/repositories/postgres.go index 14159547..fdc92f74 100644 --- a/pkg/repositories/postgres.go +++ b/pkg/repositories/postgres.go @@ -303,7 +303,7 @@ func (repository Postgres) createTransaction(tx *sql.Tx, blockId int64, transact err := tx.QueryRow( `INSERT INTO transactions (block_id, tx_hash, tx_nonce, tx_to, tx_from, tx_gaslimit, tx_gasprice, tx_value, tx_input_data) - VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9) + VALUES ($1, $2, $3, $4, $5, $6, $7, cast(NULLIF($8, '') as NUMERIC), $9) RETURNING id`, blockId, transaction.Hash, transaction.Nonce, transaction.To, transaction.From, transaction.GasLimit, transaction.GasPrice, transaction.Value, transaction.Data). Scan(&transactionId) @@ -489,7 +489,7 @@ func (repository Postgres) loadTransactions(transactionRows *sql.Rows) []core.Tr var gasLimit int64 var gasPrice int64 var inputData string - var value int64 + var value string transactionRows.Scan(&hash, &nonce, &to, &from, &gasLimit, &gasPrice, &value, &inputData) transaction := core.Transaction{ Hash: hash, diff --git a/pkg/repositories/postgres_test.go b/pkg/repositories/postgres_test.go index ce75c2c5..3e19abfc 100644 --- a/pkg/repositories/postgres_test.go +++ b/pkg/repositories/postgres_test.go @@ -7,6 +7,8 @@ import ( "io/ioutil" "log" + "math/big" + "github.com/8thlight/vulcanizedb/pkg/config" "github.com/8thlight/vulcanizedb/pkg/core" "github.com/8thlight/vulcanizedb/pkg/repositories" @@ -38,6 +40,42 @@ var _ = Describe("Postgres repository", func() { return repository }) + It("serializes big.Int to db", func() { + // postgres driver doesn't support go big.Int type + // various casts in golang uint64, int64, overflow for + // transaction value (in wei) even though + // postgres numeric can handle an arbitrary + // sized int, so use string representation of big.Int + // and cast on insert + + cfg, _ := config.NewConfig("private") + pgConfig := config.DbConnectionString(cfg.Database) + db, err := sqlx.Connect("postgres", pgConfig) + + bi := new(big.Int) + bi.SetString("34940183920000000000", 10) + Expect(bi.String()).To(Equal("34940183920000000000")) + + defer db.Exec(`DROP TABLE IF EXISTS example`) + _, err = db.Exec("CREATE TABLE example ( id INTEGER, data NUMERIC )") + Expect(err).ToNot(HaveOccurred()) + + sqlStatement := ` + INSERT INTO example (id, data) + VALUES (1, cast($1 AS NUMERIC))` + _, err = db.Exec(sqlStatement, bi.String()) + Expect(err).ToNot(HaveOccurred()) + + var data string + err = db.QueryRow(`SELECT data FROM example WHERE id = 1`).Scan(&data) + Expect(err).ToNot(HaveOccurred()) + + Expect(bi.String()).To(Equal(data)) + actual := new(big.Int) + actual.SetString(data, 10) + Expect(actual).To(Equal(bi)) + }) + It("does not commit block if block is invalid", func() { //badNonce violates db Nonce field length badNonce := fmt.Sprintf("x %s", strings.Repeat("1", 100)) diff --git a/pkg/repositories/testing/helpers.go b/pkg/repositories/testing/helpers.go index 899b0987..c258f041 100644 --- a/pkg/repositories/testing/helpers.go +++ b/pkg/repositories/testing/helpers.go @@ -4,6 +4,8 @@ import ( "sort" "strconv" + "math/big" + "github.com/8thlight/vulcanizedb/pkg/core" "github.com/8thlight/vulcanizedb/pkg/repositories" . "github.com/onsi/ginkgo" @@ -198,7 +200,8 @@ func AssertRepositoryBehavior(buildRepository func(node core.Node) repositories. nonce := uint64(10000) to := "1234567890" from := "0987654321" - value := int64(10) + var value = new(big.Int) + value.SetString("34940183920000000000", 10) inputData := "0xf7d8c8830000000000000000000000000000000000000000000000000000000000037788000000000000000000000000000000000000000000000000000000000003bd14" transaction := core.Transaction{ Hash: "x1234", @@ -207,7 +210,7 @@ func AssertRepositoryBehavior(buildRepository func(node core.Node) repositories. Nonce: nonce, To: to, From: from, - Value: value, + Value: value.String(), Data: inputData, } block := core.Block{ @@ -227,7 +230,7 @@ func AssertRepositoryBehavior(buildRepository func(node core.Node) repositories. Expect(savedTransaction.Nonce).To(Equal(nonce)) Expect(savedTransaction.GasLimit).To(Equal(gasLimit)) Expect(savedTransaction.GasPrice).To(Equal(gasPrice)) - Expect(savedTransaction.Value).To(Equal(value)) + Expect(savedTransaction.Value).To(Equal(value.String())) }) })