From 58e5f3e78baf93ac233e77b377728b98d029ed6a Mon Sep 17 00:00:00 2001 From: George Tankersley Date: Fri, 28 Sep 2018 00:52:40 +0000 Subject: [PATCH] parser: implement whole-block parsing and publicize constructors --- parser/block.go | 47 +++++++++++++++++++++++++++++++++++++ parser/block_header.go | 2 +- parser/block_header_test.go | 2 +- parser/block_test.go | 42 +++++++++++++++++++++++++++++++++ parser/transaction.go | 2 +- parser/transaction_test.go | 4 ++-- 6 files changed, 94 insertions(+), 5 deletions(-) create mode 100644 parser/block.go create mode 100644 parser/block_test.go diff --git a/parser/block.go b/parser/block.go new file mode 100644 index 0000000..0d4893f --- /dev/null +++ b/parser/block.go @@ -0,0 +1,47 @@ +package parser + +import ( + "fmt" + + "github.com/gtank/ctxd/parser/internal/bytestring" + "github.com/pkg/errors" +) + +type block struct { + hdr *blockHeader + vtx []*transaction +} + +func NewBlock() *block { + return &block{} +} + +func (b *block) ParseFromSlice(data []byte) (rest []byte, err error) { + hdr := NewBlockHeader() + data, err = hdr.ParseFromSlice(data) + if err != nil { + return nil, errors.Wrap(err, "parsing block header") + } + + s := bytestring.String(data) + var txCount int + if ok := s.ReadCompactSize(&txCount); !ok { + return nil, errors.New("could not read tx_count") + } + data = []byte(s) + + vtx := make([]*transaction, 0, txCount) + for i := 0; len(data) > 0; i++ { + tx := NewTransaction() + data, err = tx.ParseFromSlice(data) + if err != nil { + return nil, errors.Wrap(err, fmt.Sprintf("parsing transaction %d", i)) + } + vtx = append(vtx, tx) + } + + b.hdr = hdr + b.vtx = vtx + + return data, nil +} diff --git a/parser/block_header.go b/parser/block_header.go index 39294d7..739116a 100644 --- a/parser/block_header.go +++ b/parser/block_header.go @@ -79,7 +79,7 @@ func (hdr *rawBlockHeader) MarshalBinary() ([]byte, error) { return backing[:SER_BLOCK_HEADER_SIZE], nil } -func newBlockHeader() *blockHeader { +func NewBlockHeader() *blockHeader { return &blockHeader{ rawBlockHeader: new(rawBlockHeader), } diff --git a/parser/block_header_test.go b/parser/block_header_test.go index 4d87d39..400a296 100644 --- a/parser/block_header_test.go +++ b/parser/block_header_test.go @@ -72,7 +72,7 @@ func TestBlockHeader(t *testing.T) { continue } - blockHeader := newBlockHeader() + blockHeader := NewBlockHeader() _, err = blockHeader.ParseFromSlice(blockData) if err != nil { t.Error(err) diff --git a/parser/block_test.go b/parser/block_test.go new file mode 100644 index 0000000..629a895 --- /dev/null +++ b/parser/block_test.go @@ -0,0 +1,42 @@ +package parser + +import ( + "bufio" + "encoding/hex" + "fmt" + "os" + "testing" + + "github.com/pkg/errors" +) + +func TestBlockParser(t *testing.T) { + testBlocks, err := os.Open("testdata/blocks") + if err != nil { + t.Fatal(err) + } + defer testBlocks.Close() + + scan := bufio.NewScanner(testBlocks) + for i := 0; scan.Scan(); i++ { + blockDataHex := scan.Text() + blockData, err := hex.DecodeString(blockDataHex) + if err != nil { + t.Error(err) + continue + } + + block := NewBlock() + blockData, err = block.ParseFromSlice(blockData) + if err != nil { + t.Error(errors.Wrap(err, fmt.Sprintf("parsing block %d", i))) + continue + } + + // Some basic sanity checks + if block.hdr.Version != 4 { + t.Error("Read wrong version in a test block.") + break + } + } +} diff --git a/parser/transaction.go b/parser/transaction.go index 03318e7..d0a3af7 100644 --- a/parser/transaction.go +++ b/parser/transaction.go @@ -394,7 +394,7 @@ func (tx *transaction) ParseFromSlice(data []byte) ([]byte, error) { return []byte(s), nil } -func newTransaction() *transaction { +func NewTransaction() *transaction { return &transaction{ rawTransaction: new(rawTransaction), } diff --git a/parser/transaction_test.go b/parser/transaction_test.go index da78adf..0e851f4 100644 --- a/parser/transaction_test.go +++ b/parser/transaction_test.go @@ -179,7 +179,7 @@ func TestSproutTransactionParser(t *testing.T) { } for i, tt := range zip143tests { - tx := newTransaction() + tx := NewTransaction() rest, err := tx.ParseFromSlice(rawTxData[i]) if err != nil { @@ -685,7 +685,7 @@ func TestSaplingTransactionParser(t *testing.T) { } for i, tt := range zip243tests { - tx := newTransaction() + tx := NewTransaction() rest, err := tx.ParseFromSlice(rawTxData[i]) if err != nil {