diff options
Diffstat (limited to 'core/genesis.go')
-rw-r--r-- | core/genesis.go | 67 |
1 files changed, 59 insertions, 8 deletions
diff --git a/core/genesis.go b/core/genesis.go index d587011f0..a507d522b 100644 --- a/core/genesis.go +++ b/core/genesis.go @@ -17,6 +17,9 @@ package core import ( + "bytes" + "encoding/hex" + "encoding/json" "errors" "fmt" "math/big" @@ -44,24 +47,42 @@ type Genesis struct { Config *params.ChainConfig `json:"config"` Nonce uint64 `json:"nonce"` Timestamp uint64 `json:"timestamp"` - ParentHash common.Hash `json:"parentHash"` ExtraData []byte `json:"extraData"` GasLimit uint64 `json:"gasLimit" gencodec:"required"` Difficulty *big.Int `json:"difficulty" gencodec:"required"` Mixhash common.Hash `json:"mixHash"` Coinbase common.Address `json:"coinbase"` Alloc GenesisAlloc `json:"alloc" gencodec:"required"` + + // These fields are used for consensus tests. Please don't use them + // in actual genesis blocks. + Number uint64 `json:"number"` + GasUsed uint64 `json:"gasUsed"` + ParentHash common.Hash `json:"parentHash"` } // GenesisAlloc specifies the initial state that is part of the genesis block. type GenesisAlloc map[common.Address]GenesisAccount +func (ga *GenesisAlloc) UnmarshalJSON(data []byte) error { + m := make(map[common.UnprefixedAddress]GenesisAccount) + if err := json.Unmarshal(data, &m); err != nil { + return err + } + *ga = make(GenesisAlloc) + for addr, a := range m { + (*ga)[common.Address(addr)] = a + } + return nil +} + // GenesisAccount is an account in the state of the genesis block. type GenesisAccount struct { - Code []byte `json:"code,omitempty"` - Storage map[common.Hash]common.Hash `json:"storage,omitempty"` - Balance *big.Int `json:"balance" gencodec:"required"` - Nonce uint64 `json:"nonce,omitempty"` + Code []byte `json:"code,omitempty"` + Storage map[common.Hash]common.Hash `json:"storage,omitempty"` + Balance *big.Int `json:"balance" gencodec:"required"` + Nonce uint64 `json:"nonce,omitempty"` + PrivateKey []byte `json:"secretKey,omitempty"` // for tests } // field type overrides for gencodec @@ -70,13 +91,38 @@ type genesisSpecMarshaling struct { Timestamp math.HexOrDecimal64 ExtraData hexutil.Bytes GasLimit math.HexOrDecimal64 + GasUsed math.HexOrDecimal64 Difficulty *math.HexOrDecimal256 Alloc map[common.UnprefixedAddress]GenesisAccount } + type genesisAccountMarshaling struct { - Code hexutil.Bytes - Balance *math.HexOrDecimal256 - Nonce math.HexOrDecimal64 + Code hexutil.Bytes + Balance *math.HexOrDecimal256 + Nonce math.HexOrDecimal64 + Storage map[storageJSON]storageJSON + PrivateKey hexutil.Bytes +} + +// storageJSON represents a 256 bit byte array, but allows less than 256 bits when +// unmarshaling from hex. +type storageJSON common.Hash + +func (h *storageJSON) UnmarshalText(text []byte) error { + text = bytes.TrimPrefix(text, []byte("0x")) + if len(text) > 64 { + return fmt.Errorf("too many hex characters in storage key/value %q", text) + } + offset := len(h) - len(text)/2 // pad on the left + if _, err := hex.Decode(h[offset:], text); err != nil { + fmt.Println(err) + return fmt.Errorf("invalid hex storage key/value %q", text) + } + return nil +} + +func (h storageJSON) MarshalText() ([]byte, error) { + return hexutil.Bytes(h[:]).MarshalText() } // GenesisMismatchError is raised when trying to overwrite an existing @@ -187,11 +233,13 @@ func (g *Genesis) ToBlock() (*types.Block, *state.StateDB) { } root := statedb.IntermediateRoot(false) head := &types.Header{ + Number: new(big.Int).SetUint64(g.Number), Nonce: types.EncodeNonce(g.Nonce), Time: new(big.Int).SetUint64(g.Timestamp), ParentHash: g.ParentHash, Extra: g.ExtraData, GasLimit: new(big.Int).SetUint64(g.GasLimit), + GasUsed: new(big.Int).SetUint64(g.GasUsed), Difficulty: g.Difficulty, MixDigest: g.Mixhash, Coinbase: g.Coinbase, @@ -210,6 +258,9 @@ func (g *Genesis) ToBlock() (*types.Block, *state.StateDB) { // The block is committed as the canonical head block. func (g *Genesis) Commit(db ethdb.Database) (*types.Block, error) { block, statedb := g.ToBlock() + if block.Number().Sign() != 0 { + return nil, fmt.Errorf("can't commit genesis block with number > 0") + } if _, err := statedb.CommitTo(db, false); err != nil { return nil, fmt.Errorf("cannot write state: %v", err) } |