113 lines
3.5 KiB
Nim
113 lines
3.5 KiB
Nim
|
import db/[db_chain, state_db], genesis_alloc, eth_common, tables, stint,
|
||
|
byteutils, times, config, rlp, ranges, block_types, eth_trie,
|
||
|
eth_trie/memdb, constants, nimcrypto, chronicles
|
||
|
|
||
|
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
|
||
|
nonce*: UInt256
|
||
|
#privateKey: seq[byte] # For tests?
|
||
|
|
||
|
proc toAddress(n: UInt256): EthAddress =
|
||
|
let a = n.toByteArrayBE()
|
||
|
result[0 .. ^1] = a[12 .. ^1]
|
||
|
|
||
|
proc decodePrealloc(data: seq[byte]): GenesisAlloc =
|
||
|
result = newTable[EthAddress, GenesisAccount]()
|
||
|
for tup in rlp.decode(data.toRange, seq[(UInt256, UInt256)]):
|
||
|
result[toAddress(tup[0])] = GenesisAccount(balance: tup[1])
|
||
|
|
||
|
proc defaultGenesisBlockForNetwork*(id: PublicNetwork): Genesis =
|
||
|
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,
|
||
|
alloc: decodePrealloc(testnetAllocData)
|
||
|
)
|
||
|
else:
|
||
|
raise newException(Exception, "No default genesis for " & $id)
|
||
|
result.config = publicChainConfig(id)
|
||
|
|
||
|
proc toBlock*(g: Genesis): BlockHeader =
|
||
|
let tdb = trieDB(newMemDB())
|
||
|
var trie = initHexaryTrie(tdb)
|
||
|
var sdb = newAccountStateDB(tdb, trie.rootHash)
|
||
|
|
||
|
for address, account in g.alloc:
|
||
|
sdb.setBalance(address, account.balance)
|
||
|
sdb.setCode(address, account.code.toRange)
|
||
|
sdb.setNonce(address, account.nonce)
|
||
|
|
||
|
for k, v in account.storage:
|
||
|
sdb.setStorage(address, k, v)
|
||
|
|
||
|
var root = sdb.rootHash
|
||
|
|
||
|
block tempRootHashStub: # TODO: Remove this block when we calculate the root hash correctly
|
||
|
if g.config.chainId == 1:
|
||
|
const correctMainnetRootHash = toDigest("d7f8974fb5ac78d9ac099b9ad5018bedc2ce0a72dad1827a1709da30580f0544")
|
||
|
if root != correctMainnetRootHash:
|
||
|
error "Root hash incorrect. Stubbing it out."
|
||
|
root = correctMainnetRootHash
|
||
|
else:
|
||
|
error "Yay! Root hash is correct. Please remove the block where this message comes from."
|
||
|
|
||
|
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) =
|
||
|
let b = g.toBlock()
|
||
|
assert(b.blockNumber == 0, "can't commit genesis block with number > 0")
|
||
|
discard db.persistHeaderToDb(b)
|