2018-10-05 00:20:12 +00:00
|
|
|
import
|
2021-03-18 15:05:15 +00:00
|
|
|
tables, json, times, strutils,
|
2020-04-20 18:12:44 +00:00
|
|
|
eth/[common, rlp, trie], stint, stew/[byteutils],
|
2019-02-05 19:15:50 +00:00
|
|
|
chronicles, eth/trie/db,
|
2018-10-16 00:10:01 +00:00
|
|
|
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]()
|
2020-04-20 18:12:44 +00:00
|
|
|
for tup in rlp.decode(data, seq[(UInt256, UInt256)]):
|
2018-08-01 12:50:44 +00:00
|
|
|
result[toAddress(tup[0])] = GenesisAccount(balance: tup[1])
|
|
|
|
|
2020-04-09 10:06:08 +00:00
|
|
|
proc customNetPrealloc(genesisBlock: JsonNode): GenesisAlloc =
|
2020-01-13 18:35:40 +00:00
|
|
|
result = newTable[EthAddress, GenesisAccount]()
|
2021-03-18 15:05:15 +00:00
|
|
|
for address, account in genesisBlock.pairs():
|
2021-03-31 06:11:09 +00:00
|
|
|
let nonce = if "nonce" in account:
|
|
|
|
parseHexInt(account["nonce"].getStr).AccountNonce
|
|
|
|
else:
|
|
|
|
AccountNonce(0)
|
|
|
|
|
2021-03-31 06:42:12 +00:00
|
|
|
let code = if "code" in account:
|
|
|
|
hexToSeqByte(account["code"].getStr)
|
|
|
|
else:
|
|
|
|
@[]
|
|
|
|
|
2021-03-18 15:05:15 +00:00
|
|
|
var acc = GenesisAccount(
|
|
|
|
balance: fromHex(UInt256, account["balance"].getStr),
|
2021-03-31 06:42:12 +00:00
|
|
|
code: code,
|
2021-03-31 06:11:09 +00:00
|
|
|
nonce: nonce
|
2021-03-18 15:05:15 +00:00
|
|
|
)
|
2021-03-31 06:11:09 +00:00
|
|
|
|
|
|
|
if "storage" in account:
|
|
|
|
let storage = account["storage"]
|
|
|
|
for k, v in storage:
|
|
|
|
acc.storage[fromHex(UInt256, k)] = fromHex(UInt256, v.getStr)
|
|
|
|
|
2021-03-18 15:05:15 +00:00
|
|
|
result[parseAddress(address)] = acc
|
2020-01-13 18:35:40 +00:00
|
|
|
|
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(
|
2020-04-09 10:06:08 +00:00
|
|
|
nonce: 0.toBlockNonce,
|
|
|
|
timestamp: initTime(0x58ee40ba, 0),
|
|
|
|
extraData: hexToSeqByte("0x52657370656374206d7920617574686f7269746168207e452e436172746d616e42eb768f2244c8811c63729a21a3569731535f067ffc57839b00206d1ad20c69a1981b489f772031b279182d99e65703f0076e4812653aab85fca0f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"),
|
|
|
|
gasLimit: 4700000,
|
|
|
|
difficulty: 1.u256,
|
2018-08-02 14:16:34 +00:00
|
|
|
alloc: decodePrealloc(rinkebyAllocData)
|
2018-08-01 12:50:44 +00:00
|
|
|
)
|
2020-04-09 10:06:08 +00:00
|
|
|
of GoerliNet:
|
|
|
|
Genesis(
|
|
|
|
nonce: 0.toBlockNonce,
|
|
|
|
timestamp: initTime(0x5c51a607, 0),
|
|
|
|
extraData: hexToSeqByte("0x22466c6578692069732061207468696e6722202d204166726900000000000000e0a2bd4258d2768837baa26a28fe71dc079f84c70000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"),
|
|
|
|
gasLimit: 0xa00000,
|
|
|
|
difficulty: 1.u256,
|
|
|
|
alloc: decodePrealloc(goerliAllocData)
|
|
|
|
)
|
2020-01-13 18:35:40 +00:00
|
|
|
of CustomNet:
|
|
|
|
let genesis = getConfiguration().customGenesis
|
|
|
|
var alloc = new GenesisAlloc
|
2021-05-12 01:57:24 +00:00
|
|
|
assert(genesis.prealloc.isNil.not, "genesis prealloc should not nil")
|
2020-01-13 18:35:40 +00:00
|
|
|
if genesis.prealloc != parseJson("{}"):
|
|
|
|
alloc = customNetPrealloc(genesis.prealloc)
|
|
|
|
Genesis(
|
|
|
|
nonce: genesis.nonce,
|
|
|
|
extraData: genesis.extraData,
|
|
|
|
gasLimit: genesis.gasLimit,
|
|
|
|
difficulty: genesis.difficulty,
|
|
|
|
alloc: alloc,
|
|
|
|
timestamp: genesis.timestamp,
|
|
|
|
mixhash: genesis.mixHash,
|
|
|
|
coinbase: genesis.coinbase
|
|
|
|
)
|
|
|
|
|
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))
|
2020-04-20 18:12:44 +00:00
|
|
|
sdb.setCode(address, account.code)
|
2018-08-09 09:25:37 +00:00
|
|
|
for k, v in account.storage:
|
|
|
|
sdb.setStorage(address, k, v)
|
2018-08-01 12:50:44 +00:00
|
|
|
|
2018-08-08 12:48:34 +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)
|
2019-03-13 21:36:54 +00:00
|
|
|
doAssert(b.blockNumber == 0, "can't commit genesis block with number > 0")
|
2018-08-01 12:50:44 +00:00
|
|
|
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()
|
2020-01-13 18:35:40 +00:00
|
|
|
# if networkId == CustomNet:
|
|
|
|
# raise newException(Exception, "Custom genesis not implemented")
|
|
|
|
# else:
|
|
|
|
defaultGenesisBlockForNetwork(networkId).commit(db)
|