Store transactions using protobuf in default baseparser implemention

indexv1
Martin Boehm 2018-04-09 10:42:58 +02:00
parent d0089d2bcb
commit feaf55e767
6 changed files with 357 additions and 48 deletions

View File

@ -2,7 +2,9 @@ package bchain
import (
"encoding/hex"
"errors"
"github.com/gogo/protobuf/proto"
"github.com/juju/errors"
)
// BaseParser implements data parsing/handling functionality base for all other parsers
@ -57,3 +59,105 @@ func (p *BaseParser) UnpackBlockHash(buf []byte) (string, error) {
func (p *BaseParser) IsUTXOChain() bool {
return true
}
// PackTx packs transaction to byte array using protobuf
func (p *BaseParser) PackTx(tx *Tx, height uint32, blockTime int64) ([]byte, error) {
var err error
pti := make([]*ProtoTransaction_VinType, len(tx.Vin))
for i, vi := range tx.Vin {
hex, err := hex.DecodeString(vi.ScriptSig.Hex)
if err != nil {
return nil, errors.Annotatef(err, "Vin %v Hex %v", i, vi.ScriptSig.Hex)
}
itxid, err := p.PackTxid(vi.Txid)
if err != nil {
return nil, errors.Annotatef(err, "Vin %v Txid %v", i, vi.Txid)
}
pti[i] = &ProtoTransaction_VinType{
Addresses: vi.Addresses,
Coinbase: vi.Coinbase,
ScriptSigHex: hex,
Sequence: vi.Sequence,
Txid: itxid,
Vout: vi.Vout,
}
}
pto := make([]*ProtoTransaction_VoutType, len(tx.Vout))
for i, vo := range tx.Vout {
hex, err := hex.DecodeString(vo.ScriptPubKey.Hex)
if err != nil {
return nil, errors.Annotatef(err, "Vout %v Hex %v", i, vo.ScriptPubKey.Hex)
}
pto[i] = &ProtoTransaction_VoutType{
Addresses: vo.ScriptPubKey.Addresses,
N: vo.N,
ScriptPubKeyHex: hex,
Value: vo.Value,
}
}
pt := &ProtoTransaction{
Blocktime: uint64(blockTime),
Height: height,
Locktime: tx.LockTime,
Vin: pti,
Vout: pto,
}
if pt.Hex, err = hex.DecodeString(tx.Hex); err != nil {
return nil, errors.Annotatef(err, "Hex %v", tx.Hex)
}
if pt.Txid, err = p.PackTxid(tx.Txid); err != nil {
return nil, errors.Annotatef(err, "Txid %v", tx.Txid)
}
return proto.Marshal(pt)
}
// UnpackTx unpacks transaction from protobuf byte array
func (p *BaseParser) UnpackTx(buf []byte) (*Tx, uint32, error) {
var pt ProtoTransaction
err := proto.Unmarshal(buf, &pt)
if err != nil {
return nil, 0, err
}
txid, err := p.UnpackTxid(pt.Txid)
if err != nil {
return nil, 0, err
}
vin := make([]Vin, len(pt.Vin))
for i, pti := range pt.Vin {
itxid, err := p.UnpackTxid(pti.Txid)
if err != nil {
return nil, 0, err
}
vin[i] = Vin{
Addresses: pti.Addresses,
Coinbase: pti.Coinbase,
ScriptSig: ScriptSig{
Hex: hex.EncodeToString(pti.ScriptSigHex),
},
Sequence: pti.Sequence,
Txid: itxid,
Vout: pti.Vout,
}
}
vout := make([]Vout, len(pt.Vout))
for i, pto := range pt.Vout {
vout[i] = Vout{
N: pto.N,
ScriptPubKey: ScriptPubKey{
Addresses: pto.Addresses,
Hex: hex.EncodeToString(pto.ScriptPubKeyHex),
},
Value: pto.Value,
}
}
tx := Tx{
Blocktime: int64(pt.Blocktime),
Hex: hex.EncodeToString(pt.Hex),
LockTime: pt.Locktime,
Time: int64(pt.Blocktime),
Txid: txid,
Vin: vin,
Vout: vout,
}
return &tx, pt.Height, nil
}

View File

@ -9,7 +9,7 @@ import (
"github.com/ethereum/go-ethereum/common/hexutil"
proto "github.com/golang/protobuf/proto"
"github.com/golang/protobuf/proto"
"github.com/juju/errors"
ethcommon "github.com/ethereum/go-ethereum/common"

View File

@ -2,9 +2,6 @@ package zec
import (
"blockbook/bchain"
"bytes"
"encoding/binary"
"encoding/gob"
)
// ZCashParser handle
@ -26,41 +23,3 @@ func (p *ZCashParser) GetAddrIDFromAddress(address string) ([]byte, error) {
hash, _, err := CheckDecode(address)
return hash, err
}
// PackTx packs transaction to byte array
func (p *ZCashParser) PackTx(tx *bchain.Tx, height uint32, blockTime int64) ([]byte, error) {
buf := make([]byte, 4)
binary.BigEndian.PutUint32(buf, height)
buf, err := encodeTx(buf, tx)
if err != nil {
return nil, err
}
return buf, nil
}
func encodeTx(b []byte, tx *bchain.Tx) ([]byte, error) {
buf := bytes.NewBuffer(b)
enc := gob.NewEncoder(buf)
err := enc.Encode(tx)
return buf.Bytes(), err
}
// UnpackTx unpacks transaction from byte array
func (p *ZCashParser) UnpackTx(buf []byte) (*bchain.Tx, uint32, error) {
height := binary.BigEndian.Uint32(buf)
tx, err := decodeTx(buf[4:])
if err != nil {
return nil, 0, err
}
return tx, height, nil
}
func decodeTx(buf []byte) (*bchain.Tx, error) {
tx := new(bchain.Tx)
dec := gob.NewDecoder(bytes.NewBuffer(buf))
err := dec.Decode(tx)
if err != nil {
return nil, err
}
return tx, nil
}

File diff suppressed because one or more lines are too long

221
bchain/tx.pb.go 100644
View File

@ -0,0 +1,221 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// source: tx.proto
/*
Package bchain is a generated protocol buffer package.
It is generated from these files:
tx.proto
It has these top-level messages:
ProtoTransaction
*/
package bchain
import proto "github.com/golang/protobuf/proto"
import fmt "fmt"
import math "math"
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
type ProtoTransaction struct {
Txid []byte `protobuf:"bytes,1,opt,name=Txid,proto3" json:"Txid,omitempty"`
Hex []byte `protobuf:"bytes,2,opt,name=Hex,proto3" json:"Hex,omitempty"`
Blocktime uint64 `protobuf:"varint,3,opt,name=Blocktime" json:"Blocktime,omitempty"`
Locktime uint32 `protobuf:"varint,4,opt,name=Locktime" json:"Locktime,omitempty"`
Height uint32 `protobuf:"varint,5,opt,name=Height" json:"Height,omitempty"`
Vin []*ProtoTransaction_VinType `protobuf:"bytes,6,rep,name=Vin" json:"Vin,omitempty"`
Vout []*ProtoTransaction_VoutType `protobuf:"bytes,7,rep,name=Vout" json:"Vout,omitempty"`
}
func (m *ProtoTransaction) Reset() { *m = ProtoTransaction{} }
func (m *ProtoTransaction) String() string { return proto.CompactTextString(m) }
func (*ProtoTransaction) ProtoMessage() {}
func (*ProtoTransaction) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
func (m *ProtoTransaction) GetTxid() []byte {
if m != nil {
return m.Txid
}
return nil
}
func (m *ProtoTransaction) GetHex() []byte {
if m != nil {
return m.Hex
}
return nil
}
func (m *ProtoTransaction) GetBlocktime() uint64 {
if m != nil {
return m.Blocktime
}
return 0
}
func (m *ProtoTransaction) GetLocktime() uint32 {
if m != nil {
return m.Locktime
}
return 0
}
func (m *ProtoTransaction) GetHeight() uint32 {
if m != nil {
return m.Height
}
return 0
}
func (m *ProtoTransaction) GetVin() []*ProtoTransaction_VinType {
if m != nil {
return m.Vin
}
return nil
}
func (m *ProtoTransaction) GetVout() []*ProtoTransaction_VoutType {
if m != nil {
return m.Vout
}
return nil
}
type ProtoTransaction_VinType struct {
Coinbase string `protobuf:"bytes,1,opt,name=Coinbase" json:"Coinbase,omitempty"`
Txid []byte `protobuf:"bytes,2,opt,name=Txid,proto3" json:"Txid,omitempty"`
Vout uint32 `protobuf:"varint,3,opt,name=Vout" json:"Vout,omitempty"`
ScriptSigHex []byte `protobuf:"bytes,4,opt,name=ScriptSigHex,proto3" json:"ScriptSigHex,omitempty"`
Sequence uint32 `protobuf:"varint,5,opt,name=Sequence" json:"Sequence,omitempty"`
Addresses []string `protobuf:"bytes,6,rep,name=Addresses" json:"Addresses,omitempty"`
}
func (m *ProtoTransaction_VinType) Reset() { *m = ProtoTransaction_VinType{} }
func (m *ProtoTransaction_VinType) String() string { return proto.CompactTextString(m) }
func (*ProtoTransaction_VinType) ProtoMessage() {}
func (*ProtoTransaction_VinType) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0, 0} }
func (m *ProtoTransaction_VinType) GetCoinbase() string {
if m != nil {
return m.Coinbase
}
return ""
}
func (m *ProtoTransaction_VinType) GetTxid() []byte {
if m != nil {
return m.Txid
}
return nil
}
func (m *ProtoTransaction_VinType) GetVout() uint32 {
if m != nil {
return m.Vout
}
return 0
}
func (m *ProtoTransaction_VinType) GetScriptSigHex() []byte {
if m != nil {
return m.ScriptSigHex
}
return nil
}
func (m *ProtoTransaction_VinType) GetSequence() uint32 {
if m != nil {
return m.Sequence
}
return 0
}
func (m *ProtoTransaction_VinType) GetAddresses() []string {
if m != nil {
return m.Addresses
}
return nil
}
type ProtoTransaction_VoutType struct {
Value float64 `protobuf:"fixed64,1,opt,name=Value" json:"Value,omitempty"`
N uint32 `protobuf:"varint,2,opt,name=N" json:"N,omitempty"`
ScriptPubKeyHex []byte `protobuf:"bytes,3,opt,name=ScriptPubKeyHex,proto3" json:"ScriptPubKeyHex,omitempty"`
Addresses []string `protobuf:"bytes,4,rep,name=Addresses" json:"Addresses,omitempty"`
}
func (m *ProtoTransaction_VoutType) Reset() { *m = ProtoTransaction_VoutType{} }
func (m *ProtoTransaction_VoutType) String() string { return proto.CompactTextString(m) }
func (*ProtoTransaction_VoutType) ProtoMessage() {}
func (*ProtoTransaction_VoutType) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0, 1} }
func (m *ProtoTransaction_VoutType) GetValue() float64 {
if m != nil {
return m.Value
}
return 0
}
func (m *ProtoTransaction_VoutType) GetN() uint32 {
if m != nil {
return m.N
}
return 0
}
func (m *ProtoTransaction_VoutType) GetScriptPubKeyHex() []byte {
if m != nil {
return m.ScriptPubKeyHex
}
return nil
}
func (m *ProtoTransaction_VoutType) GetAddresses() []string {
if m != nil {
return m.Addresses
}
return nil
}
func init() {
proto.RegisterType((*ProtoTransaction)(nil), "bchain.ProtoTransaction")
proto.RegisterType((*ProtoTransaction_VinType)(nil), "bchain.ProtoTransaction.VinType")
proto.RegisterType((*ProtoTransaction_VoutType)(nil), "bchain.ProtoTransaction.VoutType")
}
func init() { proto.RegisterFile("tx.proto", fileDescriptor0) }
var fileDescriptor0 = []byte{
// 330 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x74, 0x92, 0xc1, 0x4e, 0xc2, 0x40,
0x10, 0x86, 0xb3, 0xb4, 0x14, 0x18, 0x21, 0x92, 0x89, 0x31, 0x0d, 0xf1, 0x50, 0x39, 0xf5, 0xd4,
0x03, 0xc6, 0x07, 0x50, 0x2f, 0x24, 0x1a, 0x42, 0x16, 0xd2, 0x7b, 0x5b, 0x36, 0xb0, 0x11, 0x77,
0xb1, 0xdd, 0x1a, 0x78, 0x16, 0x1f, 0xc1, 0x97, 0x34, 0x3b, 0x2d, 0x45, 0x48, 0xbc, 0xed, 0xff,
0xef, 0x4c, 0xff, 0x6f, 0xff, 0x14, 0xba, 0x66, 0x1f, 0xed, 0x72, 0x6d, 0x34, 0x7a, 0x69, 0xb6,
0x49, 0xa4, 0x1a, 0x7f, 0xbb, 0x30, 0x9c, 0x5b, 0x67, 0x99, 0x27, 0xaa, 0x48, 0x32, 0x23, 0xb5,
0x42, 0x04, 0x77, 0xb9, 0x97, 0x2b, 0x9f, 0x05, 0x2c, 0xec, 0x73, 0x3a, 0xe3, 0x10, 0x9c, 0xa9,
0xd8, 0xfb, 0x2d, 0xb2, 0xec, 0x11, 0xef, 0xa0, 0xf7, 0xbc, 0xd5, 0xd9, 0xbb, 0x91, 0x1f, 0xc2,
0x77, 0x02, 0x16, 0xba, 0xfc, 0x64, 0xe0, 0x08, 0xba, 0x6f, 0xc7, 0x4b, 0x37, 0x60, 0xe1, 0x80,
0x37, 0x1a, 0x6f, 0xc1, 0x9b, 0x0a, 0xb9, 0xde, 0x18, 0xbf, 0x4d, 0x37, 0xb5, 0xc2, 0x09, 0x38,
0xb1, 0x54, 0xbe, 0x17, 0x38, 0xe1, 0xd5, 0x24, 0x88, 0x2a, 0xc4, 0xe8, 0x12, 0x2f, 0x8a, 0xa5,
0x5a, 0x1e, 0x76, 0x82, 0xdb, 0x61, 0x7c, 0x04, 0x37, 0xd6, 0xa5, 0xf1, 0x3b, 0xb4, 0x74, 0xff,
0xff, 0x92, 0x2e, 0x0d, 0x6d, 0xd1, 0xf8, 0xe8, 0x87, 0x41, 0xa7, 0xfe, 0x8e, 0x45, 0x7d, 0xd1,
0x52, 0xa5, 0x49, 0x21, 0xe8, 0xc9, 0x3d, 0xde, 0xe8, 0xa6, 0x8a, 0xd6, 0x9f, 0x2a, 0xb0, 0x8e,
0x74, 0x08, 0x9e, 0xce, 0x38, 0x86, 0xfe, 0x22, 0xcb, 0xe5, 0xce, 0x2c, 0xe4, 0xda, 0xf6, 0xe4,
0xd2, 0xfc, 0x99, 0x67, 0x73, 0x16, 0xe2, 0xb3, 0x14, 0x2a, 0x13, 0xf5, 0xc3, 0x1b, 0x6d, 0xcb,
0x7c, 0x5a, 0xad, 0x72, 0x51, 0x14, 0xa2, 0xa0, 0x02, 0x7a, 0xfc, 0x64, 0x8c, 0xbe, 0xa0, 0x7b,
0xe4, 0xc7, 0x1b, 0x68, 0xc7, 0xc9, 0xb6, 0xac, 0x50, 0x19, 0xaf, 0x04, 0xf6, 0x81, 0xcd, 0x08,
0x72, 0xc0, 0xd9, 0x0c, 0x43, 0xb8, 0xae, 0x92, 0xe7, 0x65, 0xfa, 0x2a, 0x0e, 0x16, 0xc8, 0x21,
0xa0, 0x4b, 0xfb, 0x3c, 0xd7, 0xbd, 0xc8, 0x4d, 0x3d, 0xfa, 0x59, 0x1e, 0x7e, 0x03, 0x00, 0x00,
0xff, 0xff, 0x64, 0x1d, 0x38, 0xac, 0x38, 0x02, 0x00, 0x00,
}

26
bchain/tx.proto 100644
View File

@ -0,0 +1,26 @@
syntax = "proto3";
package bchain;
message ProtoTransaction {
message VinType {
string Coinbase = 1;
bytes Txid = 2;
uint32 Vout = 3;
bytes ScriptSigHex = 4;
uint32 Sequence = 5;
repeated string Addresses = 6;
}
message VoutType {
double Value = 1;
uint32 N = 2;
bytes ScriptPubKeyHex = 3;
repeated string Addresses = 4;
}
bytes Txid = 1;
bytes Hex = 2;
uint64 Blocktime = 3;
uint32 Locktime = 4;
uint32 Height = 5;
repeated VinType Vin = 6;
repeated VoutType Vout = 7;
}