-
Notifications
You must be signed in to change notification settings - Fork 672
/
build.go
125 lines (110 loc) · 2.96 KB
/
build.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
// Copyright (C) 2019-2023, Ava Labs, Inc. All rights reserved.
// See the file LICENSE for licensing terms.
package block
import (
"crypto"
"crypto/rand"
"time"
"github.com/ava-labs/avalanchego/ids"
"github.com/ava-labs/avalanchego/staking"
"github.com/ava-labs/avalanchego/utils/hashing"
"github.com/ava-labs/avalanchego/utils/wrappers"
)
func BuildUnsigned(
parentID ids.ID,
timestamp time.Time,
pChainHeight uint64,
blockBytes []byte,
) (SignedBlock, error) {
var block SignedBlock = &statelessBlock{
StatelessBlock: statelessUnsignedBlock{
ParentID: parentID,
Timestamp: timestamp.Unix(),
PChainHeight: pChainHeight,
Certificate: nil,
Block: blockBytes,
},
timestamp: timestamp,
}
bytes, err := c.Marshal(codecVersion, &block)
if err != nil {
return nil, err
}
return block, block.initialize(bytes)
}
func Build(
parentID ids.ID,
timestamp time.Time,
pChainHeight uint64,
cert *staking.Certificate,
blockBytes []byte,
chainID ids.ID,
key crypto.Signer,
) (SignedBlock, error) {
block := &statelessBlock{
StatelessBlock: statelessUnsignedBlock{
ParentID: parentID,
Timestamp: timestamp.Unix(),
PChainHeight: pChainHeight,
Certificate: cert.Raw,
Block: blockBytes,
},
timestamp: timestamp,
cert: cert,
proposer: ids.NodeIDFromCert(cert),
}
var blockIntf SignedBlock = block
unsignedBytesWithEmptySignature, err := c.Marshal(codecVersion, &blockIntf)
if err != nil {
return nil, err
}
// The serialized form of the block is the unsignedBytes followed by the
// signature, which is prefixed by a uint32. Because we are marshalling the
// block with an empty signature, we only need to strip off the length
// prefix to get the unsigned bytes.
lenUnsignedBytes := len(unsignedBytesWithEmptySignature) - wrappers.IntLen
unsignedBytes := unsignedBytesWithEmptySignature[:lenUnsignedBytes]
block.id = hashing.ComputeHash256Array(unsignedBytes)
header, err := BuildHeader(chainID, parentID, block.id)
if err != nil {
return nil, err
}
headerHash := hashing.ComputeHash256(header.Bytes())
block.Signature, err = key.Sign(rand.Reader, headerHash, crypto.SHA256)
if err != nil {
return nil, err
}
block.bytes, err = c.Marshal(codecVersion, &blockIntf)
return block, err
}
func BuildHeader(
chainID ids.ID,
parentID ids.ID,
bodyID ids.ID,
) (Header, error) {
header := statelessHeader{
Chain: chainID,
Parent: parentID,
Body: bodyID,
}
bytes, err := c.Marshal(codecVersion, &header)
header.bytes = bytes
return &header, err
}
// BuildOption the option block
// [parentID] is the ID of this option's wrapper parent block
// [innerBytes] is the byte representation of a child option block
func BuildOption(
parentID ids.ID,
innerBytes []byte,
) (Block, error) {
var block Block = &option{
PrntID: parentID,
InnerBytes: innerBytes,
}
bytes, err := c.Marshal(codecVersion, &block)
if err != nil {
return nil, err
}
return block, block.initialize(bytes)
}