diff --git a/db/rocksdb.go b/db/rocksdb.go index ef3be7db..7a34e47a 100644 --- a/db/rocksdb.go +++ b/db/rocksdb.go @@ -535,6 +535,7 @@ func (to *TxOutput) Addresses(p bchain.BlockChainParser) ([]string, error) { } type TxAddresses struct { + Height uint32 Inputs []TxInput Outputs []TxOutput } @@ -569,6 +570,7 @@ func (d *RocksDB) resetValueSatToZero(valueSat *big.Int, addrID []byte, logText func (d *RocksDB) processAddressesUTXO(block *bchain.Block, addresses map[string][]outpoint, txAddressesMap map[string]*TxAddresses, balances map[string]*AddrBalance) error { blockTxIDs := make([][]byte, len(block.Txs)) + blockTxAddresses := make([]*TxAddresses, len(block.Txs)) // first process all outputs so that inputs can point to txs in this block for txi := range block.Txs { tx := &block.Txs[txi] @@ -577,9 +579,10 @@ func (d *RocksDB) processAddressesUTXO(block *bchain.Block, addresses map[string return err } blockTxIDs[txi] = btxID - ta := TxAddresses{} + ta := TxAddresses{Height: block.Height} ta.Outputs = make([]TxOutput, len(tx.Vout)) txAddressesMap[string(btxID)] = &ta + blockTxAddresses[txi] = &ta for i, output := range tx.Vout { tao := &ta.Outputs[i] tao.ValueSat = output.ValueSat @@ -629,7 +632,7 @@ func (d *RocksDB) processAddressesUTXO(block *bchain.Block, addresses map[string for txi := range block.Txs { tx := &block.Txs[txi] spendingTxid := blockTxIDs[txi] - ta := txAddressesMap[string(spendingTxid)] + ta := blockTxAddresses[txi] ta.Inputs = make([]TxInput, len(tx.Vin)) for i, input := range tx.Vin { tai := &ta.Inputs[i] @@ -874,8 +877,8 @@ func (d *RocksDB) getTxAddresses(btxID []byte) (*TxAddresses, error) { } defer val.Free() buf := val.Data() - // 2 is minimum length of addrBalance - 1 byte inputs len, 1 byte outputs len - if len(buf) < 2 { + // 2 is minimum length of addrBalance - 1 byte height, 1 byte inputs len, 1 byte outputs len + if len(buf) < 3 { return nil, nil } return unpackTxAddresses(buf) @@ -892,7 +895,9 @@ func (d *RocksDB) GetTxAddresses(txid string) (*TxAddresses, error) { func packTxAddresses(ta *TxAddresses, buf []byte, varBuf []byte) []byte { buf = buf[:0] - l := packVaruint(uint(len(ta.Inputs)), varBuf) + l := packVaruint(uint(ta.Height), varBuf) + buf = append(buf, varBuf[:l]...) + l = packVaruint(uint(len(ta.Inputs)), varBuf) buf = append(buf, varBuf[:l]...) for i := range ta.Inputs { buf = appendTxInput(&ta.Inputs[i], buf, varBuf) @@ -930,7 +935,10 @@ func appendTxOutput(txo *TxOutput, buf []byte, varBuf []byte) []byte { func unpackTxAddresses(buf []byte) (*TxAddresses, error) { ta := TxAddresses{} - inputs, l := unpackVaruint(buf) + height, l := unpackVaruint(buf) + ta.Height = uint32(height) + inputs, ll := unpackVaruint(buf[l:]) + l += ll ta.Inputs = make([]TxInput, inputs) for i := uint(0); i < inputs; i++ { l += unpackTxInput(&ta.Inputs[i], buf[l:]) diff --git a/db/rocksdb_test.go b/db/rocksdb_test.go index cd33f6ed..7c61a5a1 100644 --- a/db/rocksdb_test.go +++ b/db/rocksdb_test.go @@ -16,6 +16,7 @@ import ( "strings" "testing" + vlq "github.com/bsm/go-vlq" "github.com/juju/errors" ) @@ -85,6 +86,12 @@ func bigintToHex(i *big.Int) string { return hex.EncodeToString(b[:l]) } +func varuintToHex(i uint) string { + b := make([]byte, vlq.MaxLen64) + l := vlq.PutUint(b, uint64(i)) + return hex.EncodeToString(b[:l]) +} + // keyPair is used to compare given key value in DB with expected // for more complicated compares it is possible to specify CompareFunc type keyPair struct { @@ -382,14 +389,18 @@ func verifyAfterUTXOBlock1(t *testing.T, d *RocksDB, afterDisconnect bool) { if err := checkColumn(d, cfTxAddresses, []keyPair{ keyPair{ txidB1T1, - "00" + "02" + + varuintToHex(225493) + + "00" + + "02" + addressToPubKeyHexWithLength(addr1, t, d) + bigintToHex(satB1T1A1) + addressToPubKeyHexWithLength(addr2, t, d) + bigintToHex(satB1T1A2), nil, }, keyPair{ txidB1T2, - "00" + "03" + + varuintToHex(225493) + + "00" + + "03" + addressToPubKeyHexWithLength(addr3, t, d) + bigintToHex(satB1T2A3) + addressToPubKeyHexWithLength(addr4, t, d) + bigintToHex(satB1T2A4) + addressToPubKeyHexWithLength(addr5, t, d) + bigintToHex(satB1T2A5), @@ -464,14 +475,18 @@ func verifyAfterUTXOBlock2(t *testing.T, d *RocksDB) { if err := checkColumn(d, cfTxAddresses, []keyPair{ keyPair{ txidB1T1, - "00" + "02" + + varuintToHex(225493) + + "00" + + "02" + addressToPubKeyHexWithLength(addr1, t, d) + bigintToHex(satB1T1A1) + spentAddressToPubKeyHexWithLength(addr2, t, d) + bigintToHex(satB1T1A2), nil, }, keyPair{ txidB1T2, - "00" + "03" + + varuintToHex(225493) + + "00" + + "03" + spentAddressToPubKeyHexWithLength(addr3, t, d) + bigintToHex(satB1T2A3) + spentAddressToPubKeyHexWithLength(addr4, t, d) + bigintToHex(satB1T2A4) + spentAddressToPubKeyHexWithLength(addr5, t, d) + bigintToHex(satB1T2A5), @@ -479,7 +494,8 @@ func verifyAfterUTXOBlock2(t *testing.T, d *RocksDB) { }, keyPair{ txidB2T1, - "02" + + varuintToHex(225494) + + "02" + inputAddressToPubKeyHexWithLength(addr3, t, d) + bigintToHex(satB1T2A3) + inputAddressToPubKeyHexWithLength(addr2, t, d) + bigintToHex(satB1T1A2) + "02" + @@ -489,7 +505,8 @@ func verifyAfterUTXOBlock2(t *testing.T, d *RocksDB) { }, keyPair{ txidB2T2, - "02" + + varuintToHex(225494) + + "02" + inputAddressToPubKeyHexWithLength(addr6, t, d) + bigintToHex(satB2T1A6) + inputAddressToPubKeyHexWithLength(addr4, t, d) + bigintToHex(satB1T2A4) + "02" + @@ -499,7 +516,8 @@ func verifyAfterUTXOBlock2(t *testing.T, d *RocksDB) { }, keyPair{ txidB2T3, - "01" + + varuintToHex(225494) + + "01" + inputAddressToPubKeyHexWithLength(addr5, t, d) + bigintToHex(satB1T2A5) + "01" + addressToPubKeyHexWithLength(addr5, t, d) + bigintToHex(satB2T3A5), @@ -507,7 +525,8 @@ func verifyAfterUTXOBlock2(t *testing.T, d *RocksDB) { }, keyPair{ txidB2T4, - "01" + inputAddressToPubKeyHexWithLength("", t, d) + bigintToHex(satZero) + + varuintToHex(225494) + + "01" + inputAddressToPubKeyHexWithLength("", t, d) + bigintToHex(satZero) + "02" + addressToPubKeyHexWithLength(addrA, t, d) + bigintToHex(satB2T4AA) + addressToPubKeyHexWithLength("", t, d) + bigintToHex(satZero), @@ -747,6 +766,7 @@ func TestRocksDB_Index_UTXO(t *testing.T) { t.Fatal(err) } taw := &TxAddresses{ + Height: 225494, Inputs: []TxInput{ { addrID: addressToOutput(addr3, d.chainParser), @@ -929,8 +949,9 @@ func Test_packTxAddresses_unpackTxAddresses(t *testing.T) { }{ { name: "1", - hex: "0216001443aac20a116e09ea4f7914be1c55e4c17aa600b70016001454633aa8bd2e552bd4e89c01e73c1b7905eb58460811207cb68a199872012d001443aac20a116e09ea4f7914be1c55e4c17aa600b70101", + hex: "7b0216001443aac20a116e09ea4f7914be1c55e4c17aa600b70016001454633aa8bd2e552bd4e89c01e73c1b7905eb58460811207cb68a199872012d001443aac20a116e09ea4f7914be1c55e4c17aa600b70101", data: &TxAddresses{ + Height: 123, Inputs: []TxInput{ { addrID: addressToOutput("tb1qgw4vyzs3dcy75nmezjlpc40yc9a2vq9hghdyt2", parser), @@ -952,8 +973,9 @@ func Test_packTxAddresses_unpackTxAddresses(t *testing.T) { }, { name: "2", - hex: "0317a9149eb21980dc9d413d8eac27314938b9da920ee53e8705021918f2c017a91409f70b896169c37981d2b54b371df0d81a136a2c870501dd7e28c017a914e371782582a4addb541362c55565d2cdf56f6498870501a1e35ec0052fa9141d9ca71efa36d814424ea6ca1437e67287aebe348705012aadcac02ea91424fbc77cdc62702ade74dcf989c15e5d3f9240bc870501664894c02fa914afbfb74ee994c7d45f6698738bc4226d065266f7870501a1e35ec03276a914d2a37ce20ac9ec4f15dd05a7c6e8e9fbdb99850e88ac043b9943603376a9146b2044146a4438e6e5bfbc65f147afeb64d14fbb88ac05012a05f200", + hex: "e0390317a9149eb21980dc9d413d8eac27314938b9da920ee53e8705021918f2c017a91409f70b896169c37981d2b54b371df0d81a136a2c870501dd7e28c017a914e371782582a4addb541362c55565d2cdf56f6498870501a1e35ec0052fa9141d9ca71efa36d814424ea6ca1437e67287aebe348705012aadcac02ea91424fbc77cdc62702ade74dcf989c15e5d3f9240bc870501664894c02fa914afbfb74ee994c7d45f6698738bc4226d065266f7870501a1e35ec03276a914d2a37ce20ac9ec4f15dd05a7c6e8e9fbdb99850e88ac043b9943603376a9146b2044146a4438e6e5bfbc65f147afeb64d14fbb88ac05012a05f200", data: &TxAddresses{ + Height: 12345, Inputs: []TxInput{ { addrID: addressToOutput("2N7iL7AvS4LViugwsdjTB13uN4T7XhV1bCP", parser), @@ -997,8 +1019,9 @@ func Test_packTxAddresses_unpackTxAddresses(t *testing.T) { }, { name: "empty address", - hex: "01000204d2020002162e010162", + hex: "baef9a1501000204d2020002162e010162", data: &TxAddresses{ + Height: 123456789, Inputs: []TxInput{ { addrID: []byte{}, @@ -1020,7 +1043,7 @@ func Test_packTxAddresses_unpackTxAddresses(t *testing.T) { }, { name: "empty", - hex: "0000", + hex: "000000", data: &TxAddresses{ Inputs: []TxInput{}, Outputs: []TxOutput{},