Add height to TxAddresses as required by explorer

This commit is contained in:
Martin Boehm 2018-08-21 13:16:29 +02:00
parent bbc47db6dd
commit 78f6162d5c
2 changed files with 49 additions and 18 deletions

View File

@ -535,6 +535,7 @@ func (to *TxOutput) Addresses(p bchain.BlockChainParser) ([]string, error) {
} }
type TxAddresses struct { type TxAddresses struct {
Height uint32
Inputs []TxInput Inputs []TxInput
Outputs []TxOutput 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 { 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)) 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 // first process all outputs so that inputs can point to txs in this block
for txi := range block.Txs { for txi := range block.Txs {
tx := &block.Txs[txi] tx := &block.Txs[txi]
@ -577,9 +579,10 @@ func (d *RocksDB) processAddressesUTXO(block *bchain.Block, addresses map[string
return err return err
} }
blockTxIDs[txi] = btxID blockTxIDs[txi] = btxID
ta := TxAddresses{} ta := TxAddresses{Height: block.Height}
ta.Outputs = make([]TxOutput, len(tx.Vout)) ta.Outputs = make([]TxOutput, len(tx.Vout))
txAddressesMap[string(btxID)] = &ta txAddressesMap[string(btxID)] = &ta
blockTxAddresses[txi] = &ta
for i, output := range tx.Vout { for i, output := range tx.Vout {
tao := &ta.Outputs[i] tao := &ta.Outputs[i]
tao.ValueSat = output.ValueSat tao.ValueSat = output.ValueSat
@ -629,7 +632,7 @@ func (d *RocksDB) processAddressesUTXO(block *bchain.Block, addresses map[string
for txi := range block.Txs { for txi := range block.Txs {
tx := &block.Txs[txi] tx := &block.Txs[txi]
spendingTxid := blockTxIDs[txi] spendingTxid := blockTxIDs[txi]
ta := txAddressesMap[string(spendingTxid)] ta := blockTxAddresses[txi]
ta.Inputs = make([]TxInput, len(tx.Vin)) ta.Inputs = make([]TxInput, len(tx.Vin))
for i, input := range tx.Vin { for i, input := range tx.Vin {
tai := &ta.Inputs[i] tai := &ta.Inputs[i]
@ -874,8 +877,8 @@ func (d *RocksDB) getTxAddresses(btxID []byte) (*TxAddresses, error) {
} }
defer val.Free() defer val.Free()
buf := val.Data() buf := val.Data()
// 2 is minimum length of addrBalance - 1 byte inputs len, 1 byte outputs len // 2 is minimum length of addrBalance - 1 byte height, 1 byte inputs len, 1 byte outputs len
if len(buf) < 2 { if len(buf) < 3 {
return nil, nil return nil, nil
} }
return unpackTxAddresses(buf) return unpackTxAddresses(buf)
@ -892,7 +895,9 @@ func (d *RocksDB) GetTxAddresses(txid string) (*TxAddresses, error) {
func packTxAddresses(ta *TxAddresses, buf []byte, varBuf []byte) []byte { func packTxAddresses(ta *TxAddresses, buf []byte, varBuf []byte) []byte {
buf = buf[:0] 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]...) buf = append(buf, varBuf[:l]...)
for i := range ta.Inputs { for i := range ta.Inputs {
buf = appendTxInput(&ta.Inputs[i], buf, varBuf) 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) { func unpackTxAddresses(buf []byte) (*TxAddresses, error) {
ta := TxAddresses{} 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) ta.Inputs = make([]TxInput, inputs)
for i := uint(0); i < inputs; i++ { for i := uint(0); i < inputs; i++ {
l += unpackTxInput(&ta.Inputs[i], buf[l:]) l += unpackTxInput(&ta.Inputs[i], buf[l:])

View File

@ -16,6 +16,7 @@ import (
"strings" "strings"
"testing" "testing"
vlq "github.com/bsm/go-vlq"
"github.com/juju/errors" "github.com/juju/errors"
) )
@ -85,6 +86,12 @@ func bigintToHex(i *big.Int) string {
return hex.EncodeToString(b[:l]) 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 // keyPair is used to compare given key value in DB with expected
// for more complicated compares it is possible to specify CompareFunc // for more complicated compares it is possible to specify CompareFunc
type keyPair struct { type keyPair struct {
@ -382,14 +389,18 @@ func verifyAfterUTXOBlock1(t *testing.T, d *RocksDB, afterDisconnect bool) {
if err := checkColumn(d, cfTxAddresses, []keyPair{ if err := checkColumn(d, cfTxAddresses, []keyPair{
keyPair{ keyPair{
txidB1T1, txidB1T1,
"00" + "02" + varuintToHex(225493) +
"00" +
"02" +
addressToPubKeyHexWithLength(addr1, t, d) + bigintToHex(satB1T1A1) + addressToPubKeyHexWithLength(addr1, t, d) + bigintToHex(satB1T1A1) +
addressToPubKeyHexWithLength(addr2, t, d) + bigintToHex(satB1T1A2), addressToPubKeyHexWithLength(addr2, t, d) + bigintToHex(satB1T1A2),
nil, nil,
}, },
keyPair{ keyPair{
txidB1T2, txidB1T2,
"00" + "03" + varuintToHex(225493) +
"00" +
"03" +
addressToPubKeyHexWithLength(addr3, t, d) + bigintToHex(satB1T2A3) + addressToPubKeyHexWithLength(addr3, t, d) + bigintToHex(satB1T2A3) +
addressToPubKeyHexWithLength(addr4, t, d) + bigintToHex(satB1T2A4) + addressToPubKeyHexWithLength(addr4, t, d) + bigintToHex(satB1T2A4) +
addressToPubKeyHexWithLength(addr5, t, d) + bigintToHex(satB1T2A5), addressToPubKeyHexWithLength(addr5, t, d) + bigintToHex(satB1T2A5),
@ -464,14 +475,18 @@ func verifyAfterUTXOBlock2(t *testing.T, d *RocksDB) {
if err := checkColumn(d, cfTxAddresses, []keyPair{ if err := checkColumn(d, cfTxAddresses, []keyPair{
keyPair{ keyPair{
txidB1T1, txidB1T1,
"00" + "02" + varuintToHex(225493) +
"00" +
"02" +
addressToPubKeyHexWithLength(addr1, t, d) + bigintToHex(satB1T1A1) + addressToPubKeyHexWithLength(addr1, t, d) + bigintToHex(satB1T1A1) +
spentAddressToPubKeyHexWithLength(addr2, t, d) + bigintToHex(satB1T1A2), spentAddressToPubKeyHexWithLength(addr2, t, d) + bigintToHex(satB1T1A2),
nil, nil,
}, },
keyPair{ keyPair{
txidB1T2, txidB1T2,
"00" + "03" + varuintToHex(225493) +
"00" +
"03" +
spentAddressToPubKeyHexWithLength(addr3, t, d) + bigintToHex(satB1T2A3) + spentAddressToPubKeyHexWithLength(addr3, t, d) + bigintToHex(satB1T2A3) +
spentAddressToPubKeyHexWithLength(addr4, t, d) + bigintToHex(satB1T2A4) + spentAddressToPubKeyHexWithLength(addr4, t, d) + bigintToHex(satB1T2A4) +
spentAddressToPubKeyHexWithLength(addr5, t, d) + bigintToHex(satB1T2A5), spentAddressToPubKeyHexWithLength(addr5, t, d) + bigintToHex(satB1T2A5),
@ -479,7 +494,8 @@ func verifyAfterUTXOBlock2(t *testing.T, d *RocksDB) {
}, },
keyPair{ keyPair{
txidB2T1, txidB2T1,
"02" + varuintToHex(225494) +
"02" +
inputAddressToPubKeyHexWithLength(addr3, t, d) + bigintToHex(satB1T2A3) + inputAddressToPubKeyHexWithLength(addr3, t, d) + bigintToHex(satB1T2A3) +
inputAddressToPubKeyHexWithLength(addr2, t, d) + bigintToHex(satB1T1A2) + inputAddressToPubKeyHexWithLength(addr2, t, d) + bigintToHex(satB1T1A2) +
"02" + "02" +
@ -489,7 +505,8 @@ func verifyAfterUTXOBlock2(t *testing.T, d *RocksDB) {
}, },
keyPair{ keyPair{
txidB2T2, txidB2T2,
"02" + varuintToHex(225494) +
"02" +
inputAddressToPubKeyHexWithLength(addr6, t, d) + bigintToHex(satB2T1A6) + inputAddressToPubKeyHexWithLength(addr6, t, d) + bigintToHex(satB2T1A6) +
inputAddressToPubKeyHexWithLength(addr4, t, d) + bigintToHex(satB1T2A4) + inputAddressToPubKeyHexWithLength(addr4, t, d) + bigintToHex(satB1T2A4) +
"02" + "02" +
@ -499,7 +516,8 @@ func verifyAfterUTXOBlock2(t *testing.T, d *RocksDB) {
}, },
keyPair{ keyPair{
txidB2T3, txidB2T3,
"01" + varuintToHex(225494) +
"01" +
inputAddressToPubKeyHexWithLength(addr5, t, d) + bigintToHex(satB1T2A5) + inputAddressToPubKeyHexWithLength(addr5, t, d) + bigintToHex(satB1T2A5) +
"01" + "01" +
addressToPubKeyHexWithLength(addr5, t, d) + bigintToHex(satB2T3A5), addressToPubKeyHexWithLength(addr5, t, d) + bigintToHex(satB2T3A5),
@ -507,7 +525,8 @@ func verifyAfterUTXOBlock2(t *testing.T, d *RocksDB) {
}, },
keyPair{ keyPair{
txidB2T4, txidB2T4,
"01" + inputAddressToPubKeyHexWithLength("", t, d) + bigintToHex(satZero) + varuintToHex(225494) +
"01" + inputAddressToPubKeyHexWithLength("", t, d) + bigintToHex(satZero) +
"02" + "02" +
addressToPubKeyHexWithLength(addrA, t, d) + bigintToHex(satB2T4AA) + addressToPubKeyHexWithLength(addrA, t, d) + bigintToHex(satB2T4AA) +
addressToPubKeyHexWithLength("", t, d) + bigintToHex(satZero), addressToPubKeyHexWithLength("", t, d) + bigintToHex(satZero),
@ -747,6 +766,7 @@ func TestRocksDB_Index_UTXO(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
taw := &TxAddresses{ taw := &TxAddresses{
Height: 225494,
Inputs: []TxInput{ Inputs: []TxInput{
{ {
addrID: addressToOutput(addr3, d.chainParser), addrID: addressToOutput(addr3, d.chainParser),
@ -929,8 +949,9 @@ func Test_packTxAddresses_unpackTxAddresses(t *testing.T) {
}{ }{
{ {
name: "1", name: "1",
hex: "0216001443aac20a116e09ea4f7914be1c55e4c17aa600b70016001454633aa8bd2e552bd4e89c01e73c1b7905eb58460811207cb68a199872012d001443aac20a116e09ea4f7914be1c55e4c17aa600b70101", hex: "7b0216001443aac20a116e09ea4f7914be1c55e4c17aa600b70016001454633aa8bd2e552bd4e89c01e73c1b7905eb58460811207cb68a199872012d001443aac20a116e09ea4f7914be1c55e4c17aa600b70101",
data: &TxAddresses{ data: &TxAddresses{
Height: 123,
Inputs: []TxInput{ Inputs: []TxInput{
{ {
addrID: addressToOutput("tb1qgw4vyzs3dcy75nmezjlpc40yc9a2vq9hghdyt2", parser), addrID: addressToOutput("tb1qgw4vyzs3dcy75nmezjlpc40yc9a2vq9hghdyt2", parser),
@ -952,8 +973,9 @@ func Test_packTxAddresses_unpackTxAddresses(t *testing.T) {
}, },
{ {
name: "2", name: "2",
hex: "0317a9149eb21980dc9d413d8eac27314938b9da920ee53e8705021918f2c017a91409f70b896169c37981d2b54b371df0d81a136a2c870501dd7e28c017a914e371782582a4addb541362c55565d2cdf56f6498870501a1e35ec0052fa9141d9ca71efa36d814424ea6ca1437e67287aebe348705012aadcac02ea91424fbc77cdc62702ade74dcf989c15e5d3f9240bc870501664894c02fa914afbfb74ee994c7d45f6698738bc4226d065266f7870501a1e35ec03276a914d2a37ce20ac9ec4f15dd05a7c6e8e9fbdb99850e88ac043b9943603376a9146b2044146a4438e6e5bfbc65f147afeb64d14fbb88ac05012a05f200", hex: "e0390317a9149eb21980dc9d413d8eac27314938b9da920ee53e8705021918f2c017a91409f70b896169c37981d2b54b371df0d81a136a2c870501dd7e28c017a914e371782582a4addb541362c55565d2cdf56f6498870501a1e35ec0052fa9141d9ca71efa36d814424ea6ca1437e67287aebe348705012aadcac02ea91424fbc77cdc62702ade74dcf989c15e5d3f9240bc870501664894c02fa914afbfb74ee994c7d45f6698738bc4226d065266f7870501a1e35ec03276a914d2a37ce20ac9ec4f15dd05a7c6e8e9fbdb99850e88ac043b9943603376a9146b2044146a4438e6e5bfbc65f147afeb64d14fbb88ac05012a05f200",
data: &TxAddresses{ data: &TxAddresses{
Height: 12345,
Inputs: []TxInput{ Inputs: []TxInput{
{ {
addrID: addressToOutput("2N7iL7AvS4LViugwsdjTB13uN4T7XhV1bCP", parser), addrID: addressToOutput("2N7iL7AvS4LViugwsdjTB13uN4T7XhV1bCP", parser),
@ -997,8 +1019,9 @@ func Test_packTxAddresses_unpackTxAddresses(t *testing.T) {
}, },
{ {
name: "empty address", name: "empty address",
hex: "01000204d2020002162e010162", hex: "baef9a1501000204d2020002162e010162",
data: &TxAddresses{ data: &TxAddresses{
Height: 123456789,
Inputs: []TxInput{ Inputs: []TxInput{
{ {
addrID: []byte{}, addrID: []byte{},
@ -1020,7 +1043,7 @@ func Test_packTxAddresses_unpackTxAddresses(t *testing.T) {
}, },
{ {
name: "empty", name: "empty",
hex: "0000", hex: "000000",
data: &TxAddresses{ data: &TxAddresses{
Inputs: []TxInput{}, Inputs: []TxInput{},
Outputs: []TxOutput{}, Outputs: []TxOutput{},