allow nimbus to read geth database

This commit is contained in:
jangko 2020-06-10 12:54:15 +07:00
parent 3eef659d19
commit eabacb0a33
No known key found for this signature in database
GPG Key ID: 31702AE10541E6B9
5 changed files with 69 additions and 10 deletions

View File

@ -222,7 +222,10 @@ proc persistMode(acc: RefAccount): PersistMode =
proc persistCode(acc: RefAccount, db: TrieDatabaseRef) =
if acc.code.len != 0:
db.put(contractHashKey(acc.account.codeHash).toOpenArray, acc.code)
when defined(geth):
db.put(acc.account.codeHash.data, acc.code)
else:
db.put(contractHashKey(acc.account.codeHash).toOpenArray, acc.code)
proc persistStorage(acc: RefAccount, db: TrieDatabaseRef) =
if acc.overlayStorage.len == 0:
@ -283,7 +286,11 @@ proc getCode*(ac: AccountsCache, address: EthAddress): seq[byte] =
if CodeLoaded in acc.flags or CodeChanged in acc.flags:
result = acc.code
else:
let data = ac.db.get(contractHashKey(acc.account.codeHash).toOpenArray)
when defined(geth):
let data = ac.db.get(acc.account.codeHash.data)
else:
let data = ac.db.get(contractHashKey(acc.account.codeHash).toOpenArray)
acc.code = data
acc.flags.incl CodeLoaded
result = acc.code
@ -411,10 +418,11 @@ iterator storage*(ac: AccountsCache, address: EthAddress): (UInt256, UInt256) =
let storageRoot = acc.account.storageRoot
var trie = initHexaryTrie(ac.db, storageRoot)
for slot, value in trie:
if slot.len != 0:
var keyData = ac.db.get(slotHashToSlotKey(slot).toOpenArray)
yield (rlp.decode(keyData, UInt256), rlp.decode(value, UInt256))
for slotHash, value in trie:
if slotHash.len == 0: continue
let keyData = ac.db.get(slotHashToSlotKey(slotHash).toOpenArray)
if keyData.len == 0: continue
yield (rlp.decode(keyData, UInt256), rlp.decode(value, UInt256))
proc getStorageRoot*(ac: AccountsCache, address: EthAddress): Hash256 =
# beware that if the account not persisted,

35
nimbus/db/geth_db.nim Normal file
View File

@ -0,0 +1,35 @@
import eth/[rlp, common], db_chain, eth/trie/db
const
headerPrefix = 'h'.byte # headerPrefix + num (uint64 big endian) + hash -> header
headerHashSuffix = 'n'.byte # headerPrefix + num (uint64 big endian) + headerHashSuffix -> hash
blockBodyPrefix = 'b'.byte # blockBodyPrefix + num (uint64 big endian) + hash -> block body
proc headerHash*(db: BaseChainDB, number: uint64): Hash256 =
var key: array[10, byte]
key[0] = headerPrefix
key[1..8] = toBytesBE(number)[0..^1]
key[^1] = headerHashSuffix
let res = db.db.get(key)
doAssert(res.len == 32)
result.data[0..31] = res[0..31]
proc blockHeader*(db: BaseChainDB, hash: Hash256, number: uint64): BlockHeader =
var key: array[41, byte]
key[0] = headerPrefix
key[1..8] = toBytesBE(number)[0..^1]
key[9..40] = hash.data[0..^1]
let res = db.db.get(key)
result = rlp.decode(res, BlockHeader)
proc blockHeader*(db: BaseChainDB, number: uint64): BlockHeader =
let hash = db.headerHash(number)
db.blockHeader(hash, number)
proc blockBody*(db: BaseChainDB, hash: Hash256, number: uint64): BlockBody =
var key: array[41, byte]
key[0] = blockBodyPrefix
key[1..8] = toBytesBE(number)[0..^1]
key[9..40] = hash.data[0..^1]
let res = db.db.get(key)
result = rlp.decode(res, BlockBody)

View File

@ -150,7 +150,10 @@ proc processBlock*(chainDB: BaseChainDB, header: BlockHeader, body: BlockBody, v
let stateDb = vmState.accountDb
if header.stateRoot != stateDb.rootHash:
error "Wrong state root in block", blockNumber=header.blockNumber, expected=header.stateRoot, actual=stateDb.rootHash, arrivedFrom=chainDB.getCanonicalHead().stateRoot
when defined(geth):
error "Wrong state root in block", blockNumber=header.blockNumber, expected=header.stateRoot, actual=stateDb.rootHash
else:
error "Wrong state root in block", blockNumber=header.blockNumber, expected=header.stateRoot, actual=stateDb.rootHash, arrivedFrom=chainDB.getCanonicalHead().stateRoot
# this one is a show stopper until we are confident in our VM's
# compatibility with the main chain
return ValidationResult.Error

View File

@ -5,8 +5,15 @@ import
chronicles, rpc/hexstrings, launcher,
vm/interpreter/vm_forks, ./config
proc getParentHeader(self: BaseChainDB, header: BlockHeader): BlockHeader =
self.getBlockHeader(header.parentHash)
when defined(geth):
import db/geth_db
proc getParentHeader(db: BaseChainDB, header: BlockHeader): BlockHeader =
db.blockHeader(header.blockNumber.truncate(uint64) - 1)
else:
proc getParentHeader(self: BaseChainDB, header: BlockHeader): BlockHeader =
self.getBlockHeader(header.parentHash)
proc `%`(x: openArray[byte]): JsonNode =
result = %toHex(x, false)

View File

@ -75,6 +75,9 @@ method difficulty*(vmState: BaseVMState): UInt256 {.base, gcsafe.} =
method gasLimit*(vmState: BaseVMState): GasInt {.base, gcsafe.} =
vmState.blockHeader.gasLimit
when defined(geth):
import db/geth_db
method getAncestorHash*(vmState: BaseVMState, blockNumber: BlockNumber): Hash256 {.base, gcsafe.} =
var ancestorDepth = vmState.blockHeader.blockNumber - blockNumber - 1
if ancestorDepth >= constants.MAX_PREV_HEADER_DEPTH:
@ -82,7 +85,10 @@ method getAncestorHash*(vmState: BaseVMState, blockNumber: BlockNumber): Hash256
if blockNumber >= vmState.blockHeader.blockNumber:
return
result = vmState.chainDB.getBlockHash(blockNumber)
when defined(geth):
result = vmState.chainDB.headerHash(blockNumber.truncate(uint64))
else:
result = vmState.chainDB.getBlockHash(blockNumber)
#TODO: should we use deque here?
# someday we may revive this code when
# we already have working miner