Merge pull request #93 from status-im/genesis
Added genesis initialization
This commit is contained in:
commit
467a9c3d7a
|
@ -7,8 +7,8 @@
|
|||
# This file may not be copied, modified, or distributed except according to
|
||||
# those terms.
|
||||
|
||||
import parseopt, strutils
|
||||
import asyncdispatch2, eth_keys, eth_p2p
|
||||
import parseopt, strutils, macros
|
||||
import asyncdispatch2, eth_keys, eth_p2p, eth_common, chronicles
|
||||
|
||||
const
|
||||
NimbusName* = "Nimbus"
|
||||
|
@ -94,14 +94,16 @@ type
|
|||
flags*: set[RpcFlags] ## RPC flags
|
||||
binds*: seq[TransportAddress] ## RPC bind address
|
||||
|
||||
PublicNetwork* = enum
|
||||
CustomNet = 0
|
||||
MainNet = 1
|
||||
MordenNet = 2
|
||||
RopstenNet = 3
|
||||
RinkebyNet = 4
|
||||
KovanNet = 42
|
||||
|
||||
NetworkFlags* = enum
|
||||
## Ethereum network flags
|
||||
RopstenNet, ## Use test Ropsten network
|
||||
RinkebyNet, ## Use test Rinkeby network
|
||||
MordenNet, ## Use test Morden network
|
||||
KovanNet, ## Use test Kovan network
|
||||
CustomNet, ## Use custom network
|
||||
MainNet, ## Use main network only
|
||||
NoDiscover, ## Peer discovery disabled
|
||||
V5Discover, ## Dicovery V5 enabled
|
||||
|
||||
|
@ -128,6 +130,22 @@ type
|
|||
## Debug configuration object
|
||||
flags*: set[DebugFlags] ## Debug flags
|
||||
|
||||
ChainConfig* = object
|
||||
chainId*: uint
|
||||
homesteadBlock*: BlockNumber
|
||||
daoForkBlock*: BlockNumber
|
||||
daoForkSupport*: bool
|
||||
|
||||
# EIP150 implements the Gas price changes (https://github.com/ethereum/EIPs/issues/150)
|
||||
eip150Block*: BlockNumber
|
||||
eip150Hash*: Hash256
|
||||
|
||||
eip155Block*: BlockNumber
|
||||
eip158Block*: BlockNumber
|
||||
|
||||
byzantiumBlock*: BlockNumber
|
||||
constantinopleBlock*: BlockNumber
|
||||
|
||||
NimbusConfiguration* = ref object
|
||||
## Main Nimbus configuration object
|
||||
rpc*: RpcConfiguration ## JSON-RPC configuration
|
||||
|
@ -138,6 +156,49 @@ var nimbusConfig {.threadvar.}: NimbusConfiguration
|
|||
|
||||
proc getConfiguration*(): NimbusConfiguration {.gcsafe.}
|
||||
|
||||
proc publicChainConfig*(id: PublicNetwork): ChainConfig =
|
||||
result = case id
|
||||
of MainNet:
|
||||
ChainConfig(
|
||||
chainId: MainNet.uint,
|
||||
homesteadBlock: 1150000.u256,
|
||||
daoForkBlock: 1920000.u256,
|
||||
daoForkSupport: true,
|
||||
eip150Block: 2463000.u256,
|
||||
eip150Hash: toDigest("2086799aeebeae135c246c65021c82b4e15a2c451340993aacfd2751886514f0"),
|
||||
eip155Block: 2675000.u256,
|
||||
eip158Block: 2675000.u256,
|
||||
byzantiumBlock: 4370000.u256
|
||||
)
|
||||
of RopstenNet:
|
||||
ChainConfig(
|
||||
chainId: RopstenNet.uint,
|
||||
homesteadBlock: 0.u256,
|
||||
daoForkSupport: true,
|
||||
eip150Block: 0.u256,
|
||||
eip150Hash: toDigest("41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d"),
|
||||
eip155Block: 10.u256,
|
||||
eip158Block: 10.u256,
|
||||
byzantiumBlock: 1700000.u256
|
||||
)
|
||||
of RinkebyNet:
|
||||
ChainConfig(
|
||||
chainId: RinkebyNet.uint,
|
||||
homesteadBlock: 1.u256,
|
||||
daoForkSupport: true,
|
||||
eip150Block: 2.u256,
|
||||
eip150Hash: toDigest("9b095b36c15eaf13044373aef8ee0bd3a382a5abb92e402afa44b8249c3a90e9"),
|
||||
eip155Block: 3.u256,
|
||||
eip158Block: 3.u256,
|
||||
byzantiumBlock: 1035301.u256
|
||||
)
|
||||
else:
|
||||
error "No chain config for public network", networkId = id
|
||||
doAssert(false, "No chain config for " & $id)
|
||||
ChainConfig()
|
||||
|
||||
result.chainId = uint(id)
|
||||
|
||||
proc processList(v: string, o: var seq[string]) =
|
||||
## Process comma-separated list of strings.
|
||||
if len(v) > 0:
|
||||
|
@ -243,42 +304,46 @@ proc processRpcArguments(key, value: string): ConfigStatus =
|
|||
else:
|
||||
result = EmptyOption
|
||||
|
||||
template setBootnodes(onodes, nodes: untyped): untyped =
|
||||
proc setBootnodes(onodes: var seq[ENode], nodeUris: openarray[string]) =
|
||||
var node: ENode
|
||||
for item in (nodes):
|
||||
onodes = newSeqOfCap[ENode](nodeUris.len)
|
||||
for item in nodeUris:
|
||||
doAssert(processENode(item, node) == Success)
|
||||
(onodes).add(node)
|
||||
onodes.add(node)
|
||||
|
||||
proc setNetwork(conf: var NetConfiguration, network: NetworkFlags,
|
||||
id: uint = 0) =
|
||||
macro availableEnumValues(T: type enum): untyped =
|
||||
let impl = getTypeImpl(T)[1].getTypeImpl()
|
||||
result = newNimNode(nnkBracket)
|
||||
for i in 1 ..< impl.len: result.add(newCall("uint", copyNimTree(impl[i])))
|
||||
|
||||
proc toPublicNetwork*(id: uint): PublicNetwork {.inline.} =
|
||||
if id in availableEnumValues(PublicNetwork):
|
||||
result = PublicNetwork(id)
|
||||
|
||||
proc setNetwork(conf: var NetConfiguration, id: PublicNetwork) =
|
||||
## Set network id and default network bootnodes
|
||||
conf.flags.excl({MainNet, MordenNet, RopstenNet, RinkebyNet, KovanNet,
|
||||
CustomNet})
|
||||
conf.flags.incl(network)
|
||||
assert(not conf.bootNodes.isNil) # Nim bug #7833
|
||||
case network
|
||||
conf.networkId = uint(id)
|
||||
case id
|
||||
of MainNet:
|
||||
conf.networkId = uint(1)
|
||||
conf.bootNodes.setLen(0)
|
||||
conf.bootNodes.setBootnodes(MainnetBootnodes)
|
||||
of MordenNet:
|
||||
conf.networkId = uint(2)
|
||||
discard
|
||||
of RopstenNet:
|
||||
conf.networkId = uint(3)
|
||||
conf.bootNodes.setLen(0)
|
||||
conf.bootNodes.setBootnodes(RopstenBootnodes)
|
||||
of RinkebyNet:
|
||||
conf.networkId = uint(4)
|
||||
conf.bootNodes.setLen(0)
|
||||
conf.bootNodes.setBootnodes(RinkebyBootnodes)
|
||||
of KovanNet:
|
||||
conf.networkId = uint(42)
|
||||
conf.bootNodes.setLen(0)
|
||||
conf.bootNodes.setBootnodes(KovanBootnodes)
|
||||
of CustomNet:
|
||||
discard
|
||||
|
||||
proc setNetwork(conf: var NetConfiguration, id: uint) =
|
||||
## Set network id and default network bootnodes
|
||||
let pubNet = toPublicNetwork(id)
|
||||
if pubNet == CustomNet:
|
||||
conf.networkId = id
|
||||
else:
|
||||
discard
|
||||
conf.setNetwork(pubNet)
|
||||
|
||||
proc processNetArguments(key, value: string): ConfigStatus =
|
||||
## Processes only `Networking` related command line options
|
||||
|
@ -307,24 +372,11 @@ proc processNetArguments(key, value: string): ConfigStatus =
|
|||
var res = 0
|
||||
result = processInteger(value, res)
|
||||
if result == Success:
|
||||
case res
|
||||
of 1:
|
||||
config.net.setNetwork(MainNet)
|
||||
of 2:
|
||||
config.net.setNetwork(MordenNet)
|
||||
of 3:
|
||||
config.net.setNetwork(RopstenNet)
|
||||
of 4:
|
||||
config.net.setNetwork(RinkebyNet)
|
||||
of 42:
|
||||
config.net.setNetwork(KovanNet)
|
||||
else:
|
||||
config.net.setNetwork(CustomNet, uint(res))
|
||||
config.net.setNetwork(uint(result))
|
||||
elif skey == "nodiscover":
|
||||
config.net.flags.incl(NoDiscover)
|
||||
elif skey == "v5discover":
|
||||
config.net.flags.incl(V5Discover)
|
||||
config.net.bootNodes.setLen(0)
|
||||
config.net.bootNodes.setBootnodes(DiscoveryV5Bootnodes)
|
||||
elif skey == "port":
|
||||
var res = 0
|
||||
|
@ -403,8 +455,7 @@ proc initConfiguration(): NimbusConfiguration =
|
|||
result.rpc.binds = @[initTAddress("127.0.0.1:8545")]
|
||||
|
||||
## Network defaults
|
||||
result.net.bootNodes = @[] # Nim bug #7833
|
||||
result.net.setNetwork(RopstenNet)
|
||||
result.net.setNetwork(MainNet)
|
||||
result.net.maxPeers = 25
|
||||
result.net.maxPendingPeers = 0
|
||||
result.net.bindPort = 30303'u16
|
||||
|
|
|
@ -30,36 +30,55 @@ proc newBaseChainDB*(db: TrieDatabaseRef): BaseChainDB =
|
|||
proc `$`*(db: BaseChainDB): string =
|
||||
result = "BaseChainDB"
|
||||
|
||||
proc getBlockHeaderByHash*(self: BaseChainDB; blockHash: Hash256): BlockHeader =
|
||||
## Returns the requested block header as specified by block hash.
|
||||
##
|
||||
## Raises BlockNotFound if it is not present in the db.
|
||||
proc getBlockHeader*(self: BaseChainDB; blockHash: Hash256, output: var BlockHeader): bool =
|
||||
try:
|
||||
let blk = self.db.get(genericHashKey(blockHash).toOpenArray).toRange
|
||||
return decode(blk, BlockHeader)
|
||||
if blk.len != 0:
|
||||
output = rlp.decode(blk, BlockHeader)
|
||||
result = true
|
||||
except KeyError:
|
||||
discard
|
||||
|
||||
proc getBlockHeader*(self: BaseChainDB, blockHash: Hash256): BlockHeader =
|
||||
## Returns the requested block header as specified by block hash.
|
||||
##
|
||||
## Raises BlockNotFound if it is not present in the db.
|
||||
if not self.getBlockHeader(blockHash, result):
|
||||
raise newException(BlockNotFound, "No block with hash " & blockHash.data.toHex)
|
||||
|
||||
proc getHash(self: BaseChainDB, key: DbKey): Hash256 {.inline.} =
|
||||
rlp.decode(self.db.get(key.toOpenArray).toRange, Hash256)
|
||||
proc getHash(self: BaseChainDB, key: DbKey, output: var Hash256): bool {.inline.} =
|
||||
try:
|
||||
output = rlp.decode(self.db.get(key.toOpenArray).toRange, Hash256)
|
||||
result = true
|
||||
except KeyError:
|
||||
discard
|
||||
|
||||
proc getCanonicalHead*(self: BaseChainDB): BlockHeader =
|
||||
let k = canonicalHeadHashKey()
|
||||
if k.toOpenArray notin self.db:
|
||||
var headHash: Hash256
|
||||
if not self.getHash(canonicalHeadHashKey(), headHash) or
|
||||
not self.getBlockHeader(headHash, result):
|
||||
raise newException(CanonicalHeadNotFound,
|
||||
"No canonical head set for this chain")
|
||||
return self.getBlockHeaderByHash(self.getHash(k))
|
||||
|
||||
proc lookupBlockHash*(self: BaseChainDB; n: BlockNumber): Hash256 {.inline.} =
|
||||
## Return the block hash for the given block number.
|
||||
self.getHash(blockNumberToHashKey(n))
|
||||
proc getBlockHash*(self: BaseChainDB, n: BlockNumber, output: var Hash256): bool {.inline.} =
|
||||
## Return the block hash for the given block number.
|
||||
self.getHash(blockNumberToHashKey(n), output)
|
||||
|
||||
proc getCanonicalBlockHeaderByNumber*(self: BaseChainDB; n: BlockNumber): BlockHeader =
|
||||
## Returns the block header with the given number in the canonical chain.
|
||||
##
|
||||
## Raises BlockNotFound if there's no block header with the given number in the
|
||||
## canonical chain.
|
||||
self.getBlockHeaderByHash(self.lookupBlockHash(n))
|
||||
proc getBlockHash*(self: BaseChainDB, n: BlockNumber): Hash256 {.inline.} =
|
||||
## Return the block hash for the given block number.
|
||||
if not self.getHash(blockNumberToHashKey(n), result):
|
||||
raise newException(BlockNotFound, "No block hash for number " & $n)
|
||||
|
||||
proc getBlockHeader*(self: BaseChainDB; n: BlockNumber, output: var BlockHeader): bool =
|
||||
## Returns the block header with the given number in the canonical chain.
|
||||
var blockHash: Hash256
|
||||
if self.getBlockHash(n, blockHash):
|
||||
result = self.getBlockHeader(blockHash, output)
|
||||
|
||||
proc getBlockHeader*(self: BaseChainDB; n: BlockNumber): BlockHeader =
|
||||
## Returns the block header with the given number in the canonical chain.
|
||||
## Raises BlockNotFound error if the block is not in the DB.
|
||||
self.getBlockHeader(self.getBlockHash(n))
|
||||
|
||||
proc getScore*(self: BaseChainDB; blockHash: Hash256): int =
|
||||
rlp.decode(self.db.get(blockHashToScoreKey(blockHash).toOpenArray).toRange, int)
|
||||
|
@ -68,20 +87,17 @@ iterator findNewAncestors(self: BaseChainDB; header: BlockHeader): BlockHeader =
|
|||
## Returns the chain leading up from the given header until the first ancestor it has in
|
||||
## common with our canonical chain.
|
||||
var h = header
|
||||
var orig: BlockHeader
|
||||
while true:
|
||||
try:
|
||||
let orig = self.getCanonicalBlockHeaderByNumber(h.blockNumber)
|
||||
if orig.hash == h.hash:
|
||||
break
|
||||
except BlockNotFound:
|
||||
discard
|
||||
if self.getBlockHeader(h.blockNumber, orig) and orig.hash == h.hash:
|
||||
break
|
||||
|
||||
yield h
|
||||
|
||||
if h.parentHash == GENESIS_PARENT_HASH:
|
||||
break
|
||||
else:
|
||||
h = self.getBlockHeaderByHash(h.parentHash)
|
||||
h = self.getBlockHeader(h.parentHash)
|
||||
|
||||
proc addBlockNumberToHashLookup(self: BaseChainDB; header: BlockHeader) =
|
||||
self.db.put(blockNumberToHashKey(header.blockNumber).toOpenArray,
|
||||
|
@ -104,19 +120,16 @@ proc removeTransactionFromCanonicalChain(self: BaseChainDB, transactionHash: Has
|
|||
|
||||
proc setAsCanonicalChainHead(self: BaseChainDB; headerHash: Hash256): seq[BlockHeader] =
|
||||
## Sets the header as the canonical chain HEAD.
|
||||
|
||||
let header = self.getBlockHeaderByHash(headerHash)
|
||||
let header = self.getBlockHeader(headerHash)
|
||||
|
||||
var newCanonicalHeaders = sequtils.toSeq(findNewAncestors(self, header))
|
||||
reverse(newCanonicalHeaders)
|
||||
for h in newCanonicalHeaders:
|
||||
var oldHash: Hash256
|
||||
try:
|
||||
oldHash = self.lookupBlockHash(h.blockNumber)
|
||||
except BlockNotFound:
|
||||
if not self.getBlockHash(h.blockNumber, oldHash):
|
||||
break
|
||||
|
||||
let oldHeader = self.getBlockHeaderByHash(oldHash)
|
||||
let oldHeader = self.getBlockHeader(oldHash)
|
||||
for txHash in self.getBlockTransactionHashes(oldHeader):
|
||||
self.removeTransactionFromCanonicalChain(txHash)
|
||||
# TODO re-add txn to internal pending pool (only if local sender)
|
||||
|
@ -171,6 +184,8 @@ proc persistHeaderToDb*(self: BaseChainDB; header: BlockHeader): seq[BlockHeader
|
|||
else: self.getScore(header.parentHash).u256 + header.difficulty
|
||||
self.db.put(blockHashToScoreKey(header.hash).toOpenArray, rlp.encode(score).toOpenArray)
|
||||
|
||||
self.addBlockNumberToHashLookup(header)
|
||||
|
||||
var headScore: int
|
||||
try:
|
||||
headScore = self.getScore(self.getCanonicalHead().hash)
|
||||
|
@ -230,6 +245,41 @@ proc persistBlockToDb*(self: BaseChainDB; blk: Block) =
|
|||
proc getStateDb*(self: BaseChainDB; stateRoot: Hash256; readOnly: bool = false): AccountStateDB =
|
||||
result = newAccountStateDB(self.db, stateRoot)
|
||||
|
||||
method genesisHash*(db: BaseChainDB): KeccakHash =
|
||||
db.getBlockHash(0.toBlockNumber)
|
||||
|
||||
method getBlockHeader*(db: BaseChainDB, b: HashOrNum): BlockHeaderRef =
|
||||
var h: BlockHeader
|
||||
var ok = case b.isHash
|
||||
of true:
|
||||
db.getBlockHeader(b.hash, h)
|
||||
else:
|
||||
db.getBlockHeader(b.number, h)
|
||||
|
||||
if ok:
|
||||
result.new()
|
||||
result[] = h
|
||||
|
||||
method getBestBlockHeader*(self: BaseChainDB): BlockHeaderRef =
|
||||
result.new()
|
||||
result[] = self.getCanonicalHead()
|
||||
|
||||
method getSuccessorHeader*(db: BaseChainDB, h: BlockHeader): BlockHeaderRef =
|
||||
let n = h.blockNumber + 1
|
||||
var r: BlockHeader
|
||||
if db.getBlockHeader(n, r):
|
||||
result.new()
|
||||
result[] = r
|
||||
|
||||
method getBlockBody*(db: BaseChainDB, blockHash: KeccakHash): BlockBodyRef =
|
||||
result = nil
|
||||
|
||||
# Deprecated:
|
||||
proc getBlockHeaderByHash*(self: BaseChainDB; blockHash: Hash256): BlockHeader {.deprecated.} =
|
||||
self.getBlockHeader(blockHash)
|
||||
|
||||
proc lookupBlockHash*(self: BaseChainDB; n: BlockNumber): Hash256 {.deprecated.} =
|
||||
self.getBlockHash(n)
|
||||
|
||||
proc getCanonicalBlockHeaderByNumber*(self: BaseChainDB; n: BlockNumber): BlockHeader {.deprecated.} =
|
||||
self.getBlockHeader(n)
|
||||
|
|
|
@ -0,0 +1,114 @@
|
|||
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
|
||||
|
||||
func toAddress(n: UInt256): EthAddress =
|
||||
let a = n.toByteArrayBE()
|
||||
result[0 .. ^1] = a.toOpenArray(12, a.high)
|
||||
|
||||
func 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(rinkebyAllocData)
|
||||
)
|
||||
else:
|
||||
# TODO: Fill out the rest
|
||||
error "No default genesis for network", id
|
||||
doAssert(false, "No default genesis for " & $id)
|
||||
Genesis()
|
||||
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)
|
File diff suppressed because one or more lines are too long
|
@ -11,7 +11,7 @@ import
|
|||
os, strutils, net, eth_common, db/[storage_types, db_chain],
|
||||
asyncdispatch2, json_rpc/rpcserver, eth_keys,
|
||||
eth_p2p, eth_p2p/rlpx_protocols/[eth, les],
|
||||
config, rpc/[common, p2p],
|
||||
config, genesis, rpc/[common, p2p],
|
||||
eth_trie
|
||||
|
||||
const UseSqlite = true
|
||||
|
@ -43,10 +43,15 @@ type
|
|||
|
||||
proc newTrieDb(): TrieDatabaseRef =
|
||||
# XXX: Setup db storage location according to config
|
||||
result = trieDB(newChainDb(":memory:"))
|
||||
result = trieDB(newChainDb("nimbus.db"))
|
||||
|
||||
proc initializeEmptyDb(db: BaseChainDB) =
|
||||
echo "Initializing empty DB (TODO)"
|
||||
echo "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)
|
||||
|
||||
proc start(): NimbusObject =
|
||||
var nimbus = NimbusObject()
|
||||
|
@ -75,6 +80,7 @@ proc start(): NimbusObject =
|
|||
|
||||
if canonicalHeadHashKey().toOpenArray notin trieDB:
|
||||
initializeEmptyDb(chainDb)
|
||||
assert(canonicalHeadHashKey().toOpenArray in trieDB)
|
||||
|
||||
nimbus.ethNode = newEthereumNode(keypair, address, conf.net.networkId,
|
||||
nil, nimbusClientId)
|
||||
|
|
|
@ -11,7 +11,8 @@ when true:
|
|||
./test_memory,
|
||||
./test_stack,
|
||||
./test_opcode,
|
||||
./test_storage_backends
|
||||
./test_storage_backends,
|
||||
./test_genesis
|
||||
|
||||
when false:
|
||||
import ./test_vm_json
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
import unittest, ../nimbus/[genesis, config], eth_common
|
||||
|
||||
suite "Genesis":
|
||||
test "Correct mainnet hash":
|
||||
let g = defaultGenesisBlockForNetwork(MainNet)
|
||||
let b = g.toBlock
|
||||
check(b.blockHash == "D4E56740F876AEF8C010B86A40D5F56745A118D0906A34E69AEC8C0DB1CB8FA3".toDigest)
|
Loading…
Reference in New Issue