2018-09-06 20:05:22 +03:00
import .. / db / [ db_chain , state_db ] , eth_common , chronicles , .. / vm_state , .. / vm_types , .. / transaction , ranges ,
2018-09-29 15:36:42 +00:00
.. / vm / [ computation , interpreter_dispatch , message ] , .. / constants , stint , nimcrypto ,
2018-12-04 18:42:55 +07:00
.. / vm_state_transactions , sugar , .. / utils , eth_trie / db , .. / tracer , . / executor , json
2018-08-29 11:49:01 +03:00
type
Chain * = ref object of AbstractChainDB
db : BaseChainDB
proc newChain * ( db : BaseChainDB ) : Chain =
result . new
result . db = db
method genesisHash * ( c : Chain ) : KeccakHash =
c . db . getBlockHash ( 0 . toBlockNumber )
method getBlockHeader * ( c : Chain , b : HashOrNum , output : var BlockHeader ) : bool =
case b . isHash
of true :
c . db . getBlockHeader ( b . hash , output )
else :
c . db . getBlockHeader ( b . number , output )
method getBestBlockHeader * ( c : Chain ) : BlockHeader =
c . db . getCanonicalHead ( )
method getSuccessorHeader * ( c : Chain , h : BlockHeader , output : var BlockHeader ) : bool =
let n = h . blockNumber + 1
c . db . getBlockHeader ( n , output )
method getBlockBody * ( c : Chain , blockHash : KeccakHash ) : BlockBodyRef =
result = nil
method persistBlocks * ( c : Chain , headers : openarray [ BlockHeader ] , bodies : openarray [ BlockBody ] ) =
# Run the VM here
assert ( headers . len = = bodies . len )
2018-09-10 11:44:07 +03:00
let blockReward = 5 . u256 * pow ( 10 . u256 , 18 ) # 5 ETH
2018-10-05 03:20:12 +03:00
let transaction = c . db . db . beginTransaction ( )
defer : transaction . dispose ( )
2018-12-07 00:16:34 +01:00
trace " Persisting blocks " , range = headers [ 0 ] . blockNumber & " - " & headers [ ^ 1 ] . blockNumber
2018-08-29 11:49:01 +03:00
for i in 0 .. < headers . len :
2018-09-10 11:44:07 +03:00
let head = c . db . getCanonicalHead ( )
assert ( head . blockNumber = = headers [ i ] . blockNumber - 1 )
2018-11-30 17:07:20 +07:00
var stateDb = newAccountStateDB ( c . db . db , head . stateRoot , c . db . pruneTrie )
2018-09-10 11:44:07 +03:00
var gasReward = 0 . u256
assert ( bodies [ i ] . transactions . calcTxRoot = = headers [ i ] . txRoot )
2018-09-06 20:05:22 +03:00
if headers [ i ] . txRoot ! = BLANK_ROOT_HASH :
# assert(head.blockNumber == headers[i].blockNumber - 1)
let vmState = newBaseVMState ( head , c . db )
2018-09-10 11:44:07 +03:00
assert ( bodies [ i ] . transactions . len ! = 0 )
2018-09-06 20:05:22 +03:00
if bodies [ i ] . transactions . len ! = 0 :
2018-12-07 00:16:34 +01:00
trace " Has transactions " , blockNumber = headers [ i ] . blockNumber , blockHash = headers [ i ] . blockHash
2018-09-10 11:44:07 +03:00
2018-09-06 20:05:22 +03:00
for t in bodies [ i ] . transactions :
var sender : EthAddress
if t . getSender ( sender ) :
2018-12-03 17:54:19 +07:00
gasReward + = processTransaction ( stateDb , t , sender , vmState )
2018-09-10 11:44:07 +03:00
else :
assert ( false , " Could not get sender " )
var mainReward = blockReward + gasReward
2018-09-27 19:09:26 +00:00
#echo "mainReward = ", mainReward , " with blockReward = ", blockReward, " and gasReward = ", gasReward
2018-09-06 20:05:22 +03:00
if headers [ i ] . ommersHash ! = EMPTY_UNCLE_HASH :
2018-09-10 11:44:07 +03:00
let h = c . db . persistUncles ( bodies [ i ] . uncles )
assert ( h = = headers [ i ] . ommersHash )
for u in 0 .. < bodies [ i ] . uncles . len :
var uncleReward = bodies [ i ] . uncles [ u ] . blockNumber + 8 . u256
uncleReward - = headers [ i ] . blockNumber
uncleReward = uncleReward * blockReward
uncleReward = uncleReward div 8 . u256
stateDb . addBalance ( bodies [ i ] . uncles [ u ] . coinbase , uncleReward )
mainReward + = blockReward div 32 . u256
# Reward beneficiary
stateDb . addBalance ( headers [ i ] . coinbase , mainReward )
if headers [ i ] . stateRoot ! = stateDb . rootHash :
2018-12-07 00:16:34 +01:00
debug " Wrong state root in block " , blockNumber = headers [ i ] . blockNumber , expected = headers [ i ] . stateRoot , actual = stateDb . rootHash , arrivedFrom = c . db . getCanonicalHead ( ) . stateRoot
let ttrace = traceTransaction ( c . db , headers [ i ] , bodies [ i ] , bodies [ i ] . transactions . len - 1 , { } )
trace " NIMBUS TRACE " , transactionTrace = ttrace . pretty ( )
2018-12-04 18:42:55 +07:00
2018-09-10 11:44:07 +03:00
assert ( headers [ i ] . stateRoot = = stateDb . rootHash )
2018-09-06 20:05:22 +03:00
discard c . db . persistHeaderToDb ( headers [ i ] )
assert ( c . db . getCanonicalHead ( ) . blockHash = = headers [ i ] . blockHash )
2018-10-05 03:20:12 +03:00
2018-11-28 09:25:36 +07:00
c . db . persistTransactions ( headers [ i ] . blockNumber , bodies [ i ] . transactions )
2018-11-24 08:00:58 +07:00
2018-10-05 03:20:12 +03:00
transaction . commit ( )