This repository has been archived by the owner on May 13, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 346
/
genesis_spec.go
146 lines (127 loc) · 4.35 KB
/
genesis_spec.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
package spec
import (
"bytes"
"crypto/sha256"
"encoding/json"
"fmt"
"time"
"github.com/hyperledger/burrow/acm/balance"
"github.com/hyperledger/burrow/genesis"
"github.com/hyperledger/burrow/keys"
"github.com/hyperledger/burrow/permission"
)
const DefaultAmount uint64 = 1000000
const DefaultPower uint64 = 10000
const DefaultProposalThreshold uint64 = 3
// A GenesisSpec is schematic representation of a genesis state, that is it is a template
// for a GenesisDoc excluding that which needs to be instantiated at the point of genesis
// so it describes the type and number of accounts, the genesis salt, but not the
// account keys or addresses, or the GenesisTime. It is responsible for generating keys
// by interacting with the KeysClient it is passed and other information not known at
// specification time
type GenesisSpec struct {
GenesisTime *time.Time `json:",omitempty" toml:",omitempty"`
ChainName string `json:",omitempty" toml:",omitempty"`
Params params `json:",omitempty" toml:",omitempty"`
Salt []byte `json:",omitempty" toml:",omitempty"`
GlobalPermissions []string `json:",omitempty" toml:",omitempty"`
Accounts []TemplateAccount `json:",omitempty" toml:",omitempty"`
}
type params struct {
ProposalThreshold uint64 `json:",omitempty" toml:",omitempty"`
}
func (gs *GenesisSpec) RealiseKeys(keyClient keys.KeyClient) error {
for _, templateAccount := range gs.Accounts {
_, _, err := templateAccount.RealisePublicKeyAndAddress(keyClient)
if err != nil {
return err
}
}
return nil
}
// Produce a fully realised GenesisDoc from a template GenesisDoc that may omit values
func (gs *GenesisSpec) GenesisDoc(keyClient keys.KeyClient, generateNodeKeys bool) (*genesis.GenesisDoc, error) {
genesisDoc := new(genesis.GenesisDoc)
if gs.GenesisTime == nil {
genesisDoc.GenesisTime = time.Now()
} else {
genesisDoc.GenesisTime = *gs.GenesisTime
}
if gs.ChainName == "" {
genesisDoc.ChainName = fmt.Sprintf("BurrowChain_%X", gs.ShortHash())
} else {
genesisDoc.ChainName = gs.ChainName
}
if gs.Params.ProposalThreshold != 0 {
genesisDoc.Params.ProposalThreshold = DefaultProposalThreshold
}
if len(gs.GlobalPermissions) == 0 {
genesisDoc.GlobalPermissions = permission.DefaultAccountPermissions.Clone()
} else {
basePerms, err := permission.BasePermissionsFromStringList(gs.GlobalPermissions)
if err != nil {
return nil, err
}
genesisDoc.GlobalPermissions = permission.AccountPermissions{
Base: basePerms,
}
}
templateAccounts := gs.Accounts
if len(gs.Accounts) == 0 {
templateAccounts = append(templateAccounts, TemplateAccount{
Amounts: balance.New().Power(DefaultPower),
})
}
for i, templateAccount := range templateAccounts {
account, err := templateAccount.GenesisAccount(keyClient, i)
if err != nil {
return nil, fmt.Errorf("could not create Account from template: %v", err)
}
genesisDoc.Accounts = append(genesisDoc.Accounts, *account)
if templateAccount.Balances().HasPower() {
// Note this does not modify the input template
templateAccount.Address = &account.Address
validator, err := templateAccount.Validator(keyClient, i, generateNodeKeys)
if err != nil {
return nil, fmt.Errorf("could not create Validator from template: %v", err)
}
genesisDoc.Validators = append(genesisDoc.Validators, *validator)
}
}
return genesisDoc, nil
}
func (gs *GenesisSpec) JSONBytes() ([]byte, error) {
bs, err := json.Marshal(gs)
if err != nil {
return nil, err
}
// rewrite buffer with indentation
indentedBuffer := new(bytes.Buffer)
if err := json.Indent(indentedBuffer, bs, "", "\t"); err != nil {
return nil, err
}
return indentedBuffer.Bytes(), nil
}
func (gs *GenesisSpec) Hash() []byte {
gsBytes, err := gs.JSONBytes()
if err != nil {
panic(fmt.Errorf("could not create hash of GenesisDoc: %v", err))
}
hasher := sha256.New()
hasher.Write(gsBytes)
return hasher.Sum(nil)
}
func (gs *GenesisSpec) ShortHash() []byte {
return gs.Hash()[:genesis.ShortHashSuffixBytes]
}
func GenesisSpecFromJSON(jsonBlob []byte) (*GenesisSpec, error) {
genDoc := new(GenesisSpec)
err := json.Unmarshal(jsonBlob, genDoc)
if err != nil {
return nil, fmt.Errorf("couldn't read GenesisSpec: %v", err)
}
return genDoc, nil
}
func accountNameFromIndex(index int) string {
return fmt.Sprintf("Account_%v", index)
}