Fix indexing of coinbase transactions
This commit is contained in:
parent
d569a08cf8
commit
f78b050234
@ -42,6 +42,9 @@ func (p *BaseParser) KeepBlockAddresses() int {
|
||||
|
||||
// PackTxid packs txid to byte array
|
||||
func (p *BaseParser) PackTxid(txid string) ([]byte, error) {
|
||||
if txid == "" {
|
||||
return nil, ErrTxidMissing
|
||||
}
|
||||
return hex.DecodeString(txid)
|
||||
}
|
||||
|
||||
|
||||
@ -14,6 +14,9 @@ var (
|
||||
// ErrAddressMissing is returned if address is not specified
|
||||
// for example To address in ethereum can be missing in case of contract transaction
|
||||
ErrAddressMissing = errors.New("Address missing")
|
||||
// ErrTxidMissing is returned if txid is not specified
|
||||
// for example coinbase transactions in Bitcoin
|
||||
ErrTxidMissing = errors.New("Txid missing")
|
||||
)
|
||||
|
||||
type ScriptSig struct {
|
||||
|
||||
@ -335,25 +335,25 @@ func appendPackedAddrID(txAddrs []byte, addrID []byte, n uint32, remaining int)
|
||||
return txAddrs
|
||||
}
|
||||
|
||||
func findAndRemoveUnspentAddr(unspentAddrs []byte, vout uint32) ([]byte, uint32, []byte) {
|
||||
func findAndRemoveUnspentAddr(unspentAddrs []byte, vout uint32) ([]byte, []byte) {
|
||||
// the addresses are packed as lenaddrID addrID vout, where lenaddrID and vout are varints
|
||||
for i := 0; i < len(unspentAddrs); {
|
||||
l, lv1 := unpackVarint(unspentAddrs[i:])
|
||||
// index of vout of address in unspentAddrs
|
||||
j := i + int(l) + lv1
|
||||
if j >= len(unspentAddrs) {
|
||||
glog.Error("rocksdb: Inconsistent data in unspentAddrs")
|
||||
return nil, 0, unspentAddrs
|
||||
glog.Error("rocksdb: Inconsistent data in unspentAddrs ", hex.EncodeToString(unspentAddrs), ", ", vout)
|
||||
return nil, unspentAddrs
|
||||
}
|
||||
n, lv2 := unpackVarint(unspentAddrs[j:])
|
||||
if uint32(n) == vout {
|
||||
addrID := append([]byte(nil), unspentAddrs[i+lv1:j]...)
|
||||
unspentAddrs = append(unspentAddrs[:i], unspentAddrs[j+lv2:]...)
|
||||
return addrID, uint32(n), unspentAddrs
|
||||
return addrID, unspentAddrs
|
||||
}
|
||||
i += j + lv2
|
||||
i = j + lv2
|
||||
}
|
||||
return nil, 0, unspentAddrs
|
||||
return nil, unspentAddrs
|
||||
}
|
||||
|
||||
func (d *RocksDB) writeAddressesUTXO(wb *gorocksdb.WriteBatch, block *bchain.Block, op int) error {
|
||||
@ -397,6 +397,10 @@ func (d *RocksDB) writeAddressesUTXO(wb *gorocksdb.WriteBatch, block *bchain.Blo
|
||||
for i, input := range tx.Vin {
|
||||
btxID, err := d.chainParser.PackTxid(input.Txid)
|
||||
if err != nil {
|
||||
// do not process inputs without input txid
|
||||
if err == bchain.ErrTxidMissing {
|
||||
continue
|
||||
}
|
||||
return err
|
||||
}
|
||||
// try to find the tx in current block
|
||||
@ -412,7 +416,7 @@ func (d *RocksDB) writeAddressesUTXO(wb *gorocksdb.WriteBatch, block *bchain.Blo
|
||||
}
|
||||
}
|
||||
var addrID []byte
|
||||
addrID, _, unspentAddrs = findAndRemoveUnspentAddr(unspentAddrs, input.Vout)
|
||||
addrID, unspentAddrs = findAndRemoveUnspentAddr(unspentAddrs, input.Vout)
|
||||
if addrID == nil {
|
||||
glog.Warningf("rocksdb: height %d, tx %v vout %v in inputs but missing in unspentTxs", block.Height, tx.Txid, input.Vout)
|
||||
continue
|
||||
|
||||
@ -491,3 +491,61 @@ func TestRocksDB_Index_UTXO(t *testing.T) {
|
||||
// disconnect the 2nd block, verify that the db contains only the 1st block
|
||||
|
||||
}
|
||||
|
||||
func Test_findAndRemoveUnspentAddr(t *testing.T) {
|
||||
type args struct {
|
||||
unspentAddrs string
|
||||
vout uint32
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want string
|
||||
want2 string
|
||||
}{
|
||||
{
|
||||
name: "3",
|
||||
args: args{
|
||||
unspentAddrs: "029c0010517a0115887452870212709393588893935687040e64635167006868060e76519351880087080a7b7b0115870a3276a9144150837fb91d9461d6b95059842ab85262c2923f88ac0c08636751680e04578710029112026114",
|
||||
vout: 3,
|
||||
},
|
||||
want: "64635167006868",
|
||||
want2: "029c0010517a0115887452870212709393588893935687040e76519351880087080a7b7b0115870a3276a9144150837fb91d9461d6b95059842ab85262c2923f88ac0c08636751680e04578710029112026114",
|
||||
},
|
||||
{
|
||||
name: "10",
|
||||
args: args{
|
||||
unspentAddrs: "029c0010517a0115887452870212709393588893935687040e64635167006868060e76519351880087080a7b7b0115870a3276a9144150837fb91d9461d6b95059842ab85262c2923f88ac0c08636751680e04578710029112026114",
|
||||
vout: 10,
|
||||
},
|
||||
want: "61",
|
||||
want2: "029c0010517a0115887452870212709393588893935687040e64635167006868060e76519351880087080a7b7b0115870a3276a9144150837fb91d9461d6b95059842ab85262c2923f88ac0c08636751680e04578710029112",
|
||||
},
|
||||
{
|
||||
name: "not there",
|
||||
args: args{
|
||||
unspentAddrs: "029c0010517a0115887452870212709393588893935687040e64635167006868060e76519351880087080a7b7b0115870a3276a9144150837fb91d9461d6b95059842ab85262c2923f88ac0c08636751680e04578710029112026114",
|
||||
vout: 11,
|
||||
},
|
||||
want: "",
|
||||
want2: "029c0010517a0115887452870212709393588893935687040e64635167006868060e76519351880087080a7b7b0115870a3276a9144150837fb91d9461d6b95059842ab85262c2923f88ac0c08636751680e04578710029112026114",
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
b, err := hex.DecodeString(tt.args.unspentAddrs)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
got, got2 := findAndRemoveUnspentAddr(b, tt.args.vout)
|
||||
h := hex.EncodeToString(got)
|
||||
if !reflect.DeepEqual(h, tt.want) {
|
||||
t.Errorf("findAndRemoveUnspentAddr() got = %v, want %v", h, tt.want)
|
||||
}
|
||||
h2 := hex.EncodeToString(got2)
|
||||
if !reflect.DeepEqual(h2, tt.want2) {
|
||||
t.Errorf("findAndRemoveUnspentAddr() got2 = %v, want %v", h2, tt.want2)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user