Introduce BitcoinType and EthereumType distinction of blockchains
This commit is contained in:
parent
13acef41d4
commit
38ba033654
@ -125,9 +125,9 @@ func (p *BaseParser) UnpackBlockHash(buf []byte) (string, error) {
|
||||
return hex.EncodeToString(buf), nil
|
||||
}
|
||||
|
||||
// IsUTXOChain returns true if the block chain is UTXO type, otherwise false
|
||||
func (p *BaseParser) IsUTXOChain() bool {
|
||||
return true
|
||||
// GetChainType is type of the blockchain, default is ChainBitcoinType
|
||||
func (p *BaseParser) GetChainType() ChainType {
|
||||
return ChainBitcoinType
|
||||
}
|
||||
|
||||
// PackTx packs transaction to byte array using protobuf
|
||||
|
||||
@ -27,7 +27,7 @@ type BitcoinRPC struct {
|
||||
Parser bchain.BlockChainParser
|
||||
Testnet bool
|
||||
Network string
|
||||
Mempool *bchain.UTXOMempool
|
||||
Mempool *bchain.MempoolBitcoinType
|
||||
ParseBlocks bool
|
||||
pushHandler func(bchain.NotificationType)
|
||||
mq *bchain.MQ
|
||||
@ -115,7 +115,7 @@ func (b *BitcoinRPC) GetChainInfoAndInitializeMempool(bc bchain.BlockChain) (str
|
||||
}
|
||||
b.mq = mq
|
||||
|
||||
b.Mempool = bchain.NewUTXOMempool(bc, b.ChainConfig.MempoolWorkers, b.ChainConfig.MempoolSubWorkers)
|
||||
b.Mempool = bchain.NewMempoolBitcoinType(bc, b.ChainConfig.MempoolWorkers, b.ChainConfig.MempoolSubWorkers)
|
||||
|
||||
return chainName, nil
|
||||
}
|
||||
|
||||
@ -7,12 +7,10 @@ import (
|
||||
"math/big"
|
||||
"strconv"
|
||||
|
||||
ethcommon "github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
|
||||
"github.com/golang/protobuf/proto"
|
||||
"github.com/juju/errors"
|
||||
|
||||
ethcommon "github.com/ethereum/go-ethereum/common"
|
||||
)
|
||||
|
||||
// EthereumParser handle
|
||||
@ -293,7 +291,7 @@ func (p *EthereumParser) UnpackBlockHash(buf []byte) (string, error) {
|
||||
return hexutil.Encode(buf), nil
|
||||
}
|
||||
|
||||
// IsUTXOChain returns true if the block chain is UTXO type, otherwise false
|
||||
func (p *EthereumParser) IsUTXOChain() bool {
|
||||
return false
|
||||
// GetChainType returns TypeEthereum
|
||||
func (p *EthereumParser) GetChainType() bchain.ChainType {
|
||||
return bchain.ChainEthereumType
|
||||
}
|
||||
|
||||
@ -45,7 +45,7 @@ type EthereumRPC struct {
|
||||
Parser *EthereumParser
|
||||
Testnet bool
|
||||
Network string
|
||||
Mempool *bchain.NonUTXOMempool
|
||||
Mempool *bchain.MempoolEthereumType
|
||||
bestHeaderMu sync.Mutex
|
||||
bestHeader *ethtypes.Header
|
||||
bestHeaderTime time.Time
|
||||
@ -185,7 +185,7 @@ func (b *EthereumRPC) Initialize() error {
|
||||
}
|
||||
|
||||
// create mempool
|
||||
b.Mempool = bchain.NewNonUTXOMempool(b)
|
||||
b.Mempool = bchain.NewMempoolEthereumType(b)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -23,8 +23,8 @@ type txidio struct {
|
||||
io []addrIndex
|
||||
}
|
||||
|
||||
// UTXOMempool is mempool handle.
|
||||
type UTXOMempool struct {
|
||||
// MempoolBitcoinType is mempool handle.
|
||||
type MempoolBitcoinType struct {
|
||||
chain BlockChain
|
||||
mux sync.Mutex
|
||||
txToInputOutput map[string][]addrIndex
|
||||
@ -34,10 +34,10 @@ type UTXOMempool struct {
|
||||
onNewTxAddr OnNewTxAddrFunc
|
||||
}
|
||||
|
||||
// NewUTXOMempool creates new mempool handler.
|
||||
// NewMempoolBitcoinType creates new mempool handler.
|
||||
// For now there is no cleanup of sync routines, the expectation is that the mempool is created only once per process
|
||||
func NewUTXOMempool(chain BlockChain, workers int, subworkers int) *UTXOMempool {
|
||||
m := &UTXOMempool{
|
||||
func NewMempoolBitcoinType(chain BlockChain, workers int, subworkers int) *MempoolBitcoinType {
|
||||
m := &MempoolBitcoinType{
|
||||
chain: chain,
|
||||
chanTxid: make(chan string, 1),
|
||||
chanAddrIndex: make(chan txidio, 1),
|
||||
@ -68,7 +68,7 @@ func NewUTXOMempool(chain BlockChain, workers int, subworkers int) *UTXOMempool
|
||||
}
|
||||
|
||||
// GetTransactions returns slice of mempool transactions for given address
|
||||
func (m *UTXOMempool) GetTransactions(address string) ([]string, error) {
|
||||
func (m *MempoolBitcoinType) GetTransactions(address string) ([]string, error) {
|
||||
parser := m.chain.GetChainParser()
|
||||
addrDesc, err := parser.GetAddrDescFromAddress(address)
|
||||
if err != nil {
|
||||
@ -78,7 +78,7 @@ func (m *UTXOMempool) GetTransactions(address string) ([]string, error) {
|
||||
}
|
||||
|
||||
// GetAddrDescTransactions returns slice of mempool transactions for given address descriptor
|
||||
func (m *UTXOMempool) GetAddrDescTransactions(addrDesc AddressDescriptor) ([]string, error) {
|
||||
func (m *MempoolBitcoinType) GetAddrDescTransactions(addrDesc AddressDescriptor) ([]string, error) {
|
||||
m.mux.Lock()
|
||||
defer m.mux.Unlock()
|
||||
outpoints := m.addrDescToTx[string(addrDesc)]
|
||||
@ -89,14 +89,14 @@ func (m *UTXOMempool) GetAddrDescTransactions(addrDesc AddressDescriptor) ([]str
|
||||
return txs, nil
|
||||
}
|
||||
|
||||
func (m *UTXOMempool) updateMappings(newTxToInputOutput map[string][]addrIndex, newAddrDescToTx map[string][]outpoint) {
|
||||
func (m *MempoolBitcoinType) updateMappings(newTxToInputOutput map[string][]addrIndex, newAddrDescToTx map[string][]outpoint) {
|
||||
m.mux.Lock()
|
||||
defer m.mux.Unlock()
|
||||
m.txToInputOutput = newTxToInputOutput
|
||||
m.addrDescToTx = newAddrDescToTx
|
||||
}
|
||||
|
||||
func (m *UTXOMempool) getInputAddress(input outpoint) *addrIndex {
|
||||
func (m *MempoolBitcoinType) getInputAddress(input outpoint) *addrIndex {
|
||||
itx, err := m.chain.GetTransactionForMempool(input.txid)
|
||||
if err != nil {
|
||||
glog.Error("cannot get transaction ", input.txid, ": ", err)
|
||||
@ -115,7 +115,7 @@ func (m *UTXOMempool) getInputAddress(input outpoint) *addrIndex {
|
||||
|
||||
}
|
||||
|
||||
func (m *UTXOMempool) getTxAddrs(txid string, chanInput chan outpoint, chanResult chan *addrIndex) ([]addrIndex, bool) {
|
||||
func (m *MempoolBitcoinType) getTxAddrs(txid string, chanInput chan outpoint, chanResult chan *addrIndex) ([]addrIndex, bool) {
|
||||
tx, err := m.chain.GetTransactionForMempool(txid)
|
||||
if err != nil {
|
||||
glog.Error("cannot get transaction ", txid, ": ", err)
|
||||
@ -170,7 +170,7 @@ func (m *UTXOMempool) getTxAddrs(txid string, chanInput chan outpoint, chanResul
|
||||
// Resync gets mempool transactions and maps outputs to transactions.
|
||||
// Resync is not reentrant, it should be called from a single thread.
|
||||
// Read operations (GetTransactions) are safe.
|
||||
func (m *UTXOMempool) Resync(onNewTxAddr OnNewTxAddrFunc) (int, error) {
|
||||
func (m *MempoolBitcoinType) Resync(onNewTxAddr OnNewTxAddrFunc) (int, error) {
|
||||
start := time.Now()
|
||||
glog.V(1).Info("mempool: resync")
|
||||
m.onNewTxAddr = onNewTxAddr
|
||||
@ -7,21 +7,21 @@ import (
|
||||
"github.com/golang/glog"
|
||||
)
|
||||
|
||||
// NonUTXOMempool is mempool handle of non UTXO chains
|
||||
type NonUTXOMempool struct {
|
||||
// MempoolEthereumType is mempool handle of EthereumType chains
|
||||
type MempoolEthereumType struct {
|
||||
chain BlockChain
|
||||
mux sync.Mutex
|
||||
txToInputOutput map[string][]addrIndex
|
||||
addrDescToTx map[string][]outpoint
|
||||
}
|
||||
|
||||
// NewNonUTXOMempool creates new mempool handler.
|
||||
func NewNonUTXOMempool(chain BlockChain) *NonUTXOMempool {
|
||||
return &NonUTXOMempool{chain: chain}
|
||||
// NewMempoolEthereumType creates new mempool handler.
|
||||
func NewMempoolEthereumType(chain BlockChain) *MempoolEthereumType {
|
||||
return &MempoolEthereumType{chain: chain}
|
||||
}
|
||||
|
||||
// GetTransactions returns slice of mempool transactions for given address
|
||||
func (m *NonUTXOMempool) GetTransactions(address string) ([]string, error) {
|
||||
func (m *MempoolEthereumType) GetTransactions(address string) ([]string, error) {
|
||||
parser := m.chain.GetChainParser()
|
||||
addrDesc, err := parser.GetAddrDescFromAddress(address)
|
||||
if err != nil {
|
||||
@ -31,7 +31,7 @@ func (m *NonUTXOMempool) GetTransactions(address string) ([]string, error) {
|
||||
}
|
||||
|
||||
// GetAddrDescTransactions returns slice of mempool transactions for given address descriptor
|
||||
func (m *NonUTXOMempool) GetAddrDescTransactions(addrDesc AddressDescriptor) ([]string, error) {
|
||||
func (m *MempoolEthereumType) GetAddrDescTransactions(addrDesc AddressDescriptor) ([]string, error) {
|
||||
m.mux.Lock()
|
||||
defer m.mux.Unlock()
|
||||
outpoints := m.addrDescToTx[string(addrDesc)]
|
||||
@ -42,7 +42,7 @@ func (m *NonUTXOMempool) GetAddrDescTransactions(addrDesc AddressDescriptor) ([]
|
||||
return txs, nil
|
||||
}
|
||||
|
||||
func (m *NonUTXOMempool) updateMappings(newTxToInputOutput map[string][]addrIndex, newAddrDescToTx map[string][]outpoint) {
|
||||
func (m *MempoolEthereumType) updateMappings(newTxToInputOutput map[string][]addrIndex, newAddrDescToTx map[string][]outpoint) {
|
||||
m.mux.Lock()
|
||||
defer m.mux.Unlock()
|
||||
m.txToInputOutput = newTxToInputOutput
|
||||
@ -52,7 +52,7 @@ func (m *NonUTXOMempool) updateMappings(newTxToInputOutput map[string][]addrInde
|
||||
// Resync gets mempool transactions and maps outputs to transactions.
|
||||
// Resync is not reentrant, it should be called from a single thread.
|
||||
// Read operations (GetTransactions) are safe.
|
||||
func (m *NonUTXOMempool) Resync(onNewTxAddr OnNewTxAddrFunc) (int, error) {
|
||||
func (m *MempoolEthereumType) Resync(onNewTxAddr OnNewTxAddrFunc) (int, error) {
|
||||
start := time.Now()
|
||||
glog.V(1).Info("Mempool: resync")
|
||||
txs, err := m.chain.GetMempool()
|
||||
@ -9,6 +9,16 @@ import (
|
||||
"math/big"
|
||||
)
|
||||
|
||||
// ChainType is type of the blockchain
|
||||
type ChainType int
|
||||
|
||||
const (
|
||||
// ChainBitcoinType is blockchain derived from bitcoin
|
||||
ChainBitcoinType = ChainType(iota)
|
||||
// TypeEthereum is blockchain derived from ethereum
|
||||
ChainEthereumType
|
||||
)
|
||||
|
||||
// errors with specific meaning returned by blockchain rpc
|
||||
var (
|
||||
// ErrBlockNotFound is returned when block is not found
|
||||
@ -23,11 +33,13 @@ var (
|
||||
ErrTxidMissing = errors.New("Txid missing")
|
||||
)
|
||||
|
||||
// ScriptSig contains data about input script
|
||||
type ScriptSig struct {
|
||||
// Asm string `json:"asm"`
|
||||
Hex string `json:"hex"`
|
||||
}
|
||||
|
||||
// Vin contains data about tx output
|
||||
type Vin struct {
|
||||
Coinbase string `json:"coinbase"`
|
||||
Txid string `json:"txid"`
|
||||
@ -37,6 +49,7 @@ type Vin struct {
|
||||
Addresses []string `json:"addresses"`
|
||||
}
|
||||
|
||||
// ScriptPubKey contains data about output script
|
||||
type ScriptPubKey struct {
|
||||
// Asm string `json:"asm"`
|
||||
Hex string `json:"hex,omitempty"`
|
||||
@ -44,6 +57,7 @@ type ScriptPubKey struct {
|
||||
Addresses []string `json:"addresses"`
|
||||
}
|
||||
|
||||
// Vout contains data about tx output
|
||||
type Vout struct {
|
||||
ValueSat big.Int
|
||||
JsonValue json.Number `json:"value"`
|
||||
@ -66,6 +80,7 @@ type Tx struct {
|
||||
Blocktime int64 `json:"blocktime,omitempty"`
|
||||
}
|
||||
|
||||
// Block is block header and list of transactions
|
||||
type Block struct {
|
||||
BlockHeader
|
||||
Txs []Tx `json:"tx"`
|
||||
@ -93,6 +108,7 @@ type BlockInfo struct {
|
||||
Txids []string `json:"tx,omitempty"`
|
||||
}
|
||||
|
||||
// MempoolEntry is used to get data about mempool entry
|
||||
type MempoolEntry struct {
|
||||
Size uint32 `json:"size"`
|
||||
FeeSat big.Int
|
||||
@ -110,6 +126,7 @@ type MempoolEntry struct {
|
||||
Depends []string `json:"depends"`
|
||||
}
|
||||
|
||||
// ChainInfo is used to get information about blockchain
|
||||
type ChainInfo struct {
|
||||
Chain string `json:"chain"`
|
||||
Blocks int `json:"blocks"`
|
||||
@ -124,6 +141,7 @@ type ChainInfo struct {
|
||||
Warnings string `json:"warnings"`
|
||||
}
|
||||
|
||||
// RPCError defines rpc error returned by backend
|
||||
type RPCError struct {
|
||||
Code int `json:"code"`
|
||||
Message string `json:"message"`
|
||||
@ -182,13 +200,10 @@ type BlockChain interface {
|
||||
|
||||
// BlockChainParser defines common interface to parsing and conversions of block chain data
|
||||
type BlockChainParser interface {
|
||||
// chain configuration description
|
||||
// UTXO chains need "inputs" column in db, that map transactions to transactions that spend them
|
||||
// non UTXO chains have mapping of address to input and output transactions directly in "outputs" column in db
|
||||
IsUTXOChain() bool
|
||||
// KeepBlockAddresses returns number of blocks which are to be kept in blockaddresses column
|
||||
// and used in case of fork
|
||||
// if 0 the blockaddresses column is not used at all (usually non UTXO chains)
|
||||
// type of the blockchain
|
||||
GetChainType() ChainType
|
||||
// KeepBlockAddresses returns number of blocks which are to be kept in blockTxs column
|
||||
// to be used for rollbacks
|
||||
KeepBlockAddresses() int
|
||||
// AmountToDecimalString converts amount in big.Int to string with decimal point in the correct place
|
||||
AmountToDecimalString(a *big.Int) string
|
||||
|
||||
@ -22,7 +22,7 @@ type bulkAddresses struct {
|
||||
// BulkConnect is used to connect blocks in bulk, faster but if interrupted inconsistent way
|
||||
type BulkConnect struct {
|
||||
d *RocksDB
|
||||
isUTXO bool
|
||||
chainType bchain.ChainType
|
||||
bulkAddresses []bulkAddresses
|
||||
bulkAddressesCount int
|
||||
txAddressesMap map[string]*TxAddresses
|
||||
@ -42,7 +42,7 @@ const (
|
||||
func (d *RocksDB) InitBulkConnect() (*BulkConnect, error) {
|
||||
bc := &BulkConnect{
|
||||
d: d,
|
||||
isUTXO: d.chainParser.IsUTXOChain(),
|
||||
chainType: d.chainParser.GetChainType(),
|
||||
txAddressesMap: make(map[string]*TxAddresses),
|
||||
balances: make(map[string]*AddrBalance),
|
||||
}
|
||||
@ -168,11 +168,12 @@ func (b *BulkConnect) storeBulkAddresses(wb *gorocksdb.WriteBatch) error {
|
||||
// ConnectBlock connects block in bulk mode
|
||||
func (b *BulkConnect) ConnectBlock(block *bchain.Block, storeBlockTxs bool) error {
|
||||
b.height = block.Height
|
||||
if !b.isUTXO {
|
||||
// for non bitcoin types connect blocks in non bulk mode
|
||||
if b.chainType != bchain.ChainBitcoinType {
|
||||
return b.d.ConnectBlock(block)
|
||||
}
|
||||
addresses := make(map[string][]outpoint)
|
||||
if err := b.d.processAddressesUTXO(block, addresses, b.txAddressesMap, b.balances); err != nil {
|
||||
if err := b.d.processAddressesBitcoinType(block, addresses, b.txAddressesMap, b.balances); err != nil {
|
||||
return err
|
||||
}
|
||||
var storeAddressesChan, storeBalancesChan chan error
|
||||
|
||||
@ -271,21 +271,21 @@ func (d *RocksDB) writeBlock(block *bchain.Block, op int) error {
|
||||
}
|
||||
}
|
||||
|
||||
isUTXO := d.chainParser.IsUTXOChain()
|
||||
chainType := d.chainParser.GetChainType()
|
||||
|
||||
if err := d.writeHeightFromBlock(wb, block, op); err != nil {
|
||||
return err
|
||||
}
|
||||
if isUTXO {
|
||||
if chainType == bchain.ChainBitcoinType {
|
||||
if op == opDelete {
|
||||
// block does not contain mapping tx-> input address, which is necessary to recreate
|
||||
// unspentTxs; therefore it is not possible to DisconnectBlocks this way
|
||||
return errors.New("DisconnectBlock is not supported for UTXO chains")
|
||||
return errors.New("DisconnectBlock is not supported for BitcoinType chains")
|
||||
}
|
||||
addresses := make(map[string][]outpoint)
|
||||
txAddressesMap := make(map[string]*TxAddresses)
|
||||
balances := make(map[string]*AddrBalance)
|
||||
if err := d.processAddressesUTXO(block, addresses, txAddressesMap, balances); err != nil {
|
||||
if err := d.processAddressesBitcoinType(block, addresses, txAddressesMap, balances); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := d.storeAddresses(wb, block.Height, addresses); err != nil {
|
||||
@ -300,8 +300,8 @@ func (d *RocksDB) writeBlock(block *bchain.Block, op int) error {
|
||||
if err := d.storeAndCleanupBlockTxs(wb, block); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
if err := d.writeAddressesNonUTXO(wb, block, op); err != nil {
|
||||
} else if chainType == bchain.ChainEthereumType {
|
||||
if err := d.writeAddressesTypeEthereum(wb, block, op); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@ -375,7 +375,7 @@ func (d *RocksDB) GetAndResetConnectBlockStats() string {
|
||||
return s
|
||||
}
|
||||
|
||||
func (d *RocksDB) processAddressesUTXO(block *bchain.Block, addresses map[string][]outpoint, txAddressesMap map[string]*TxAddresses, balances map[string]*AddrBalance) error {
|
||||
func (d *RocksDB) processAddressesBitcoinType(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
|
||||
@ -861,7 +861,7 @@ func (d *RocksDB) addAddrDescToRecords(op int, wb *gorocksdb.WriteBatch, records
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *RocksDB) writeAddressesNonUTXO(wb *gorocksdb.WriteBatch, block *bchain.Block, op int) error {
|
||||
func (d *RocksDB) writeAddressesTypeEthereum(wb *gorocksdb.WriteBatch, block *bchain.Block, op int) error {
|
||||
addresses := make(map[string][]outpoint)
|
||||
for _, tx := range block.Txs {
|
||||
btxID, err := d.chainParser.PackTxid(tx.Txid)
|
||||
@ -1166,9 +1166,9 @@ func (d *RocksDB) disconnectTxAddresses(wb *gorocksdb.WriteBatch, height uint32,
|
||||
return nil
|
||||
}
|
||||
|
||||
// DisconnectBlockRangeUTXO removes all data belonging to blocks in range lower-higher
|
||||
// DisconnectBlockRangeBitcoinType removes all data belonging to blocks in range lower-higher
|
||||
// if they are in the range kept in the cfBlockTxids column
|
||||
func (d *RocksDB) DisconnectBlockRangeUTXO(lower uint32, higher uint32) error {
|
||||
func (d *RocksDB) DisconnectBlockRangeBitcoinType(lower uint32, higher uint32) error {
|
||||
glog.Infof("db: disconnecting blocks %d-%d", lower, higher)
|
||||
blocks := make([][]blockTxs, higher-lower+1)
|
||||
for height := lower; height <= higher; height++ {
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
// +build unittest
|
||||
// build unittest
|
||||
|
||||
package db
|
||||
|
||||
@ -151,7 +151,7 @@ func checkColumn(d *RocksDB, col int, kp []keyPair) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func verifyAfterUTXOBlock1(t *testing.T, d *RocksDB, afterDisconnect bool) {
|
||||
func verifyAfterBitcoinTypeOBlock1(t *testing.T, d *RocksDB, afterDisconnect bool) {
|
||||
if err := checkColumn(d, cfHeight, []keyPair{
|
||||
keyPair{
|
||||
"000370d5",
|
||||
@ -232,7 +232,7 @@ func verifyAfterUTXOBlock1(t *testing.T, d *RocksDB, afterDisconnect bool) {
|
||||
}
|
||||
}
|
||||
|
||||
func verifyAfterUTXOBlock2(t *testing.T, d *RocksDB) {
|
||||
func verifyAfterBitcoinTypeBlock2(t *testing.T, d *RocksDB) {
|
||||
if err := checkColumn(d, cfHeight, []keyPair{
|
||||
keyPair{
|
||||
"000370d5",
|
||||
@ -423,7 +423,7 @@ func testTxCache(t *testing.T, d *RocksDB, b *bchain.Block, tx *bchain.Tx) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestRocksDB_Index_UTXO is an integration test probing the whole indexing functionality for UTXO chains
|
||||
// TestRocksDB_Index_BitcoinType is an integration test probing the whole indexing functionality for BitcoinType chains
|
||||
// It does the following:
|
||||
// 1) Connect two blocks (inputs from 2nd block are spending some outputs from the 1st block)
|
||||
// 2) GetTransactions for various addresses / low-high ranges
|
||||
@ -433,25 +433,25 @@ func testTxCache(t *testing.T, d *RocksDB, b *bchain.Block, tx *bchain.Tx) {
|
||||
// 6) Disconnect the block 2 using BlockTxs column
|
||||
// 7) Reconnect block 2 and check
|
||||
// After each step, the content of DB is examined and any difference against expected state is regarded as failure
|
||||
func TestRocksDB_Index_UTXO(t *testing.T) {
|
||||
func TestRocksDB_Index_BitcoinType(t *testing.T) {
|
||||
d := setupRocksDB(t, &testBitcoinParser{
|
||||
BitcoinParser: bitcoinTestnetParser(),
|
||||
})
|
||||
defer closeAndDestroyRocksDB(t, d)
|
||||
|
||||
// connect 1st block - will log warnings about missing UTXO transactions in txAddresses column
|
||||
block1 := dbtestdata.GetTestUTXOBlock1(d.chainParser)
|
||||
block1 := dbtestdata.GetTestBitcoinTypeBlock1(d.chainParser)
|
||||
if err := d.ConnectBlock(block1); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
verifyAfterUTXOBlock1(t, d, false)
|
||||
verifyAfterBitcoinTypeOBlock1(t, d, false)
|
||||
|
||||
// connect 2nd block - use some outputs from the 1st block as the inputs and 1 input uses tx from the same block
|
||||
block2 := dbtestdata.GetTestUTXOBlock2(d.chainParser)
|
||||
block2 := dbtestdata.GetTestBitcoinTypeBlock2(d.chainParser)
|
||||
if err := d.ConnectBlock(block2); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
verifyAfterUTXOBlock2(t, d)
|
||||
verifyAfterBitcoinTypeBlock2(t, d)
|
||||
|
||||
// get transactions for various addresses / low-high ranges
|
||||
verifyGetTransactions(t, d, dbtestdata.Addr2, 0, 1000000, []txidVoutOutput{
|
||||
@ -532,27 +532,27 @@ func TestRocksDB_Index_UTXO(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// DisconnectBlock for UTXO chains is not possible
|
||||
// DisconnectBlock for BitcoinType chains is not possible
|
||||
err = d.DisconnectBlock(block2)
|
||||
if err == nil || err.Error() != "DisconnectBlock is not supported for UTXO chains" {
|
||||
if err == nil || err.Error() != "DisconnectBlock is not supported for BitcoinType chains" {
|
||||
t.Fatal(err)
|
||||
}
|
||||
verifyAfterUTXOBlock2(t, d)
|
||||
verifyAfterBitcoinTypeBlock2(t, d)
|
||||
|
||||
// try to disconnect both blocks, however only the last one is kept, it is not possible
|
||||
err = d.DisconnectBlockRangeUTXO(225493, 225494)
|
||||
err = d.DisconnectBlockRangeBitcoinType(225493, 225494)
|
||||
if err == nil || err.Error() != "Cannot disconnect blocks with height 225493 and lower. It is necessary to rebuild index." {
|
||||
t.Fatal(err)
|
||||
}
|
||||
verifyAfterUTXOBlock2(t, d)
|
||||
verifyAfterBitcoinTypeBlock2(t, d)
|
||||
|
||||
// disconnect the 2nd block, verify that the db contains only data from the 1st block with restored unspentTxs
|
||||
// and that the cached tx is removed
|
||||
err = d.DisconnectBlockRangeUTXO(225494, 225494)
|
||||
err = d.DisconnectBlockRangeBitcoinType(225494, 225494)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
verifyAfterUTXOBlock1(t, d, true)
|
||||
verifyAfterBitcoinTypeOBlock1(t, d, true)
|
||||
if err := checkColumn(d, cfTransactions, []keyPair{}); err != nil {
|
||||
{
|
||||
t.Fatal(err)
|
||||
@ -563,7 +563,7 @@ func TestRocksDB_Index_UTXO(t *testing.T) {
|
||||
if err := d.ConnectBlock(block2); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
verifyAfterUTXOBlock2(t, d)
|
||||
verifyAfterBitcoinTypeBlock2(t, d)
|
||||
|
||||
// test public methods for address balance and tx addresses
|
||||
|
||||
@ -627,7 +627,7 @@ func TestRocksDB_Index_UTXO(t *testing.T) {
|
||||
|
||||
}
|
||||
|
||||
func Test_BulkConnect_UTXO(t *testing.T) {
|
||||
func Test_BulkConnect_BitcoinType(t *testing.T) {
|
||||
d := setupRocksDB(t, &testBitcoinParser{
|
||||
BitcoinParser: bitcoinTestnetParser(),
|
||||
})
|
||||
@ -642,7 +642,7 @@ func Test_BulkConnect_UTXO(t *testing.T) {
|
||||
t.Fatal("DB not in DbStateInconsistent")
|
||||
}
|
||||
|
||||
if err := bc.ConnectBlock(dbtestdata.GetTestUTXOBlock1(d.chainParser), false); err != nil {
|
||||
if err := bc.ConnectBlock(dbtestdata.GetTestBitcoinTypeBlock1(d.chainParser), false); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := checkColumn(d, cfBlockTxs, []keyPair{}); err != nil {
|
||||
@ -651,7 +651,7 @@ func Test_BulkConnect_UTXO(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
if err := bc.ConnectBlock(dbtestdata.GetTestUTXOBlock2(d.chainParser), true); err != nil {
|
||||
if err := bc.ConnectBlock(dbtestdata.GetTestBitcoinTypeBlock2(d.chainParser), true); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
@ -663,7 +663,7 @@ func Test_BulkConnect_UTXO(t *testing.T) {
|
||||
t.Fatal("DB not in DbStateOpen")
|
||||
}
|
||||
|
||||
verifyAfterUTXOBlock2(t, d)
|
||||
verifyAfterBitcoinTypeBlock2(t, d)
|
||||
}
|
||||
|
||||
func Test_packBigint_unpackBigint(t *testing.T) {
|
||||
|
||||
@ -393,9 +393,9 @@ func (w *SyncWorker) getBlockChain(out chan blockResult, done chan struct{}) {
|
||||
// DisconnectBlocks removes all data belonging to blocks in range lower-higher,
|
||||
func (w *SyncWorker) DisconnectBlocks(lower uint32, higher uint32, hashes []string) error {
|
||||
glog.Infof("sync: disconnecting blocks %d-%d", lower, higher)
|
||||
// if the chain is UTXO, always use DisconnectBlockRange
|
||||
if w.chain.GetChainParser().IsUTXOChain() {
|
||||
return w.db.DisconnectBlockRangeUTXO(lower, higher)
|
||||
// if the chain is ChainBitcoinType, always use DisconnectBlockRange
|
||||
if w.chain.GetChainParser().GetChainType() == bchain.ChainBitcoinType {
|
||||
return w.db.DisconnectBlockRangeBitcoinType(lower, higher)
|
||||
}
|
||||
blocks := make([]*bchain.Block, len(hashes))
|
||||
var err error
|
||||
|
||||
@ -86,8 +86,8 @@ Good examples of coin configuration are
|
||||
* `parse` – Use binary parser for block decoding if *true* else call verbose back-end RPC method that returns
|
||||
JSON. Note that verbose method is slow and not every coin support it. However there are coin implementations
|
||||
that don't support binary parsing (e.g. ZCash).
|
||||
* `mempool_workers` – Number of workers for UTXO mempool.
|
||||
* `mempool_sub_workers` – Number of subworkers for UTXO mempool.
|
||||
* `mempool_workers` – Number of workers for BitcoinType mempool.
|
||||
* `mempool_sub_workers` – Number of subworkers for BitcoinType mempool.
|
||||
* `block_addresses_to_keep` – Number of blocks that are to be kept in blockaddresses column.
|
||||
* `additional_params` – Object of coin-specific params.
|
||||
|
||||
|
||||
@ -48,10 +48,10 @@ func setupRocksDB(t *testing.T, parser bchain.BlockChainParser) (*db.RocksDB, *c
|
||||
}
|
||||
d.SetInternalState(is)
|
||||
// import data
|
||||
if err := d.ConnectBlock(dbtestdata.GetTestUTXOBlock1(parser)); err != nil {
|
||||
if err := d.ConnectBlock(dbtestdata.GetTestBitcoinTypeBlock1(parser)); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := d.ConnectBlock(dbtestdata.GetTestUTXOBlock2(parser)); err != nil {
|
||||
if err := d.ConnectBlock(dbtestdata.GetTestBitcoinTypeBlock2(parser)); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
return d, is, tmp
|
||||
@ -575,7 +575,7 @@ func socketioTests(t *testing.T, ts *httptest.Server) {
|
||||
}
|
||||
}
|
||||
|
||||
func Test_PublicServer_UTXO(t *testing.T) {
|
||||
func Test_PublicServer_BitcoinType(t *testing.T) {
|
||||
s, dbpath := setupPublicHTTPServer(t)
|
||||
defer closeAndDestroyPublicServer(t, s, dbpath)
|
||||
s.ConnectFullPublicInterface()
|
||||
@ -585,5 +585,4 @@ func Test_PublicServer_UTXO(t *testing.T) {
|
||||
|
||||
httpTests(t, ts)
|
||||
socketioTests(t, ts)
|
||||
|
||||
}
|
||||
|
||||
@ -54,7 +54,7 @@ func AddressToPubKeyHex(addr string, parser bchain.BlockChainParser) string {
|
||||
return hex.EncodeToString(b)
|
||||
}
|
||||
|
||||
func GetTestUTXOBlock1(parser bchain.BlockChainParser) *bchain.Block {
|
||||
func GetTestBitcoinTypeBlock1(parser bchain.BlockChainParser) *bchain.Block {
|
||||
return &bchain.Block{
|
||||
BlockHeader: bchain.BlockHeader{
|
||||
Height: 225493,
|
||||
@ -119,7 +119,7 @@ func GetTestUTXOBlock1(parser bchain.BlockChainParser) *bchain.Block {
|
||||
}
|
||||
}
|
||||
|
||||
func GetTestUTXOBlock2(parser bchain.BlockChainParser) *bchain.Block {
|
||||
func GetTestBitcoinTypeBlock2(parser bchain.BlockChainParser) *bchain.Block {
|
||||
return &bchain.Block{
|
||||
BlockHeader: bchain.BlockHeader{
|
||||
Height: 225494,
|
||||
|
||||
@ -45,26 +45,26 @@ func (c *fakeBlockChain) GetChainInfo() (v *bchain.ChainInfo, err error) {
|
||||
Chain: c.GetNetworkName(),
|
||||
Blocks: 2,
|
||||
Headers: 2,
|
||||
Bestblockhash: GetTestUTXOBlock2(c.parser).BlockHeader.Hash,
|
||||
Bestblockhash: GetTestBitcoinTypeBlock2(c.parser).BlockHeader.Hash,
|
||||
Version: "001001",
|
||||
Subversion: c.GetSubversion(),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (c *fakeBlockChain) GetBestBlockHash() (v string, err error) {
|
||||
return GetTestUTXOBlock2(c.parser).BlockHeader.Hash, nil
|
||||
return GetTestBitcoinTypeBlock2(c.parser).BlockHeader.Hash, nil
|
||||
}
|
||||
|
||||
func (c *fakeBlockChain) GetBestBlockHeight() (v uint32, err error) {
|
||||
return GetTestUTXOBlock2(c.parser).BlockHeader.Height, nil
|
||||
return GetTestBitcoinTypeBlock2(c.parser).BlockHeader.Height, nil
|
||||
}
|
||||
|
||||
func (c *fakeBlockChain) GetBlockHash(height uint32) (v string, err error) {
|
||||
b1 := GetTestUTXOBlock1(c.parser)
|
||||
b1 := GetTestBitcoinTypeBlock1(c.parser)
|
||||
if height == b1.BlockHeader.Height {
|
||||
return b1.BlockHeader.Hash, nil
|
||||
}
|
||||
b2 := GetTestUTXOBlock2(c.parser)
|
||||
b2 := GetTestBitcoinTypeBlock2(c.parser)
|
||||
if height == b2.BlockHeader.Height {
|
||||
return b2.BlockHeader.Hash, nil
|
||||
}
|
||||
@ -72,11 +72,11 @@ func (c *fakeBlockChain) GetBlockHash(height uint32) (v string, err error) {
|
||||
}
|
||||
|
||||
func (c *fakeBlockChain) GetBlockHeader(hash string) (v *bchain.BlockHeader, err error) {
|
||||
b1 := GetTestUTXOBlock1(c.parser)
|
||||
b1 := GetTestBitcoinTypeBlock1(c.parser)
|
||||
if hash == b1.BlockHeader.Hash {
|
||||
return &b1.BlockHeader, nil
|
||||
}
|
||||
b2 := GetTestUTXOBlock2(c.parser)
|
||||
b2 := GetTestBitcoinTypeBlock2(c.parser)
|
||||
if hash == b2.BlockHeader.Hash {
|
||||
return &b2.BlockHeader, nil
|
||||
}
|
||||
@ -84,11 +84,11 @@ func (c *fakeBlockChain) GetBlockHeader(hash string) (v *bchain.BlockHeader, err
|
||||
}
|
||||
|
||||
func (c *fakeBlockChain) GetBlock(hash string, height uint32) (v *bchain.Block, err error) {
|
||||
b1 := GetTestUTXOBlock1(c.parser)
|
||||
b1 := GetTestBitcoinTypeBlock1(c.parser)
|
||||
if hash == b1.BlockHeader.Hash || height == b1.BlockHeader.Height {
|
||||
return b1, nil
|
||||
}
|
||||
b2 := GetTestUTXOBlock2(c.parser)
|
||||
b2 := GetTestBitcoinTypeBlock2(c.parser)
|
||||
if hash == b2.BlockHeader.Hash || height == b2.BlockHeader.Height {
|
||||
return b2, nil
|
||||
}
|
||||
@ -106,11 +106,11 @@ func getBlockInfo(b *bchain.Block) *bchain.BlockInfo {
|
||||
}
|
||||
|
||||
func (c *fakeBlockChain) GetBlockInfo(hash string) (v *bchain.BlockInfo, err error) {
|
||||
b1 := GetTestUTXOBlock1(c.parser)
|
||||
b1 := GetTestBitcoinTypeBlock1(c.parser)
|
||||
if hash == b1.BlockHeader.Hash {
|
||||
return getBlockInfo(b1), nil
|
||||
}
|
||||
b2 := GetTestUTXOBlock2(c.parser)
|
||||
b2 := GetTestBitcoinTypeBlock2(c.parser)
|
||||
if hash == b2.BlockHeader.Hash {
|
||||
return getBlockInfo(b2), nil
|
||||
}
|
||||
@ -131,9 +131,9 @@ func getTxInBlock(b *bchain.Block, txid string) *bchain.Tx {
|
||||
}
|
||||
|
||||
func (c *fakeBlockChain) GetTransaction(txid string) (v *bchain.Tx, err error) {
|
||||
v = getTxInBlock(GetTestUTXOBlock1(c.parser), txid)
|
||||
v = getTxInBlock(GetTestBitcoinTypeBlock1(c.parser), txid)
|
||||
if v == nil {
|
||||
v = getTxInBlock(GetTestUTXOBlock2(c.parser), txid)
|
||||
v = getTxInBlock(GetTestBitcoinTypeBlock2(c.parser), txid)
|
||||
}
|
||||
if v != nil {
|
||||
return v, nil
|
||||
|
||||
Loading…
Reference in New Issue
Block a user