Add parser utils to reuse commonly used function
This commit is contained in:
parent
afb50f55c8
commit
e3f7a0ae5e
@ -3,8 +3,8 @@ package btg
|
||||
import (
|
||||
"blockbook/bchain"
|
||||
"blockbook/bchain/coins/btc"
|
||||
"blockbook/bchain/coins/utils"
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/btcsuite/btcd/chaincfg"
|
||||
@ -72,19 +72,6 @@ func GetChainParams(chain string) *chaincfg.Params {
|
||||
}
|
||||
}
|
||||
|
||||
// minTxPayload is the minimum payload size for a transaction. Note
|
||||
// that any realistically usable transaction must have at least one
|
||||
// input or output, but that is a rule enforced at a higher layer, so
|
||||
// it is intentionally not included here.
|
||||
// Version 4 bytes + Varint number of transaction inputs 1 byte + Varint
|
||||
// number of transaction outputs 1 byte + LockTime 4 bytes + min input
|
||||
// payload + min output payload.
|
||||
const minTxPayload = 10
|
||||
|
||||
// maxTxPerBlock is the maximum number of transactions that could
|
||||
// possibly fit into a block.
|
||||
const maxTxPerBlock = (wire.MaxBlockPayload / minTxPayload) + 1
|
||||
|
||||
// headerFixedLength is the length of fixed fields of a block (i.e. without solution)
|
||||
// see https://github.com/BTCGPU/BTCGPU/wiki/Technical-Spec#block-header
|
||||
const headerFixedLength = 44 + (chainhash.HashSize * 3)
|
||||
@ -98,7 +85,7 @@ func (p *BGoldParser) ParseBlock(b []byte) (*bchain.Block, error) {
|
||||
}
|
||||
|
||||
w := wire.MsgBlock{}
|
||||
err = decodeTransactions(r, 0, wire.WitnessEncoding, &w)
|
||||
err = utils.DecodeTransactions(r, 0, wire.WitnessEncoding, &w)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -129,31 +116,3 @@ func skipHeader(r io.ReadSeeker, pver uint32) error {
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func decodeTransactions(r io.Reader, pver uint32, enc wire.MessageEncoding, blk *wire.MsgBlock) error {
|
||||
txCount, err := wire.ReadVarInt(r, pver)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Prevent more transactions than could possibly fit into a block.
|
||||
// It would be possible to cause memory exhaustion and panics without
|
||||
// a sane upper bound on this count.
|
||||
if txCount > maxTxPerBlock {
|
||||
str := fmt.Sprintf("too many transactions to fit into a block "+
|
||||
"[count %d, max %d]", txCount, maxTxPerBlock)
|
||||
return &wire.MessageError{Func: "btg.decodeTransactions", Description: str}
|
||||
}
|
||||
|
||||
blk.Transactions = make([]*wire.MsgTx, 0, txCount)
|
||||
for i := uint64(0); i < txCount; i++ {
|
||||
tx := wire.MsgTx{}
|
||||
err := tx.BtcDecode(r, pver, enc)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
blk.Transactions = append(blk.Transactions, &tx)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -3,9 +3,8 @@ package dogecoin
|
||||
import (
|
||||
"blockbook/bchain"
|
||||
"blockbook/bchain/coins/btc"
|
||||
"blockbook/bchain/coins/utils"
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/btcsuite/btcd/chaincfg"
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
@ -50,21 +49,6 @@ func GetChainParams(chain string) *chaincfg.Params {
|
||||
}
|
||||
}
|
||||
|
||||
// minTxPayload is the minimum payload size for a transaction. Note
|
||||
// that any realistically usable transaction must have at least one
|
||||
// input or output, but that is a rule enforced at a higher layer, so
|
||||
// it is intentionally not included here.
|
||||
// Version 4 bytes + Varint number of transaction inputs 1 byte + Varint
|
||||
// number of transaction outputs 1 byte + LockTime 4 bytes + min input
|
||||
// payload + min output payload.
|
||||
const minTxPayload = 10
|
||||
|
||||
// maxTxPerBlock is the maximum number of transactions that could
|
||||
// possibly fit into a block.
|
||||
const maxTxPerBlock = (wire.MaxBlockPayload / minTxPayload) + 1
|
||||
|
||||
const versionAuxpow = (1 << 8)
|
||||
|
||||
// ParseBlock parses raw block to our Block struct
|
||||
// it has special handling for Auxpow blocks that cannot be parsed by standard btc wire parser
|
||||
func (p *DogecoinParser) ParseBlock(b []byte) (*bchain.Block, error) {
|
||||
@ -75,57 +59,13 @@ func (p *DogecoinParser) ParseBlock(b []byte) (*bchain.Block, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if (h.Version & versionAuxpow) != 0 {
|
||||
// skip Auxpow part of the block
|
||||
// https://github.com/dogecoin/dogecoin/blob/master/src/auxpow.h#L130
|
||||
// CMerkleTx CTransaction
|
||||
tx := wire.MsgTx{}
|
||||
err = tx.BtcDecode(r, 0, wire.WitnessEncoding)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// CMerkleTx uint256 hashBlock
|
||||
_, err = r.Seek(32, io.SeekCurrent)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// CMerkleTx std::vector<uint256> vMerkleBranch
|
||||
size, err := wire.ReadVarInt(r, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_, err = r.Seek(int64(size)*32, io.SeekCurrent)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// CMerkleTx int nIndex
|
||||
_, err = r.Seek(4, io.SeekCurrent)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// CAuxPow std::vector<uint256> vChainMerkleBranch;
|
||||
size, err = wire.ReadVarInt(r, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_, err = r.Seek(int64(size)*32, io.SeekCurrent)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// CAuxPow int nChainIndex;
|
||||
_, err = r.Seek(4, io.SeekCurrent)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// CAuxPow CPureBlockHeader parentBlock;
|
||||
ph := wire.BlockHeader{}
|
||||
err = ph.Deserialize(r)
|
||||
if err != nil {
|
||||
if (h.Version & utils.VersionAuxpow) != 0 {
|
||||
if err = utils.SkipAuxpow(r); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
err = decodeTransactions(r, 0, wire.WitnessEncoding, &w)
|
||||
err = utils.DecodeTransactions(r, 0, wire.WitnessEncoding, &w)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -137,31 +77,3 @@ func (p *DogecoinParser) ParseBlock(b []byte) (*bchain.Block, error) {
|
||||
|
||||
return &bchain.Block{Txs: txs}, nil
|
||||
}
|
||||
|
||||
func decodeTransactions(r io.Reader, pver uint32, enc wire.MessageEncoding, blk *wire.MsgBlock) error {
|
||||
txCount, err := wire.ReadVarInt(r, pver)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Prevent more transactions than could possibly fit into a block.
|
||||
// It would be possible to cause memory exhaustion and panics without
|
||||
// a sane upper bound on this count.
|
||||
if txCount > maxTxPerBlock {
|
||||
str := fmt.Sprintf("too many transactions to fit into a block "+
|
||||
"[count %d, max %d]", txCount, maxTxPerBlock)
|
||||
return &wire.MessageError{Func: "btg.decodeTransactions", Description: str}
|
||||
}
|
||||
|
||||
blk.Transactions = make([]*wire.MsgTx, 0, txCount)
|
||||
for i := uint64(0); i < txCount; i++ {
|
||||
tx := wire.MsgTx{}
|
||||
err := tx.BtcDecode(r, pver, enc)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
blk.Transactions = append(blk.Transactions, &tx)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
105
bchain/coins/utils/parserutils.go
Normal file
105
bchain/coins/utils/parserutils.go
Normal file
@ -0,0 +1,105 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
)
|
||||
|
||||
// minTxPayload is the minimum payload size for a transaction. Note
|
||||
// that any realistically usable transaction must have at least one
|
||||
// input or output, but that is a rule enforced at a higher layer, so
|
||||
// it is intentionally not included here.
|
||||
// Version 4 bytes + Varint number of transaction inputs 1 byte + Varint
|
||||
// number of transaction outputs 1 byte + LockTime 4 bytes + min input
|
||||
// payload + min output payload.
|
||||
const minTxPayload = 10
|
||||
|
||||
// maxTxPerBlock is the maximum number of transactions that could
|
||||
// possibly fit into a block.
|
||||
const maxTxPerBlock = (wire.MaxBlockPayload / minTxPayload) + 1
|
||||
|
||||
// DecodeTransactions decodes transactions from input stream using wire
|
||||
func DecodeTransactions(r io.Reader, pver uint32, enc wire.MessageEncoding, blk *wire.MsgBlock) error {
|
||||
txCount, err := wire.ReadVarInt(r, pver)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Prevent more transactions than could possibly fit into a block.
|
||||
// It would be possible to cause memory exhaustion and panics without
|
||||
// a sane upper bound on this count.
|
||||
if txCount > maxTxPerBlock {
|
||||
str := fmt.Sprintf("too many transactions to fit into a block "+
|
||||
"[count %d, max %d]", txCount, maxTxPerBlock)
|
||||
return &wire.MessageError{Func: "btg.decodeTransactions", Description: str}
|
||||
}
|
||||
|
||||
blk.Transactions = make([]*wire.MsgTx, 0, txCount)
|
||||
for i := uint64(0); i < txCount; i++ {
|
||||
tx := wire.MsgTx{}
|
||||
err := tx.BtcDecode(r, pver, enc)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
blk.Transactions = append(blk.Transactions, &tx)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// VersionAuxpow marks that block contains Auxpow
|
||||
const VersionAuxpow = (1 << 8)
|
||||
|
||||
// SkipAuxpow skips Auxpow data in block
|
||||
func SkipAuxpow(r io.ReadSeeker) error {
|
||||
// skip Auxpow part of the block
|
||||
// https://github.com/dogecoin/dogecoin/blob/master/src/auxpow.h#L130
|
||||
// CMerkleTx CTransaction
|
||||
tx := wire.MsgTx{}
|
||||
err := tx.BtcDecode(r, 0, wire.WitnessEncoding)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// CMerkleTx uint256 hashBlock
|
||||
_, err = r.Seek(32, io.SeekCurrent)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// CMerkleTx std::vector<uint256> vMerkleBranch
|
||||
size, err := wire.ReadVarInt(r, 0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = r.Seek(int64(size)*32, io.SeekCurrent)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// CMerkleTx int nIndex
|
||||
_, err = r.Seek(4, io.SeekCurrent)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// CAuxPow std::vector<uint256> vChainMerkleBranch;
|
||||
size, err = wire.ReadVarInt(r, 0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = r.Seek(int64(size)*32, io.SeekCurrent)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// CAuxPow int nChainIndex;
|
||||
_, err = r.Seek(4, io.SeekCurrent)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// CAuxPow CPureBlockHeader parentBlock;
|
||||
ph := wire.BlockHeader{}
|
||||
err = ph.Deserialize(r)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user