Insert utxos in the right order in disconnect block
This commit is contained in:
parent
00b0a402ea
commit
2e37cbb974
@ -564,6 +564,10 @@ func (ab *AddrBalance) ReceivedSat() *big.Int {
|
|||||||
// addUtxo
|
// addUtxo
|
||||||
func (ab *AddrBalance) addUtxo(u *Utxo) {
|
func (ab *AddrBalance) addUtxo(u *Utxo) {
|
||||||
ab.Utxos = append(ab.Utxos, *u)
|
ab.Utxos = append(ab.Utxos, *u)
|
||||||
|
ab.manageUtxoMap(u)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ab *AddrBalance) manageUtxoMap(u *Utxo) {
|
||||||
l := len(ab.Utxos)
|
l := len(ab.Utxos)
|
||||||
if l >= 16 {
|
if l >= 16 {
|
||||||
if len(ab.utxosMap) == 0 {
|
if len(ab.utxosMap) == 0 {
|
||||||
@ -583,9 +587,45 @@ func (ab *AddrBalance) addUtxo(u *Utxo) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// on disconnect, the added utxos must be inserted in the right position so that utxosMap index works
|
||||||
|
func (ab *AddrBalance) addUtxoInDisconnect(u *Utxo) {
|
||||||
|
insert := -1
|
||||||
|
if len(ab.utxosMap) > 0 {
|
||||||
|
if i, e := ab.utxosMap[string(u.BtxID)]; e {
|
||||||
|
insert = i
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for i := range ab.Utxos {
|
||||||
|
utxo := &ab.Utxos[i]
|
||||||
|
if *(*int)(unsafe.Pointer(&utxo.BtxID[0])) == *(*int)(unsafe.Pointer(&u.BtxID[0])) && bytes.Equal(utxo.BtxID, u.BtxID) {
|
||||||
|
insert = i
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if insert > -1 {
|
||||||
|
// check if it is necessary to insert the utxo into the array
|
||||||
|
for i := insert; i < len(ab.Utxos); i++ {
|
||||||
|
utxo := &ab.Utxos[i]
|
||||||
|
// either the vout is greater than the inserted vout or it is a different tx
|
||||||
|
if utxo.Vout > u.Vout || *(*int)(unsafe.Pointer(&utxo.BtxID[0])) != *(*int)(unsafe.Pointer(&u.BtxID[0])) || !bytes.Equal(utxo.BtxID, u.BtxID) {
|
||||||
|
// found the right place, insert the utxo
|
||||||
|
ab.Utxos = append(ab.Utxos, *u)
|
||||||
|
copy(ab.Utxos[i+1:], ab.Utxos[i:])
|
||||||
|
ab.Utxos[i] = *u
|
||||||
|
// reset utxosMap after insert, the index will have to be rebuilt if needed
|
||||||
|
ab.utxosMap = nil
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ab.Utxos = append(ab.Utxos, *u)
|
||||||
|
ab.manageUtxoMap(u)
|
||||||
|
}
|
||||||
|
|
||||||
// markUtxoAsSpent finds outpoint btxID:vout in utxos and marks it as spent
|
// markUtxoAsSpent finds outpoint btxID:vout in utxos and marks it as spent
|
||||||
// for small number of utxos the linear search is done, for larger number there is a hashmap index
|
// for small number of utxos the linear search is done, for larger number there is a hashmap index
|
||||||
// it is much faster than removing the utxo from the slice as it would cause in memory copy operations
|
// it is much faster than removing the utxo from the slice as it would cause in memory reallocations
|
||||||
func (ab *AddrBalance) markUtxoAsSpent(btxID []byte, vout int32) {
|
func (ab *AddrBalance) markUtxoAsSpent(btxID []byte, vout int32) {
|
||||||
if len(ab.utxosMap) == 0 {
|
if len(ab.utxosMap) == 0 {
|
||||||
for i := range ab.Utxos {
|
for i := range ab.Utxos {
|
||||||
@ -1360,7 +1400,7 @@ func (d *RocksDB) disconnectTxAddressesInputs(wb *gorocksdb.WriteBatch, btxID []
|
|||||||
d.resetValueSatToZero(&balance.SentSat, t.AddrDesc, "sent amount")
|
d.resetValueSatToZero(&balance.SentSat, t.AddrDesc, "sent amount")
|
||||||
}
|
}
|
||||||
balance.BalanceSat.Add(&balance.BalanceSat, &t.ValueSat)
|
balance.BalanceSat.Add(&balance.BalanceSat, &t.ValueSat)
|
||||||
balance.Utxos = append(balance.Utxos, Utxo{
|
balance.addUtxoInDisconnect(&Utxo{
|
||||||
BtxID: input.btxID,
|
BtxID: input.btxID,
|
||||||
Vout: input.index,
|
Vout: input.index,
|
||||||
Height: inputHeight,
|
Height: inputHeight,
|
||||||
@ -1420,8 +1460,7 @@ func (d *RocksDB) disconnectBlock(height uint32, blockTxs []blockTxs) error {
|
|||||||
s := string(addrDesc)
|
s := string(addrDesc)
|
||||||
b, fb := balances[s]
|
b, fb := balances[s]
|
||||||
if !fb {
|
if !fb {
|
||||||
// do not use addressBalanceDetailUTXOIndexed as the utxo may be in wrong order for the helper map
|
b, err = d.GetAddrDescBalance(addrDesc, addressBalanceDetailUTXOIndexed)
|
||||||
b, err = d.GetAddrDescBalance(addrDesc, AddressBalanceDetailUTXO)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
@ -192,7 +192,7 @@ func verifyAfterBitcoinTypeBlock1(t *testing.T, d *RocksDB, afterDisconnect bool
|
|||||||
// the vout is encoded as signed varint, i.e. value * 2 for non negative values
|
// the vout is encoded as signed varint, i.e. value * 2 for non negative values
|
||||||
if err := checkColumn(d, cfAddresses, []keyPair{
|
if err := checkColumn(d, cfAddresses, []keyPair{
|
||||||
{addressKeyHex(dbtestdata.Addr1, 225493, d), txIndexesHex(dbtestdata.TxidB1T1, []int32{0}), nil},
|
{addressKeyHex(dbtestdata.Addr1, 225493, d), txIndexesHex(dbtestdata.TxidB1T1, []int32{0}), nil},
|
||||||
{addressKeyHex(dbtestdata.Addr2, 225493, d), txIndexesHex(dbtestdata.TxidB1T1, []int32{1}), nil},
|
{addressKeyHex(dbtestdata.Addr2, 225493, d), txIndexesHex(dbtestdata.TxidB1T1, []int32{1, 2}), nil},
|
||||||
{addressKeyHex(dbtestdata.Addr3, 225493, d), txIndexesHex(dbtestdata.TxidB1T2, []int32{0}), nil},
|
{addressKeyHex(dbtestdata.Addr3, 225493, d), txIndexesHex(dbtestdata.TxidB1T2, []int32{0}), nil},
|
||||||
{addressKeyHex(dbtestdata.Addr4, 225493, d), txIndexesHex(dbtestdata.TxidB1T2, []int32{1}), nil},
|
{addressKeyHex(dbtestdata.Addr4, 225493, d), txIndexesHex(dbtestdata.TxidB1T2, []int32{1}), nil},
|
||||||
{addressKeyHex(dbtestdata.Addr5, 225493, d), txIndexesHex(dbtestdata.TxidB1T2, []int32{2}), nil},
|
{addressKeyHex(dbtestdata.Addr5, 225493, d), txIndexesHex(dbtestdata.TxidB1T2, []int32{2}), nil},
|
||||||
@ -206,8 +206,9 @@ func verifyAfterBitcoinTypeBlock1(t *testing.T, d *RocksDB, afterDisconnect bool
|
|||||||
dbtestdata.TxidB1T1,
|
dbtestdata.TxidB1T1,
|
||||||
varuintToHex(225493) +
|
varuintToHex(225493) +
|
||||||
"00" +
|
"00" +
|
||||||
"02" +
|
"03" +
|
||||||
addressToPubKeyHexWithLength(dbtestdata.Addr1, t, d) + bigintToHex(dbtestdata.SatB1T1A1) +
|
addressToPubKeyHexWithLength(dbtestdata.Addr1, t, d) + bigintToHex(dbtestdata.SatB1T1A1) +
|
||||||
|
addressToPubKeyHexWithLength(dbtestdata.Addr2, t, d) + bigintToHex(dbtestdata.SatB1T1A2) +
|
||||||
addressToPubKeyHexWithLength(dbtestdata.Addr2, t, d) + bigintToHex(dbtestdata.SatB1T1A2),
|
addressToPubKeyHexWithLength(dbtestdata.Addr2, t, d) + bigintToHex(dbtestdata.SatB1T1A2),
|
||||||
nil,
|
nil,
|
||||||
},
|
},
|
||||||
@ -235,8 +236,9 @@ func verifyAfterBitcoinTypeBlock1(t *testing.T, d *RocksDB, afterDisconnect bool
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
dbtestdata.AddressToPubKeyHex(dbtestdata.Addr2, d.chainParser),
|
dbtestdata.AddressToPubKeyHex(dbtestdata.Addr2, d.chainParser),
|
||||||
"01" + bigintToHex(dbtestdata.SatZero) + bigintToHex(dbtestdata.SatB1T1A2) +
|
"01" + bigintToHex(dbtestdata.SatZero) + bigintToHex(dbtestdata.SatB1T1A2Double) +
|
||||||
dbtestdata.TxidB1T1 + varuintToHex(1) + varuintToHex(225493) + bigintToHex(dbtestdata.SatB1T1A2),
|
dbtestdata.TxidB1T1 + varuintToHex(1) + varuintToHex(225493) + bigintToHex(dbtestdata.SatB1T1A2) +
|
||||||
|
dbtestdata.TxidB1T1 + varuintToHex(2) + varuintToHex(225493) + bigintToHex(dbtestdata.SatB1T1A2),
|
||||||
nil,
|
nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -302,7 +304,7 @@ func verifyAfterBitcoinTypeBlock2(t *testing.T, d *RocksDB) {
|
|||||||
}
|
}
|
||||||
if err := checkColumn(d, cfAddresses, []keyPair{
|
if err := checkColumn(d, cfAddresses, []keyPair{
|
||||||
{addressKeyHex(dbtestdata.Addr1, 225493, d), txIndexesHex(dbtestdata.TxidB1T1, []int32{0}), nil},
|
{addressKeyHex(dbtestdata.Addr1, 225493, d), txIndexesHex(dbtestdata.TxidB1T1, []int32{0}), nil},
|
||||||
{addressKeyHex(dbtestdata.Addr2, 225493, d), txIndexesHex(dbtestdata.TxidB1T1, []int32{1}), nil},
|
{addressKeyHex(dbtestdata.Addr2, 225493, d), txIndexesHex(dbtestdata.TxidB1T1, []int32{1, 2}), nil},
|
||||||
{addressKeyHex(dbtestdata.Addr3, 225493, d), txIndexesHex(dbtestdata.TxidB1T2, []int32{0}), nil},
|
{addressKeyHex(dbtestdata.Addr3, 225493, d), txIndexesHex(dbtestdata.TxidB1T2, []int32{0}), nil},
|
||||||
{addressKeyHex(dbtestdata.Addr4, 225493, d), txIndexesHex(dbtestdata.TxidB1T2, []int32{1}), nil},
|
{addressKeyHex(dbtestdata.Addr4, 225493, d), txIndexesHex(dbtestdata.TxidB1T2, []int32{1}), nil},
|
||||||
{addressKeyHex(dbtestdata.Addr5, 225493, d), txIndexesHex(dbtestdata.TxidB1T2, []int32{2}), nil},
|
{addressKeyHex(dbtestdata.Addr5, 225493, d), txIndexesHex(dbtestdata.TxidB1T2, []int32{2}), nil},
|
||||||
@ -325,9 +327,10 @@ func verifyAfterBitcoinTypeBlock2(t *testing.T, d *RocksDB) {
|
|||||||
dbtestdata.TxidB1T1,
|
dbtestdata.TxidB1T1,
|
||||||
varuintToHex(225493) +
|
varuintToHex(225493) +
|
||||||
"00" +
|
"00" +
|
||||||
"02" +
|
"03" +
|
||||||
addressToPubKeyHexWithLength(dbtestdata.Addr1, t, d) + bigintToHex(dbtestdata.SatB1T1A1) +
|
addressToPubKeyHexWithLength(dbtestdata.Addr1, t, d) + bigintToHex(dbtestdata.SatB1T1A1) +
|
||||||
spentAddressToPubKeyHexWithLength(dbtestdata.Addr2, t, d) + bigintToHex(dbtestdata.SatB1T1A2),
|
spentAddressToPubKeyHexWithLength(dbtestdata.Addr2, t, d) + bigintToHex(dbtestdata.SatB1T1A2) +
|
||||||
|
addressToPubKeyHexWithLength(dbtestdata.Addr2, t, d) + bigintToHex(dbtestdata.SatB1T1A2),
|
||||||
nil,
|
nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -395,7 +398,8 @@ func verifyAfterBitcoinTypeBlock2(t *testing.T, d *RocksDB) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
dbtestdata.AddressToPubKeyHex(dbtestdata.Addr2, d.chainParser),
|
dbtestdata.AddressToPubKeyHex(dbtestdata.Addr2, d.chainParser),
|
||||||
"02" + bigintToHex(dbtestdata.SatB1T1A2) + bigintToHex(dbtestdata.SatZero),
|
"02" + bigintToHex(dbtestdata.SatB1T1A2) + bigintToHex(dbtestdata.SatB1T1A2) +
|
||||||
|
dbtestdata.TxidB1T1 + varuintToHex(2) + varuintToHex(225493) + bigintToHex(dbtestdata.SatB1T1A2),
|
||||||
nil,
|
nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -563,9 +567,11 @@ func TestRocksDB_Index_BitcoinType(t *testing.T) {
|
|||||||
verifyGetTransactions(t, d, dbtestdata.Addr2, 0, 1000000, []txidIndex{
|
verifyGetTransactions(t, d, dbtestdata.Addr2, 0, 1000000, []txidIndex{
|
||||||
{dbtestdata.TxidB2T1, ^1},
|
{dbtestdata.TxidB2T1, ^1},
|
||||||
{dbtestdata.TxidB1T1, 1},
|
{dbtestdata.TxidB1T1, 1},
|
||||||
|
{dbtestdata.TxidB1T1, 2},
|
||||||
}, nil)
|
}, nil)
|
||||||
verifyGetTransactions(t, d, dbtestdata.Addr2, 225493, 225493, []txidIndex{
|
verifyGetTransactions(t, d, dbtestdata.Addr2, 225493, 225493, []txidIndex{
|
||||||
{dbtestdata.TxidB1T1, 1},
|
{dbtestdata.TxidB1T1, 1},
|
||||||
|
{dbtestdata.TxidB1T1, 2},
|
||||||
}, nil)
|
}, nil)
|
||||||
verifyGetTransactions(t, d, dbtestdata.Addr2, 225494, 1000000, []txidIndex{
|
verifyGetTransactions(t, d, dbtestdata.Addr2, 225494, 1000000, []txidIndex{
|
||||||
{dbtestdata.TxidB2T1, ^1},
|
{dbtestdata.TxidB2T1, ^1},
|
||||||
@ -1101,6 +1107,213 @@ func Test_packAddrBalance_unpackAddrBalance(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func createUtxoMap(ab *AddrBalance) {
|
||||||
|
l := len(ab.Utxos)
|
||||||
|
ab.utxosMap = make(map[string]int, 32)
|
||||||
|
for i := 0; i < l; i++ {
|
||||||
|
s := string(ab.Utxos[i].BtxID)
|
||||||
|
if _, e := ab.utxosMap[s]; !e {
|
||||||
|
ab.utxosMap[s] = i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func TestAddrBalance_utxo_methods(t *testing.T) {
|
||||||
|
ab := &AddrBalance{
|
||||||
|
Txs: 10,
|
||||||
|
SentSat: *big.NewInt(10000),
|
||||||
|
BalanceSat: *big.NewInt(1000),
|
||||||
|
}
|
||||||
|
|
||||||
|
// addUtxo
|
||||||
|
ab.addUtxo(&Utxo{
|
||||||
|
BtxID: hexToBytes(dbtestdata.TxidB1T1),
|
||||||
|
Vout: 1,
|
||||||
|
Height: 5000,
|
||||||
|
ValueSat: *big.NewInt(100),
|
||||||
|
})
|
||||||
|
ab.addUtxo(&Utxo{
|
||||||
|
BtxID: hexToBytes(dbtestdata.TxidB1T1),
|
||||||
|
Vout: 4,
|
||||||
|
Height: 5000,
|
||||||
|
ValueSat: *big.NewInt(100),
|
||||||
|
})
|
||||||
|
ab.addUtxo(&Utxo{
|
||||||
|
BtxID: hexToBytes(dbtestdata.TxidB1T2),
|
||||||
|
Vout: 0,
|
||||||
|
Height: 5001,
|
||||||
|
ValueSat: *big.NewInt(800),
|
||||||
|
})
|
||||||
|
want := &AddrBalance{
|
||||||
|
Txs: 10,
|
||||||
|
SentSat: *big.NewInt(10000),
|
||||||
|
BalanceSat: *big.NewInt(1000),
|
||||||
|
Utxos: []Utxo{
|
||||||
|
Utxo{
|
||||||
|
BtxID: hexToBytes(dbtestdata.TxidB1T1),
|
||||||
|
Vout: 1,
|
||||||
|
Height: 5000,
|
||||||
|
ValueSat: *big.NewInt(100),
|
||||||
|
},
|
||||||
|
Utxo{
|
||||||
|
BtxID: hexToBytes(dbtestdata.TxidB1T1),
|
||||||
|
Vout: 4,
|
||||||
|
Height: 5000,
|
||||||
|
ValueSat: *big.NewInt(100),
|
||||||
|
},
|
||||||
|
Utxo{
|
||||||
|
BtxID: hexToBytes(dbtestdata.TxidB1T2),
|
||||||
|
Vout: 0,
|
||||||
|
Height: 5001,
|
||||||
|
ValueSat: *big.NewInt(800),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(ab, want) {
|
||||||
|
t.Errorf("addUtxo, got %+v, want %+v", ab, want)
|
||||||
|
}
|
||||||
|
|
||||||
|
// addUtxoInDisconnect
|
||||||
|
ab.addUtxoInDisconnect(&Utxo{
|
||||||
|
BtxID: hexToBytes(dbtestdata.TxidB2T1),
|
||||||
|
Vout: 0,
|
||||||
|
Height: 5003,
|
||||||
|
ValueSat: *big.NewInt(800),
|
||||||
|
})
|
||||||
|
ab.addUtxoInDisconnect(&Utxo{
|
||||||
|
BtxID: hexToBytes(dbtestdata.TxidB2T1),
|
||||||
|
Vout: 1,
|
||||||
|
Height: 5003,
|
||||||
|
ValueSat: *big.NewInt(800),
|
||||||
|
})
|
||||||
|
ab.addUtxoInDisconnect(&Utxo{
|
||||||
|
BtxID: hexToBytes(dbtestdata.TxidB1T1),
|
||||||
|
Vout: 10,
|
||||||
|
Height: 5000,
|
||||||
|
ValueSat: *big.NewInt(100),
|
||||||
|
})
|
||||||
|
ab.addUtxoInDisconnect(&Utxo{
|
||||||
|
BtxID: hexToBytes(dbtestdata.TxidB1T1),
|
||||||
|
Vout: 2,
|
||||||
|
Height: 5000,
|
||||||
|
ValueSat: *big.NewInt(100),
|
||||||
|
})
|
||||||
|
ab.addUtxoInDisconnect(&Utxo{
|
||||||
|
BtxID: hexToBytes(dbtestdata.TxidB1T1),
|
||||||
|
Vout: 0,
|
||||||
|
Height: 5000,
|
||||||
|
ValueSat: *big.NewInt(100),
|
||||||
|
})
|
||||||
|
want = &AddrBalance{
|
||||||
|
Txs: 10,
|
||||||
|
SentSat: *big.NewInt(10000),
|
||||||
|
BalanceSat: *big.NewInt(1000),
|
||||||
|
Utxos: []Utxo{
|
||||||
|
Utxo{
|
||||||
|
BtxID: hexToBytes(dbtestdata.TxidB1T1),
|
||||||
|
Vout: 0,
|
||||||
|
Height: 5000,
|
||||||
|
ValueSat: *big.NewInt(100),
|
||||||
|
},
|
||||||
|
Utxo{
|
||||||
|
BtxID: hexToBytes(dbtestdata.TxidB1T1),
|
||||||
|
Vout: 1,
|
||||||
|
Height: 5000,
|
||||||
|
ValueSat: *big.NewInt(100),
|
||||||
|
},
|
||||||
|
Utxo{
|
||||||
|
BtxID: hexToBytes(dbtestdata.TxidB1T1),
|
||||||
|
Vout: 2,
|
||||||
|
Height: 5000,
|
||||||
|
ValueSat: *big.NewInt(100),
|
||||||
|
},
|
||||||
|
Utxo{
|
||||||
|
BtxID: hexToBytes(dbtestdata.TxidB1T1),
|
||||||
|
Vout: 4,
|
||||||
|
Height: 5000,
|
||||||
|
ValueSat: *big.NewInt(100),
|
||||||
|
},
|
||||||
|
Utxo{
|
||||||
|
BtxID: hexToBytes(dbtestdata.TxidB1T1),
|
||||||
|
Vout: 10,
|
||||||
|
Height: 5000,
|
||||||
|
ValueSat: *big.NewInt(100),
|
||||||
|
},
|
||||||
|
Utxo{
|
||||||
|
BtxID: hexToBytes(dbtestdata.TxidB1T2),
|
||||||
|
Vout: 0,
|
||||||
|
Height: 5001,
|
||||||
|
ValueSat: *big.NewInt(800),
|
||||||
|
},
|
||||||
|
Utxo{
|
||||||
|
BtxID: hexToBytes(dbtestdata.TxidB2T1),
|
||||||
|
Vout: 0,
|
||||||
|
Height: 5003,
|
||||||
|
ValueSat: *big.NewInt(800),
|
||||||
|
},
|
||||||
|
Utxo{
|
||||||
|
BtxID: hexToBytes(dbtestdata.TxidB2T1),
|
||||||
|
Vout: 1,
|
||||||
|
Height: 5003,
|
||||||
|
ValueSat: *big.NewInt(800),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(ab, want) {
|
||||||
|
t.Errorf("addUtxoInDisconnect, got %+v, want %+v", ab, want)
|
||||||
|
}
|
||||||
|
|
||||||
|
// markUtxoAsSpent
|
||||||
|
ab.markUtxoAsSpent(hexToBytes(dbtestdata.TxidB2T1), 0)
|
||||||
|
want.Utxos[6].Vout = -1
|
||||||
|
if !reflect.DeepEqual(ab, want) {
|
||||||
|
t.Errorf("markUtxoAsSpent, got %+v, want %+v", ab, want)
|
||||||
|
}
|
||||||
|
|
||||||
|
// addUtxo with utxosMap
|
||||||
|
for i := 0; i < 20; i += 2 {
|
||||||
|
utxo := Utxo{
|
||||||
|
BtxID: hexToBytes(dbtestdata.TxidB2T2),
|
||||||
|
Vout: int32(i),
|
||||||
|
Height: 5009,
|
||||||
|
ValueSat: *big.NewInt(800),
|
||||||
|
}
|
||||||
|
ab.addUtxo(&utxo)
|
||||||
|
want.Utxos = append(want.Utxos, utxo)
|
||||||
|
}
|
||||||
|
createUtxoMap(want)
|
||||||
|
if !reflect.DeepEqual(ab, want) {
|
||||||
|
t.Errorf("addUtxo with utxosMap, got %+v, want %+v", ab, want)
|
||||||
|
}
|
||||||
|
|
||||||
|
// markUtxoAsSpent with utxosMap
|
||||||
|
ab.markUtxoAsSpent(hexToBytes(dbtestdata.TxidB2T1), 1)
|
||||||
|
want.Utxos[7].Vout = -1
|
||||||
|
if !reflect.DeepEqual(ab, want) {
|
||||||
|
t.Errorf("markUtxoAsSpent with utxosMap, got %+v, want %+v", ab, want)
|
||||||
|
}
|
||||||
|
|
||||||
|
// addUtxoInDisconnect with utxosMap
|
||||||
|
ab.addUtxoInDisconnect(&Utxo{
|
||||||
|
BtxID: hexToBytes(dbtestdata.TxidB1T1),
|
||||||
|
Vout: 3,
|
||||||
|
Height: 5000,
|
||||||
|
ValueSat: *big.NewInt(100),
|
||||||
|
})
|
||||||
|
want.Utxos = append(want.Utxos, Utxo{})
|
||||||
|
copy(want.Utxos[3+1:], want.Utxos[3:])
|
||||||
|
want.Utxos[3] = Utxo{
|
||||||
|
BtxID: hexToBytes(dbtestdata.TxidB1T1),
|
||||||
|
Vout: 3,
|
||||||
|
Height: 5000,
|
||||||
|
ValueSat: *big.NewInt(100),
|
||||||
|
}
|
||||||
|
want.utxosMap = nil
|
||||||
|
if !reflect.DeepEqual(ab, want) {
|
||||||
|
t.Errorf("addUtxoInDisconnect with utxosMap, got %+v, want %+v", ab, want)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
func TestRocksTickers(t *testing.T) {
|
func TestRocksTickers(t *testing.T) {
|
||||||
d := setupRocksDB(t, &testBitcoinParser{
|
d := setupRocksDB(t, &testBitcoinParser{
|
||||||
BitcoinParser: bitcoinTestnetParser(),
|
BitcoinParser: bitcoinTestnetParser(),
|
||||||
|
|||||||
@ -236,7 +236,7 @@ func httpTestsBitcoinType(t *testing.T, ts *httptest.Server) {
|
|||||||
body: []string{
|
body: []string{
|
||||||
`<a class="navbar-brand" href="/">Fake Coin Explorer</a>`,
|
`<a class="navbar-brand" href="/">Fake Coin Explorer</a>`,
|
||||||
`<h1>Address`,
|
`<h1>Address`,
|
||||||
`<small class="text-muted">0 FAKE</small>`,
|
`<small class="text-muted">0.00012345 FAKE</small>`,
|
||||||
`<span class="data">mtGXQvBowMkBpnhLckhxhbwYK44Gs9eEtz</span>`,
|
`<span class="data">mtGXQvBowMkBpnhLckhxhbwYK44Gs9eEtz</span>`,
|
||||||
`<td class="data">0.00012345 FAKE</td>`,
|
`<td class="data">0.00012345 FAKE</td>`,
|
||||||
`<a href="/tx/7c3be24063f268aaa1ed81b64776798f56088757641a34fb156c4f51ed2e9d25">7c3be24063f268aaa1ed81b64776798f56088757641a34fb156c4f51ed2e9d25</a>`,
|
`<a href="/tx/7c3be24063f268aaa1ed81b64776798f56088757641a34fb156c4f51ed2e9d25">7c3be24063f268aaa1ed81b64776798f56088757641a34fb156c4f51ed2e9d25</a>`,
|
||||||
@ -375,7 +375,7 @@ func httpTestsBitcoinType(t *testing.T, ts *httptest.Server) {
|
|||||||
body: []string{
|
body: []string{
|
||||||
`<a class="navbar-brand" href="/">Fake Coin Explorer</a>`,
|
`<a class="navbar-brand" href="/">Fake Coin Explorer</a>`,
|
||||||
`<h1>Address`,
|
`<h1>Address`,
|
||||||
`<small class="text-muted">0 FAKE</small>`,
|
`<small class="text-muted">0.00012345 FAKE</small>`,
|
||||||
`<span class="data">mtGXQvBowMkBpnhLckhxhbwYK44Gs9eEtz</span>`,
|
`<span class="data">mtGXQvBowMkBpnhLckhxhbwYK44Gs9eEtz</span>`,
|
||||||
`<td class="data">0.00012345 FAKE</td>`,
|
`<td class="data">0.00012345 FAKE</td>`,
|
||||||
`<a href="/tx/7c3be24063f268aaa1ed81b64776798f56088757641a34fb156c4f51ed2e9d25">7c3be24063f268aaa1ed81b64776798f56088757641a34fb156c4f51ed2e9d25</a>`,
|
`<a href="/tx/7c3be24063f268aaa1ed81b64776798f56088757641a34fb156c4f51ed2e9d25">7c3be24063f268aaa1ed81b64776798f56088757641a34fb156c4f51ed2e9d25</a>`,
|
||||||
@ -506,7 +506,7 @@ func httpTestsBitcoinType(t *testing.T, ts *httptest.Server) {
|
|||||||
status: http.StatusOK,
|
status: http.StatusOK,
|
||||||
contentType: "application/json; charset=utf-8",
|
contentType: "application/json; charset=utf-8",
|
||||||
body: []string{
|
body: []string{
|
||||||
`{"hex":"","txid":"00b2c06055e5e90e9c82bd4181fde310104391a7fa4f289b1704e5d90caa3840","version":0,"locktime":0,"vin":[],"vout":[{"ValueSat":100000000,"value":0,"n":0,"scriptPubKey":{"hex":"76a914010d39800f86122416e28f485029acf77507169288ac","addresses":null}},{"ValueSat":12345,"value":0,"n":1,"scriptPubKey":{"hex":"76a9148bdf0aa3c567aa5975c2e61321b8bebbe7293df688ac","addresses":null}}],"confirmations":2,"time":1521515026,"blocktime":1521515026}`,
|
`{"hex":"","txid":"00b2c06055e5e90e9c82bd4181fde310104391a7fa4f289b1704e5d90caa3840","version":0,"locktime":0,"vin":[],"vout":[{"ValueSat":100000000,"value":0,"n":0,"scriptPubKey":{"hex":"76a914010d39800f86122416e28f485029acf77507169288ac","addresses":null}},{"ValueSat":12345,"value":0,"n":1,"scriptPubKey":{"hex":"76a9148bdf0aa3c567aa5975c2e61321b8bebbe7293df688ac","addresses":null}},{"ValueSat":12345,"value":0,"n":2,"scriptPubKey":{"hex":"76a9148bdf0aa3c567aa5975c2e61321b8bebbe7293df688ac","addresses":null}}],"confirmations":2,"time":1521515026,"blocktime":1521515026}`,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -776,7 +776,7 @@ func httpTestsBitcoinType(t *testing.T, ts *httptest.Server) {
|
|||||||
status: http.StatusOK,
|
status: http.StatusOK,
|
||||||
contentType: "application/json; charset=utf-8",
|
contentType: "application/json; charset=utf-8",
|
||||||
body: []string{
|
body: []string{
|
||||||
`[{"time":1521514800,"txs":1,"received":"12345","sent":"0","rates":{"eur":1301,"usd":2001}},{"time":1521594000,"txs":1,"received":"0","sent":"12345","rates":{"eur":1303,"usd":2003}}]`,
|
`[{"time":1521514800,"txs":1,"received":"24690","sent":"0","rates":{"eur":1301,"usd":2001}},{"time":1521594000,"txs":1,"received":"0","sent":"12345","rates":{"eur":1303,"usd":2003}}]`,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -803,7 +803,7 @@ func httpTestsBitcoinType(t *testing.T, ts *httptest.Server) {
|
|||||||
status: http.StatusOK,
|
status: http.StatusOK,
|
||||||
contentType: "application/json; charset=utf-8",
|
contentType: "application/json; charset=utf-8",
|
||||||
body: []string{
|
body: []string{
|
||||||
`[{"time":1521514800,"txs":1,"received":"12345","sent":"0","rates":{"eur":1301,"usd":2001}}]`,
|
`[{"time":1521514800,"txs":1,"received":"24690","sent":"0","rates":{"eur":1301,"usd":2001}}]`,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -884,7 +884,7 @@ func httpTestsBitcoinType(t *testing.T, ts *httptest.Server) {
|
|||||||
status: http.StatusOK,
|
status: http.StatusOK,
|
||||||
contentType: "application/json; charset=utf-8",
|
contentType: "application/json; charset=utf-8",
|
||||||
body: []string{
|
body: []string{
|
||||||
`{"page":1,"totalPages":1,"itemsOnPage":1000,"hash":"0000000076fbbed90fd75b0e18856aa35baa984e9c9d444cf746ad85e94e2997","nextBlockHash":"00000000eb0443fd7dc4a1ed5c686a8e995057805f9a161d9a5a77a95e72b7b6","height":225493,"confirmations":2,"size":1234567,"time":1521515026,"version":0,"merkleRoot":"","nonce":"","bits":"","difficulty":"","txCount":2,"txs":[{"txid":"00b2c06055e5e90e9c82bd4181fde310104391a7fa4f289b1704e5d90caa3840","vin":[],"vout":[{"value":"100000000","n":0,"addresses":["mfcWp7DB6NuaZsExybTTXpVgWz559Np4Ti"],"isAddress":true},{"value":"12345","n":1,"spent":true,"addresses":["mtGXQvBowMkBpnhLckhxhbwYK44Gs9eEtz"],"isAddress":true}],"blockHash":"0000000076fbbed90fd75b0e18856aa35baa984e9c9d444cf746ad85e94e2997","blockHeight":225493,"confirmations":2,"blockTime":1521515026,"value":"100012345","valueIn":"0","fees":"0"},{"txid":"effd9ef509383d536b1c8af5bf434c8efbf521a4f2befd4022bbd68694b4ac75","vin":[],"vout":[{"value":"1234567890123","n":0,"spent":true,"addresses":["mv9uLThosiEnGRbVPS7Vhyw6VssbVRsiAw"],"isAddress":true},{"value":"1","n":1,"spent":true,"addresses":["2MzmAKayJmja784jyHvRUW1bXPget1csRRG"],"isAddress":true},{"value":"9876","n":2,"spent":true,"addresses":["2NEVv9LJmAnY99W1pFoc5UJjVdypBqdnvu1"],"isAddress":true}],"blockHash":"0000000076fbbed90fd75b0e18856aa35baa984e9c9d444cf746ad85e94e2997","blockHeight":225493,"confirmations":2,"blockTime":1521515026,"value":"1234567900000","valueIn":"0","fees":"0"}]}`,
|
`{"page":1,"totalPages":1,"itemsOnPage":1000,"hash":"0000000076fbbed90fd75b0e18856aa35baa984e9c9d444cf746ad85e94e2997","nextBlockHash":"00000000eb0443fd7dc4a1ed5c686a8e995057805f9a161d9a5a77a95e72b7b6","height":225493,"confirmations":2,"size":1234567,"time":1521515026,"version":0,"merkleRoot":"","nonce":"","bits":"","difficulty":"","txCount":2,"txs":[{"txid":"00b2c06055e5e90e9c82bd4181fde310104391a7fa4f289b1704e5d90caa3840","vin":[],"vout":[{"value":"100000000","n":0,"addresses":["mfcWp7DB6NuaZsExybTTXpVgWz559Np4Ti"],"isAddress":true},{"value":"12345","n":1,"spent":true,"addresses":["mtGXQvBowMkBpnhLckhxhbwYK44Gs9eEtz"],"isAddress":true},{"value":"12345","n":2,"addresses":["mtGXQvBowMkBpnhLckhxhbwYK44Gs9eEtz"],"isAddress":true}],"blockHash":"0000000076fbbed90fd75b0e18856aa35baa984e9c9d444cf746ad85e94e2997","blockHeight":225493,"confirmations":2,"blockTime":1521515026,"value":"100024690","valueIn":"0","fees":"0"},{"txid":"effd9ef509383d536b1c8af5bf434c8efbf521a4f2befd4022bbd68694b4ac75","vin":[],"vout":[{"value":"1234567890123","n":0,"spent":true,"addresses":["mv9uLThosiEnGRbVPS7Vhyw6VssbVRsiAw"],"isAddress":true},{"value":"1","n":1,"spent":true,"addresses":["2MzmAKayJmja784jyHvRUW1bXPget1csRRG"],"isAddress":true},{"value":"9876","n":2,"spent":true,"addresses":["2NEVv9LJmAnY99W1pFoc5UJjVdypBqdnvu1"],"isAddress":true}],"blockHash":"0000000076fbbed90fd75b0e18856aa35baa984e9c9d444cf746ad85e94e2997","blockHeight":225493,"confirmations":2,"blockTime":1521515026,"value":"1234567900000","valueIn":"0","fees":"0"}]}`,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -986,7 +986,7 @@ func socketioTestsBitcoinType(t *testing.T, ts *httptest.Server) {
|
|||||||
"to": 5,
|
"to": 5,
|
||||||
},
|
},
|
||||||
}},
|
}},
|
||||||
want: `{"result":{"totalCount":2,"items":[{"addresses":{"mtGXQvBowMkBpnhLckhxhbwYK44Gs9eEtz":{"inputIndexes":[1],"outputIndexes":[]}},"satoshis":-12345,"confirmations":1,"tx":{"hex":"","height":225494,"blockTimestamp":1521595678,"version":0,"hash":"7c3be24063f268aaa1ed81b64776798f56088757641a34fb156c4f51ed2e9d25","inputs":[{"txid":"effd9ef509383d536b1c8af5bf434c8efbf521a4f2befd4022bbd68694b4ac75","outputIndex":0,"script":"","sequence":0,"address":"mv9uLThosiEnGRbVPS7Vhyw6VssbVRsiAw","satoshis":1234567890123},{"txid":"00b2c06055e5e90e9c82bd4181fde310104391a7fa4f289b1704e5d90caa3840","outputIndex":1,"script":"","sequence":0,"address":"mtGXQvBowMkBpnhLckhxhbwYK44Gs9eEtz","satoshis":12345}],"inputSatoshis":1234567902468,"outputs":[{"satoshis":317283951061,"script":"76a914ccaaaf374e1b06cb83118453d102587b4273d09588ac","address":"mzB8cYrfRwFRFAGTDzV8LkUQy5BQicxGhX"},{"satoshis":917283951061,"script":"76a9148d802c045445df49613f6a70ddd2e48526f3701f88ac","address":"mtR97eM2HPWVM6c8FGLGcukgaHHQv7THoL"},{"satoshis":0,"script":"6a072020f1686f6a20","address":"OP_RETURN 2020f1686f6a20"}],"outputSatoshis":1234567902122,"feeSatoshis":346}},{"addresses":{"mtGXQvBowMkBpnhLckhxhbwYK44Gs9eEtz":{"inputIndexes":[],"outputIndexes":[1]}},"satoshis":12345,"confirmations":2,"tx":{"hex":"","height":225493,"blockTimestamp":1521515026,"version":0,"hash":"00b2c06055e5e90e9c82bd4181fde310104391a7fa4f289b1704e5d90caa3840","inputs":[],"outputs":[{"satoshis":100000000,"script":"76a914010d39800f86122416e28f485029acf77507169288ac","address":"mfcWp7DB6NuaZsExybTTXpVgWz559Np4Ti"},{"satoshis":12345,"script":"76a9148bdf0aa3c567aa5975c2e61321b8bebbe7293df688ac","address":"mtGXQvBowMkBpnhLckhxhbwYK44Gs9eEtz"}],"outputSatoshis":100012345}}]}}`,
|
want: `{"result":{"totalCount":2,"items":[{"addresses":{"mtGXQvBowMkBpnhLckhxhbwYK44Gs9eEtz":{"inputIndexes":[1],"outputIndexes":[]}},"satoshis":-12345,"confirmations":1,"tx":{"hex":"","height":225494,"blockTimestamp":1521595678,"version":0,"hash":"7c3be24063f268aaa1ed81b64776798f56088757641a34fb156c4f51ed2e9d25","inputs":[{"txid":"effd9ef509383d536b1c8af5bf434c8efbf521a4f2befd4022bbd68694b4ac75","outputIndex":0,"script":"","sequence":0,"address":"mv9uLThosiEnGRbVPS7Vhyw6VssbVRsiAw","satoshis":1234567890123},{"txid":"00b2c06055e5e90e9c82bd4181fde310104391a7fa4f289b1704e5d90caa3840","outputIndex":1,"script":"","sequence":0,"address":"mtGXQvBowMkBpnhLckhxhbwYK44Gs9eEtz","satoshis":12345}],"inputSatoshis":1234567902468,"outputs":[{"satoshis":317283951061,"script":"76a914ccaaaf374e1b06cb83118453d102587b4273d09588ac","address":"mzB8cYrfRwFRFAGTDzV8LkUQy5BQicxGhX"},{"satoshis":917283951061,"script":"76a9148d802c045445df49613f6a70ddd2e48526f3701f88ac","address":"mtR97eM2HPWVM6c8FGLGcukgaHHQv7THoL"},{"satoshis":0,"script":"6a072020f1686f6a20","address":"OP_RETURN 2020f1686f6a20"}],"outputSatoshis":1234567902122,"feeSatoshis":346}},{"addresses":{"mtGXQvBowMkBpnhLckhxhbwYK44Gs9eEtz":{"inputIndexes":[],"outputIndexes":[1,2]}},"satoshis":24690,"confirmations":2,"tx":{"hex":"","height":225493,"blockTimestamp":1521515026,"version":0,"hash":"00b2c06055e5e90e9c82bd4181fde310104391a7fa4f289b1704e5d90caa3840","inputs":[],"outputs":[{"satoshis":100000000,"script":"76a914010d39800f86122416e28f485029acf77507169288ac","address":"mfcWp7DB6NuaZsExybTTXpVgWz559Np4Ti"},{"satoshis":12345,"script":"76a9148bdf0aa3c567aa5975c2e61321b8bebbe7293df688ac","address":"mtGXQvBowMkBpnhLckhxhbwYK44Gs9eEtz"},{"satoshis":12345,"script":"76a9148bdf0aa3c567aa5975c2e61321b8bebbe7293df688ac","address":"mtGXQvBowMkBpnhLckhxhbwYK44Gs9eEtz"}],"outputSatoshis":100024690}}]}}`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "socketio getBlockHeader",
|
name: "socketio getBlockHeader",
|
||||||
@ -1370,7 +1370,7 @@ func websocketTestsBitcoinType(t *testing.T, ts *httptest.Server) {
|
|||||||
"descriptor": "mtGXQvBowMkBpnhLckhxhbwYK44Gs9eEtz",
|
"descriptor": "mtGXQvBowMkBpnhLckhxhbwYK44Gs9eEtz",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
want: `{"id":"32","data":[{"time":1521514800,"txs":1,"received":"12345","sent":"0","rates":{"eur":1301,"usd":2001}},{"time":1521594000,"txs":1,"received":"0","sent":"12345","rates":{"eur":1303,"usd":2003}}]}`,
|
want: `{"id":"32","data":[{"time":1521514800,"txs":1,"received":"24690","sent":"0","rates":{"eur":1301,"usd":2001}},{"time":1521594000,"txs":1,"received":"0","sent":"12345","rates":{"eur":1303,"usd":2003}}]}`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "websocket getBalanceHistory xpub",
|
name: "websocket getBalanceHistory xpub",
|
||||||
|
|||||||
@ -38,6 +38,7 @@ var (
|
|||||||
SatZero = big.NewInt(0)
|
SatZero = big.NewInt(0)
|
||||||
SatB1T1A1 = big.NewInt(100000000)
|
SatB1T1A1 = big.NewInt(100000000)
|
||||||
SatB1T1A2 = big.NewInt(12345)
|
SatB1T1A2 = big.NewInt(12345)
|
||||||
|
SatB1T1A2Double = big.NewInt(12345 * 2)
|
||||||
SatB1T2A3 = big.NewInt(1234567890123)
|
SatB1T2A3 = big.NewInt(1234567890123)
|
||||||
SatB1T2A4 = big.NewInt(1)
|
SatB1T2A4 = big.NewInt(1)
|
||||||
SatB1T2A5 = big.NewInt(9876)
|
SatB1T2A5 = big.NewInt(9876)
|
||||||
@ -90,6 +91,13 @@ func GetTestBitcoinTypeBlock1(parser bchain.BlockChainParser) *bchain.Block {
|
|||||||
},
|
},
|
||||||
ValueSat: *SatB1T1A2,
|
ValueSat: *SatB1T1A2,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
N: 2,
|
||||||
|
ScriptPubKey: bchain.ScriptPubKey{
|
||||||
|
Hex: AddressToPubKeyHex(Addr2, parser),
|
||||||
|
},
|
||||||
|
ValueSat: *SatB1T1A2,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
Blocktime: 1521515026,
|
Blocktime: 1521515026,
|
||||||
Time: 1521515026,
|
Time: 1521515026,
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user