nimbus-eth1/nimbus/genesis.nim

115 lines
3.5 KiB
Nim
Raw Normal View History

import
times, tables,
2019-02-05 19:15:50 +00:00
eth/[common, rlp, trie], stint, byteutils, ranges, block_types, nimcrypto,
chronicles, eth/trie/db,
db/[db_chain, state_db], genesis_alloc, config, constants
2018-08-01 12:50:44 +00:00
type
Genesis* = object
config*: ChainConfig
nonce*: BlockNonce
timestamp*: EthTime
extraData*: seq[byte]
gasLimit*: GasInt
difficulty*: DifficultyInt
mixhash*: Hash256
coinbase*: EthAddress
alloc*: GenesisAlloc
GenesisAlloc = TableRef[EthAddress, GenesisAccount]
GenesisAccount = object
code*: seq[byte]
storage*: Table[UInt256, UInt256]
balance*: UInt256
2018-09-02 02:26:22 +00:00
nonce*: AccountNonce
2018-08-01 12:50:44 +00:00
2018-08-02 14:08:10 +00:00
func toAddress(n: UInt256): EthAddress =
2018-08-01 12:50:44 +00:00
let a = n.toByteArrayBE()
2018-08-02 14:08:10 +00:00
result[0 .. ^1] = a.toOpenArray(12, a.high)
2018-08-01 12:50:44 +00:00
2018-08-02 14:08:10 +00:00
func decodePrealloc(data: seq[byte]): GenesisAlloc =
2018-08-01 12:50:44 +00:00
result = newTable[EthAddress, GenesisAccount]()
for tup in rlp.decode(data.toRange, seq[(UInt256, UInt256)]):
result[toAddress(tup[0])] = GenesisAccount(balance: tup[1])
2018-08-03 11:10:07 +00:00
proc defaultGenesisBlockForNetwork*(id: PublicNetwork): Genesis =
2018-08-01 12:50:44 +00:00
result = case id
of MainNet:
Genesis(
nonce: 66.toBlockNonce,
extraData: hexToSeqByte("0x11bbe8db4e347b4e8c937c1c8370e4b5ed33adb3db69cbdb7a38e1e50b1b82fa"),
gasLimit: 5000,
difficulty: 17179869184.u256,
alloc: decodePrealloc(mainnetAllocData)
)
of RopstenNet:
Genesis(
nonce: 66.toBlockNonce,
extraData: hexToSeqByte("0x3535353535353535353535353535353535353535353535353535353535353535"),
gasLimit: 16777216,
difficulty: 1048576.u256,
alloc: decodePrealloc(testnetAllocData)
)
of RinkebyNet:
Genesis(
nonce: 66.toBlockNonce,
extraData: hexToSeqByte("0x3535353535353535353535353535353535353535353535353535353535353535"),
gasLimit: 16777216,
difficulty: 1048576.u256,
2018-08-02 14:16:34 +00:00
alloc: decodePrealloc(rinkebyAllocData)
2018-08-01 12:50:44 +00:00
)
else:
2018-08-03 11:10:07 +00:00
# TODO: Fill out the rest
error "No default genesis for network", id
doAssert(false, "No default genesis for " & $id)
Genesis()
2018-08-01 12:50:44 +00:00
result.config = publicChainConfig(id)
2018-09-10 08:44:07 +00:00
proc toBlock*(g: Genesis, db: BaseChainDB = nil): BlockHeader =
2018-11-30 10:07:20 +00:00
let (tdb, pruneTrie) = if db.isNil: (newMemoryDB(), true)
else: (db.db, db.pruneTrie)
2018-08-01 12:50:44 +00:00
var trie = initHexaryTrie(tdb)
2018-11-30 10:07:20 +00:00
var sdb = newAccountStateDB(tdb, trie.rootHash, pruneTrie)
2018-08-01 12:50:44 +00:00
for address, account in g.alloc:
2018-08-09 09:25:37 +00:00
sdb.setAccount(address, newAccount(account.nonce, account.balance))
sdb.setCode(address, account.code.toRange)
for k, v in account.storage:
sdb.setStorage(address, k, v)
2018-08-01 12:50:44 +00:00
var root = sdb.rootHash
2018-08-01 12:50:44 +00:00
result = BlockHeader(
nonce: g.nonce,
timestamp: g.timestamp,
extraData: g.extraData,
gasLimit: g.gasLimit,
difficulty: g.difficulty,
mixDigest: g.mixhash,
coinbase: g.coinbase,
stateRoot: root,
parentHash: GENESIS_PARENT_HASH,
txRoot: BLANK_ROOT_HASH,
receiptRoot: BLANK_ROOT_HASH,
ommersHash: EMPTY_UNCLE_HASH
)
if g.gasLimit == 0:
result.gasLimit = GENESIS_GAS_LIMIT
if g.difficulty == 0:
result.difficulty = GENESIS_DIFFICULTY
proc commit*(g: Genesis, db: BaseChainDB) =
2018-09-10 08:44:07 +00:00
let b = g.toBlock(db)
2018-08-01 12:50:44 +00:00
assert(b.blockNumber == 0, "can't commit genesis block with number > 0")
discard db.persistHeaderToDb(b)
2019-01-08 10:47:40 +00:00
proc initializeEmptyDb*(db: BaseChainDB) =
trace "Writing genesis to DB"
let networkId = getConfiguration().net.networkId.toPublicNetwork()
if networkId == CustomNet:
raise newException(Exception, "Custom genesis not implemented")
else:
defaultGenesisBlockForNetwork(networkId).commit(db)