simplify names and interfaces
parent
cbce18f47e
commit
1c6d622834
|
@ -135,8 +135,8 @@ func (b *BitcoinRPC) GetTransaction(txid string) (tx *Tx, err error) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetOutpointAddresses returns all unique addresses from given transaction output.
|
// GetAddresses returns all unique addresses from given transaction output.
|
||||||
func (b *BitcoinRPC) GetOutpointAddresses(txid string, vout uint32) ([]string, error) {
|
func (b *BitcoinRPC) GetAddresses(txid string, vout uint32) ([]string, error) {
|
||||||
tx, err := b.GetTransaction(txid)
|
tx, err := b.GetTransaction(txid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
130
blockbook.go
130
blockbook.go
|
@ -11,21 +11,25 @@ type BlockParser interface {
|
||||||
ParseBlock(b []byte) (*Block, error)
|
ParseBlock(b []byte) (*Block, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type BlockOracle interface {
|
var (
|
||||||
|
ErrTxNotFound = errors.New("transaction not found")
|
||||||
|
)
|
||||||
|
|
||||||
|
type Blocks interface {
|
||||||
GetBestBlockHash() (string, error)
|
GetBestBlockHash() (string, error)
|
||||||
GetBlockHash(height uint32) (string, error)
|
GetBlockHash(height uint32) (string, error)
|
||||||
GetBlock(hash string) (*Block, error)
|
GetBlock(hash string) (*Block, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type OutpointAddressOracle interface {
|
type Outpoints interface {
|
||||||
GetOutpointAddresses(txid string, vout uint32) ([]string, error)
|
GetAddresses(txid string, vout uint32) ([]string, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type AddressTransactionOracle interface {
|
type Addresses interface {
|
||||||
GetAddressTransactions(address string, lower uint32, higher uint32, fn func(txids []string) error) error
|
GetTransactions(address string, lower uint32, higher uint32, fn func(txids []string) error) error
|
||||||
}
|
}
|
||||||
|
|
||||||
type BlockIndex interface {
|
type Indexer interface {
|
||||||
ConnectBlock(block *Block, txids map[string][]string) error
|
ConnectBlock(block *Block, txids map[string][]string) error
|
||||||
DisconnectBlock(block *Block, txids map[string][]string) error
|
DisconnectBlock(block *Block, txids map[string][]string) error
|
||||||
}
|
}
|
||||||
|
@ -81,7 +85,7 @@ func main() {
|
||||||
address := *queryAddress
|
address := *queryAddress
|
||||||
|
|
||||||
if address != "" {
|
if address != "" {
|
||||||
if err = db.GetAddressTransactions(address, height, until, printResult); err != nil {
|
if err = db.GetTransactions(address, height, until, printResult); err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -99,15 +103,15 @@ func printResult(txids []string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Block) CollectBlockAddresses(o OutpointAddressOracle) (map[string][]string, error) {
|
func (b *Block) GetAllAddresses(outpoints Outpoints) (map[string][]string, error) {
|
||||||
addrs := make(map[string][]string, 0)
|
addrs := make(map[string][]string, 0)
|
||||||
|
|
||||||
for _, tx := range b.Txs {
|
for _, tx := range b.Txs {
|
||||||
voutAddrs, err := tx.CollectAddresses(o)
|
ta, err := b.GetTxAddresses(outpoints, tx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
for _, addr := range voutAddrs {
|
for _, addr := range ta {
|
||||||
addrs[addr] = append(addrs[addr], tx.Txid)
|
addrs[addr] = append(addrs[addr], tx.Txid)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -115,69 +119,62 @@ func (b *Block) CollectBlockAddresses(o OutpointAddressOracle) (map[string][]str
|
||||||
return addrs, nil
|
return addrs, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
func (b *Block) GetTxAddresses(outpoints Outpoints, tx *Tx) ([]string, error) {
|
||||||
ErrTxNotFound = errors.New("transaction not found")
|
seen := make(map[string]struct{}) // Only unique values.
|
||||||
)
|
|
||||||
|
|
||||||
func (b *Block) GetOutpointAddresses(txid string, vout uint32) ([]string, error) {
|
// Process outputs.
|
||||||
|
for _, o := range tx.Vout {
|
||||||
|
for _, a := range o.ScriptPubKey.Addresses {
|
||||||
|
seen[a] = struct{}{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process inputs. For each input, we need to take a look to the
|
||||||
|
// outpoint index.
|
||||||
|
for _, i := range tx.Vin {
|
||||||
|
if i.Coinbase != "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lookup output in in the outpoint index. In case it's not
|
||||||
|
// found, take a look in this block.
|
||||||
|
va, err := outpoints.GetAddresses(i.Txid, i.Vout)
|
||||||
|
if err == ErrTxNotFound {
|
||||||
|
va, err = b.GetAddresses(i.Txid, i.Vout)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, a := range va {
|
||||||
|
seen[a] = struct{}{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert the result set into a slice.
|
||||||
|
addrs := make([]string, len(seen))
|
||||||
|
i := 0
|
||||||
|
for a := range seen {
|
||||||
|
addrs[i] = a
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
return addrs, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Block) GetAddresses(txid string, vout uint32) ([]string, error) {
|
||||||
|
// TODO: Lookup transaction in constant time.
|
||||||
for _, tx := range b.Txs {
|
for _, tx := range b.Txs {
|
||||||
if tx.Txid == txid {
|
if tx.Txid == txid {
|
||||||
return tx.Vout[vout].ScriptPubKey.Addresses, nil
|
return tx.Vout[vout].ScriptPubKey.Addresses, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, ErrTxNotFound
|
return nil, ErrTxNotFound
|
||||||
}
|
}
|
||||||
|
|
||||||
type JoinedOutpointAddressOracle struct {
|
|
||||||
outpoints OutpointAddressOracle
|
|
||||||
block *Block
|
|
||||||
}
|
|
||||||
|
|
||||||
func (o *JoinedOutpointAddressOracle) GetOutpointAddresses(txid string, vout uint32) ([]string, error) {
|
|
||||||
addrs, err := o.block.GetOutpointAddresses(txid, vout)
|
|
||||||
if err == nil {
|
|
||||||
return addrs, err
|
|
||||||
}
|
|
||||||
return o.outpoints.GetOutpointAddresses(txid, vout)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (tx *Tx) CollectAddresses(o OutpointAddressOracle) ([]string, error) {
|
|
||||||
addrs := make([]string, 0)
|
|
||||||
seen := make(map[string]struct{})
|
|
||||||
|
|
||||||
for _, vout := range tx.Vout {
|
|
||||||
for _, addr := range vout.ScriptPubKey.Addresses {
|
|
||||||
if _, found := seen[addr]; !found {
|
|
||||||
addrs = append(addrs, addr)
|
|
||||||
seen[addr] = struct{}{}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, vin := range tx.Vin {
|
|
||||||
if vin.Coinbase != "" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
vinAddrs, err := o.GetOutpointAddresses(vin.Txid, vin.Vout)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
for _, addr := range vinAddrs {
|
|
||||||
if _, found := seen[addr]; !found {
|
|
||||||
addrs = append(addrs, addr)
|
|
||||||
seen[addr] = struct{}{}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return addrs, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func indexBlocks(
|
func indexBlocks(
|
||||||
blocks BlockOracle,
|
blocks Blocks,
|
||||||
outpoints OutpointAddressOracle,
|
outpoints Outpoints,
|
||||||
index BlockIndex,
|
index Indexer,
|
||||||
lower uint32,
|
lower uint32,
|
||||||
higher uint32,
|
higher uint32,
|
||||||
) error {
|
) error {
|
||||||
|
@ -185,14 +182,11 @@ func indexBlocks(
|
||||||
|
|
||||||
go getBlocks(lower, higher, blocks, bch)
|
go getBlocks(lower, higher, blocks, bch)
|
||||||
|
|
||||||
blouts := JoinedOutpointAddressOracle{outpoints: outpoints}
|
|
||||||
|
|
||||||
for res := range bch {
|
for res := range bch {
|
||||||
if res.err != nil {
|
if res.err != nil {
|
||||||
return res.err
|
return res.err
|
||||||
}
|
}
|
||||||
blouts.block = res.block
|
addrs, err := res.block.GetAllAddresses(outpoints)
|
||||||
addrs, err := res.block.CollectBlockAddresses(&blouts)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -208,7 +202,7 @@ type blockResult struct {
|
||||||
err error
|
err error
|
||||||
}
|
}
|
||||||
|
|
||||||
func getBlocks(lower uint32, higher uint32, blocks BlockOracle, results chan<- blockResult) {
|
func getBlocks(lower uint32, higher uint32, blocks Blocks, results chan<- blockResult) {
|
||||||
defer close(results)
|
defer close(results)
|
||||||
|
|
||||||
height := lower
|
height := lower
|
||||||
|
|
|
@ -55,7 +55,7 @@ func (d *RocksDB) Close() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *RocksDB) GetOutpointAddresses(txid string, vout uint32) ([]string, error) {
|
func (d *RocksDB) GetAddresses(txid string, vout uint32) ([]string, error) {
|
||||||
log.Printf("rocksdb: outpoint get %s:%d", txid, vout)
|
log.Printf("rocksdb: outpoint get %s:%d", txid, vout)
|
||||||
k, err := packOutpointKey(txid, vout)
|
k, err := packOutpointKey(txid, vout)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -69,7 +69,7 @@ func (d *RocksDB) GetOutpointAddresses(txid string, vout uint32) ([]string, erro
|
||||||
return unpackOutpointValue(v.Data())
|
return unpackOutpointValue(v.Data())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *RocksDB) GetAddressTransactions(address string, lower uint32, higher uint32, fn func(txids []string) error) (err error) {
|
func (d *RocksDB) GetTransactions(address string, lower uint32, higher uint32, fn func(txids []string) error) (err error) {
|
||||||
log.Printf("rocksdb: address get %d:%d %s", lower, higher, address)
|
log.Printf("rocksdb: address get %d:%d %s", lower, higher, address)
|
||||||
|
|
||||||
kstart, err := packAddressKey(lower, address)
|
kstart, err := packAddressKey(lower, address)
|
||||||
|
|
Loading…
Reference in New Issue