-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.go
149 lines (125 loc) · 4.43 KB
/
main.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
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
package main
import (
"errors"
"io"
"os"
"fmt"
"io/ioutil"
"bytes"
"encoding/json"
"github.com/ethereum/go-ethereum/core/types"
"golang.org/x/crypto/ssh/terminal"
// "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/common/hexutil"
)
var (
// IstanbulDigest represents a hash of "Istanbul practical byzantine fault tolerance"
// to identify whether the block is from Istanbul consensus engine
IstanbulDigest = common.HexToHash("0x63746963616c2062797a616e74696e65206661756c7420746f6c6572616e6365")
IstanbulExtraVanity = 32 // Fixed number of extra-data bytes reserved for validator vanity
IstanbulExtraSeal = 65 // Fixed number of extra-data bytes reserved for validator seal
// ErrInvalidIstanbulHeaderExtra is returned if the length of extra-data is less than 32 bytes
ErrInvalidIstanbulHeaderExtra = errors.New("invalid istanbul header extra-data")
)
type IstanbulExtra struct {
Validators []common.Address
Seal []byte
CommittedSeal [][]byte
}
// EncodeRLP serializes ist into the Ethereum RLP format.
func (ist *IstanbulExtra) EncodeRLP(w io.Writer) error {
return rlp.Encode(w, []interface{}{
ist.Validators,
ist.Seal,
ist.CommittedSeal,
})
}
// DecodeRLP implements rlp.Decoder, and load the istanbul fields from a RLP stream.
func (ist *IstanbulExtra) DecodeRLP(s *rlp.Stream) error {
var istanbulExtra struct {
Validators []common.Address
Seal []byte
CommittedSeal [][]byte
}
if err := s.Decode(&istanbulExtra); err != nil {
return err
}
ist.Validators, ist.Seal, ist.CommittedSeal = istanbulExtra.Validators, istanbulExtra.Seal, istanbulExtra.CommittedSeal
return nil
}
// ExtractIstanbulExtra extracts all values of the IstanbulExtra from the header. It returns an
// error if the length of the given extra-data is less than 32 bytes or the extra-data can not
// be decoded.
func ExtractIstanbulExtra(h *types.Header) (*IstanbulExtra, error) {
if len(h.Extra) < IstanbulExtraVanity {
return nil, ErrInvalidIstanbulHeaderExtra
}
var istanbulExtra *IstanbulExtra
err := rlp.DecodeBytes(h.Extra[IstanbulExtraVanity:], &istanbulExtra)
if err != nil {
return nil, err
}
return istanbulExtra, nil
}
// IstanbulFilteredHeader returns a filtered header which some information (like seal, committed seals)
// are clean to fulfill the Istanbul hash rules. It returns nil if the extra-data cannot be
// decoded/encoded by rlp.
func IstanbulFilteredHeader(h *types.Header, keepSeal bool) *types.Header {
newHeader := types.CopyHeader(h)
istanbulExtra, err := ExtractIstanbulExtra(newHeader)
if err != nil {
return nil
}
if !keepSeal {
istanbulExtra.Seal = []byte{}
}
istanbulExtra.CommittedSeal = [][]byte{}
payload, err := rlp.EncodeToBytes(&istanbulExtra)
if err != nil {
return nil
}
newHeader.Extra = append(newHeader.Extra[:IstanbulExtraVanity], payload...)
return newHeader
}
func Encode(vanity string, validators []common.Address) (string, error) {
newVanity, err := hexutil.Decode(vanity)
if err != nil {
return "", err
}
if len(newVanity) < IstanbulExtraVanity {
newVanity = append(newVanity, bytes.Repeat([]byte{0x00}, IstanbulExtraVanity-len(newVanity))...)
}
newVanity = newVanity[:IstanbulExtraVanity]
ist := &IstanbulExtra{
Validators: validators,
Seal: make([]byte, IstanbulExtraSeal),
CommittedSeal: [][]byte{},
}
payload, err := rlp.EncodeToBytes(&ist)
if err != nil {
return "", err
}
return "0x" + common.Bytes2Hex(append(newVanity, payload...)), nil
}
func ReadSTDINtoAddress(data []byte) ([]common.Address, error) {
var addrs []string
var addrsDec []common.Address
json.Unmarshal(data, &addrs)
for i := 0; i < len(addrs); i++ {
addrsDec = append(addrsDec, common.HexToAddress(addrs[i]))
}
return addrsDec, nil
}
func main() {
if ! terminal.IsTerminal(0) {
fmt.Print("Extradata for addrs: ")
b, _ := ioutil.ReadAll(os.Stdin)
addrs, _ := ReadSTDINtoAddress(b)
extraData, _ := Encode("0x00", addrs)
fmt.Printf("{%s}\n", extraData)
} else {
fmt.Println("no piped data\n")
}
}