/
gengen.go
306 lines (258 loc) · 8.71 KB
/
gengen.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
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
package gengen
import (
"context"
"fmt"
"io"
address "github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
bserv "github.com/ipfs/boxo/blockservice"
blockstore "github.com/ipfs/boxo/blockstore"
offline "github.com/ipfs/boxo/exchange/offline"
dag "github.com/ipfs/boxo/ipld/merkledag"
cid "github.com/ipfs/go-cid"
ds "github.com/ipfs/go-datastore"
cbor "github.com/ipfs/go-ipld-cbor"
format "github.com/ipfs/go-ipld-format"
car "github.com/ipld/go-car"
"github.com/filecoin-project/venus/pkg/crypto"
"github.com/filecoin-project/venus/pkg/genesis"
"github.com/filecoin-project/venus/pkg/wallet/key"
blockstoreutil "github.com/filecoin-project/venus/venus-shared/blockstore"
"github.com/filecoin-project/venus/venus-shared/types"
)
// CreateStorageMinerConfig holds configuration options used to create a storage
// miner in the genesis block. Note: Instances of this struct can be created
// from the contents of fixtures/setup.json, which means that a JSON
// encoder/decoder must exist for any of the struct's fields' types.
type CreateStorageMinerConfig struct {
// Owner is the name of the key that owns this miner
// It must be a name of a key from the configs 'Keys' list
Owner int
// PeerID is the peer ID to set as the miners owner
PeerID string
// CommittedSectors is the list of sector commitments in this miner's proving set
CommittedSectors []*CommitConfig
// RegisteredSealProof is the proof configuration used by this miner
// (which implies sector size and window post partition size)
SealProofType abi.RegisteredSealProof
// ProvingPeriodStart is next chain epoch at which a miner will need to submit a windowed post
// If unset, it will be set to the proving period.
ProvingPeriodStart *abi.ChainEpoch
MarketBalance abi.TokenAmount
}
// CommitConfig carries all information needed to get a sector commitment in the
// genesis state.
type CommitConfig struct {
CommR cid.Cid
CommD cid.Cid
SectorNum abi.SectorNumber
DealCfg *DealConfig
ProofType abi.RegisteredSealProof
}
// DealConfig carries the information needed to specify a self-deal committing
// power to the market while initializing genesis miners
type DealConfig struct {
CommP cid.Cid
PieceSize uint64
Verified bool
// Client and Provider are miner worker and miner address
// StartEpoch is 0
EndEpoch int64
// StoragePricePerEpoch is 0
// Collateral values are 0 for now (might need to change to some minimum)
}
// GenesisCfg is the top level configuration struct used to create a genesis block.
type GenesisCfg struct {
// Seed is used to sample randomness for generating keys
Seed int64
// KeysToGen is the number of random keys to generate and return
KeysToGen int
// Import keys are pre-generated keys to be imported. These keys will be appended to the generated keys.
ImportKeys []*key.KeyInfo
// PreallocatedFunds is a mapping from generated key index to string values of whole filecoin
// that will be preallocated to each account
PreallocatedFunds []string
// Miners is a list of miners that should be set up at the start of the network
Miners []*CreateStorageMinerConfig
// Network is the name of the network
Network string
// Time is the genesis block time in unix seconds
Time uint64
}
// RenderedGenInfo contains information about a genesis block creation
type RenderedGenInfo struct {
// Keys is the set of keys generated
Keys []*key.KeyInfo
// Miners is the list of addresses of miners created
Miners []*RenderedMinerInfo
// GenesisCid is the cid of the created genesis block
GenesisCid cid.Cid
}
// RenderedMinerInfo contains info about a created miner
type RenderedMinerInfo struct {
// Owner is the key name of the owner of this miner
Owner int
// Address is the address generated on-chain for the miner
Address address.Address
// The amount of storage power this miner was created with
RawPower abi.StoragePower
QAPower abi.StoragePower
}
// GenOption is a configuration option.
type GenOption func(*GenesisCfg) error
// GenTime returns a config option setting the genesis time stamp
func GenTime(t uint64) GenOption {
return func(gc *GenesisCfg) error {
gc.Time = t
return nil
}
}
// GenKeys returns a config option that sets the number of keys to generate
func GenKeys(n int, prealloc string) GenOption {
return func(gc *GenesisCfg) error {
if gc.KeysToGen > 0 {
return fmt.Errorf("repeated genkeys not supported")
}
gc.KeysToGen = n
for i := 0; i < n; i++ {
gc.PreallocatedFunds = append(gc.PreallocatedFunds, prealloc)
}
return nil
}
}
// ImportKeys returns a config option that imports keys and pre-allocates to them
func ImportKeys(kis []key.KeyInfo, prealloc string) GenOption {
return func(gc *GenesisCfg) error {
for _, ki := range kis {
gc.ImportKeys = append(gc.ImportKeys, &ki)
gc.PreallocatedFunds = append(gc.PreallocatedFunds, prealloc)
}
return nil
}
}
// Prealloc returns a config option that sets up an actor account.
func Prealloc(idx int, amt string) GenOption {
return func(gc *GenesisCfg) error {
if len(gc.PreallocatedFunds)-1 < idx {
return fmt.Errorf("bad actor account idx %d for only %d pre alloc gen keys", idx, len(gc.PreallocatedFunds))
}
gc.PreallocatedFunds[idx] = amt
return nil
}
}
// NetworkName returns a config option that sets the network name.
func NetworkName(name string) GenOption {
return func(gc *GenesisCfg) error {
gc.Network = name
return nil
}
}
func MinerConfigs(minerCfgs []*CreateStorageMinerConfig) GenOption {
return func(gc *GenesisCfg) error {
gc.Miners = minerCfgs
return nil
}
}
var defaultGenTimeOpt = GenTime(123456789)
// MakeGenesisFunc returns a genesis function configured by a set of options.
func MakeGenesisFunc(opts ...GenOption) genesis.InitFunc {
// Dragons: GenesisInitFunc should take in only a blockstore to remove the hidden
// assumption that cst and bs are backed by the same storage.
return func(cst cbor.IpldStore, bs blockstoreutil.Blockstore) (*types.BlockHeader, error) {
ctx := context.Background()
genCfg := &GenesisCfg{}
err := defaultGenTimeOpt(genCfg)
if err != nil {
return nil, err
}
for _, opt := range opts {
if err := opt(genCfg); err != nil {
return nil, err
}
}
ri, err := GenGen(ctx, genCfg, bs)
if err != nil {
return nil, err
}
var b types.BlockHeader
err = cst.Get(ctx, ri.GenesisCid, &b)
if err != nil {
return nil, err
}
return &b, nil
}
}
// GenGen takes the genesis configuration and creates a genesis block that
// matches the description. It writes all chunks to the dagservice, and returns
// the final genesis block.
//
// WARNING: Do not use maps in this code, they will make this code non deterministic.
func GenGen(ctx context.Context, cfg *GenesisCfg, bs blockstoreutil.Blockstore) (*RenderedGenInfo, error) {
generator := NewGenesisGenerator(bs)
err := generator.Init(cfg)
if err != nil {
return nil, err
}
err = generator.setupBuiltInActors(ctx)
if err != nil {
return nil, err
}
err = generator.setupPrealloc(ctx)
if err != nil {
return nil, err
}
minerInfos, err := generator.setupMiners(ctx)
if err != nil {
return nil, err
}
genCid, err := generator.genBlock(ctx)
if err != nil {
return nil, err
}
return &RenderedGenInfo{
Keys: generator.keys,
GenesisCid: genCid,
Miners: minerInfos,
}, nil
}
// GenGenesisCar generates a car for the given genesis configuration
func GenGenesisCar(cfg *GenesisCfg, out io.Writer) (*RenderedGenInfo, error) {
ctx := context.Background()
bstore := blockstoreutil.WrapIDStore(blockstore.NewBlockstore(ds.NewMapDatastore()))
dserv := dag.NewDAGService(bserv.New(bstore, offline.Exchange(bstore)))
info, err := GenGen(ctx, cfg, bstore)
if err != nil {
return nil, err
}
// Ignore cids that make it on chain but that should not be read through
// and therefore don't have corresponding blocks in store
ignore := cid.NewSet()
for _, m := range cfg.Miners {
for _, comm := range m.CommittedSectors {
ignore.Add(comm.CommR)
ignore.Add(comm.CommD)
ignore.Add(comm.DealCfg.CommP)
}
}
ignoreWalkFunc := func(nd format.Node) (out []*format.Link, err error) {
links := nd.Links()
var filteredLinks []*format.Link
for _, l := range links {
if ignore.Has(l.Cid) {
continue
}
filteredLinks = append(filteredLinks, l)
}
return filteredLinks, nil
}
return info, car.WriteCarWithWalker(ctx, dserv, []cid.Cid{info.GenesisCid}, out, ignoreWalkFunc)
}
// signer doesn't actually sign because it's not actually validated
type signer struct{}
var _ types.Signer = (*signer)(nil)
func (ggs *signer) SignBytes(_ context.Context, data []byte, addr address.Address) (*crypto.Signature, error) {
return nil, nil
}
func (ggs *signer) HasAddress(_ context.Context, addr address.Address) (bool, error) {
return true, nil
}