/
block.go
133 lines (110 loc) · 2.93 KB
/
block.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
package types
import (
"encoding/hex"
"fmt"
"io"
"github.com/bytom/vapor/encoding/blockchain"
"github.com/bytom/vapor/encoding/bufpool"
"github.com/bytom/vapor/errors"
)
// serflag variables, start with 1
const (
_ = iota
SerBlockHeader
SerBlockTransactions
SerBlockFull
)
// Block describes a complete block, including its header and the transactions
// it contains.
type Block struct {
BlockHeader
Transactions []*Tx
}
func (b *Block) marshalText(serflags uint8) ([]byte, error) {
buf := bufpool.Get()
defer bufpool.Put(buf)
ew := errors.NewWriter(buf)
if err := b.writeTo(ew, serflags); err != nil {
return nil, err
}
if err := ew.Err(); err != nil {
return nil, err
}
enc := make([]byte, hex.EncodedLen(buf.Len()))
hex.Encode(enc, buf.Bytes())
return enc, nil
}
// MarshalText fulfills the json.Marshaler interface. This guarantees that
// blocks will get deserialized correctly when being parsed from HTTP requests.
func (b *Block) MarshalText() ([]byte, error) {
return b.marshalText(SerBlockFull)
}
// MarshalTextForBlockHeader fulfills the json.Marshaler interface.
func (b *Block) MarshalTextForBlockHeader() ([]byte, error) {
return b.marshalText(SerBlockHeader)
}
// MarshalTextForTransactions fulfills the json.Marshaler interface.
func (b *Block) MarshalTextForTransactions() ([]byte, error) {
return b.marshalText(SerBlockTransactions)
}
// UnmarshalText fulfills the encoding.TextUnmarshaler interface.
func (b *Block) UnmarshalText(text []byte) error {
decoded := make([]byte, hex.DecodedLen(len(text)))
if _, err := hex.Decode(decoded, text); err != nil {
return err
}
r := blockchain.NewReader(decoded)
if err := b.readFrom(r); err != nil {
return err
}
if trailing := r.Len(); trailing > 0 {
return fmt.Errorf("trailing garbage (%d bytes)", trailing)
}
return nil
}
func (b *Block) readFrom(r *blockchain.Reader) error {
serflag, err := b.BlockHeader.readFrom(r)
if err != nil {
return err
}
if serflag == SerBlockHeader {
return nil
}
n, err := blockchain.ReadVarint31(r)
if err != nil {
return errors.Wrap(err, "reading number of transactions")
}
for ; n > 0; n-- {
data := TxData{}
if err = data.readFrom(r); err != nil {
return errors.Wrapf(err, "reading transaction %d", len(b.Transactions))
}
b.Transactions = append(b.Transactions, NewTx(data))
}
return nil
}
// WriteTo write block to io.Writer
func (b *Block) WriteTo(w io.Writer) (int64, error) {
ew := errors.NewWriter(w)
if err := b.writeTo(ew, SerBlockFull); err != nil {
return 0, err
}
return ew.Written(), ew.Err()
}
func (b *Block) writeTo(w io.Writer, serflags uint8) error {
if err := b.BlockHeader.writeTo(w, serflags); err != nil {
return err
}
if serflags == SerBlockHeader {
return nil
}
if _, err := blockchain.WriteVarint31(w, uint64(len(b.Transactions))); err != nil {
return err
}
for _, tx := range b.Transactions {
if _, err := tx.WriteTo(w); err != nil {
return err
}
}
return nil
}