miner address calculation for PoA consensus engine

This commit is contained in:
jangko 2020-06-19 20:24:09 +07:00
parent 2e583e9aa0
commit 2385df7bae
No known key found for this signature in database
GPG Key ID: 31702AE10541E6B9
2 changed files with 69 additions and 15 deletions

View File

@ -26,16 +26,18 @@ proc processTransaction*(tx: Transaction, sender: EthAddress, vmState: BaseVMSta
vmState.cumulativeGasUsed += result vmState.cumulativeGasUsed += result
let miner = vmState.getMinerAddress()
vmState.mutateStateDB: vmState.mutateStateDB:
# miner fee # miner fee
let txFee = result.u256 * tx.gasPrice.u256 let txFee = result.u256 * tx.gasPrice.u256
db.addBalance(vmState.blockHeader.coinbase, txFee) db.addBalance(miner, txFee)
for deletedAccount in vmState.suicides: for deletedAccount in vmState.suicides:
db.deleteAccount deletedAccount db.deleteAccount deletedAccount
if fork >= FkSpurious: if fork >= FkSpurious:
vmState.touchedAccounts.incl(vmState.blockHeader.coinbase) vmState.touchedAccounts.incl(miner)
# EIP158/161 state clearing # EIP158/161 state clearing
for account in vmState.touchedAccounts: for account in vmState.touchedAccounts:
if db.accountExists(account) and db.isEmptyAccount(account): if db.accountExists(account) and db.isEmptyAccount(account):
@ -93,6 +95,25 @@ const
eth2 # FkIstanbul eth2 # FkIstanbul
] ]
proc calculateReward(fork: Fork, header: BlockHeader, body: BlockBody, vmState: BaseVMState) =
# PoA consensus engine have no reward for miner
if vmState.consensusEnginePoA: return
let blockReward = blockRewards[fork]
var mainReward = blockReward
for uncle in body.uncles:
var uncleReward = uncle.blockNumber.u256 + 8.u256
uncleReward -= header.blockNumber.u256
uncleReward = uncleReward * blockReward
uncleReward = uncleReward div 8.u256
vmState.mutateStateDB:
db.addBalance(uncle.coinbase, uncleReward)
mainReward += blockReward div 32.u256
vmState.mutateStateDB:
db.addBalance(header.coinbase, mainReward)
proc processBlock*(chainDB: BaseChainDB, header: BlockHeader, body: BlockBody, vmState: BaseVMState): ValidationResult = proc processBlock*(chainDB: BaseChainDB, header: BlockHeader, body: BlockBody, vmState: BaseVMState): ValidationResult =
var dbTx = chainDB.db.beginTransaction() var dbTx = chainDB.db.beginTransaction()
defer: dbTx.dispose() defer: dbTx.dispose()
@ -125,25 +146,16 @@ proc processBlock*(chainDB: BaseChainDB, header: BlockHeader, body: BlockBody, v
return ValidationResult.Error return ValidationResult.Error
vmState.receipts[txIndex] = makeReceipt(vmState, fork) vmState.receipts[txIndex] = makeReceipt(vmState, fork)
let blockReward = blockRewards[fork]
var mainReward = blockReward
if header.ommersHash != EMPTY_UNCLE_HASH: if header.ommersHash != EMPTY_UNCLE_HASH:
let h = chainDB.persistUncles(body.uncles) let h = chainDB.persistUncles(body.uncles)
if h != header.ommersHash: if h != header.ommersHash:
debug "Uncle hash mismatch" debug "Uncle hash mismatch"
return ValidationResult.Error return ValidationResult.Error
for uncle in body.uncles:
var uncleReward = uncle.blockNumber.u256 + 8.u256 calculateReward(fork, header, body, vmState)
uncleReward -= header.blockNumber.u256
uncleReward = uncleReward * blockReward
uncleReward = uncleReward div 8.u256
vmState.mutateStateDB:
db.addBalance(uncle.coinbase, uncleReward)
mainReward += blockReward div 32.u256
# Reward beneficiary # Reward beneficiary
vmState.mutateStateDB: vmState.mutateStateDB:
db.addBalance(header.coinbase, mainReward)
if vmState.generateWitness: if vmState.generateWitness:
db.collectWitnessData() db.collectWitnessData()
db.persist(ClearCache in vmState.flags) db.persist(ClearCache in vmState.flags)

View File

@ -7,8 +7,8 @@
import import
macros, strformat, tables, sets, options, macros, strformat, tables, sets, options,
eth/common, eth/[common, keys, rlp], nimcrypto/keccak,
vm/interpreter/[vm_forks, gas_costs], vm/interpreter/[vm_forks, gas_costs], ./errors,
./constants, ./db/[db_chain, accounts_cache], ./constants, ./db/[db_chain, accounts_cache],
./utils, json, vm_types, vm/transaction_tracer, ./utils, json, vm_types, vm/transaction_tracer,
./config, ../stateless/[multi_keys, witness_from_tree, witness_types] ./config, ../stateless/[multi_keys, witness_from_tree, witness_types]
@ -61,6 +61,48 @@ proc setupTxContext*(vmState: BaseVMState, origin: EthAddress, gasPrice: GasInt,
vmState.chainDB.config.toFork(vmState.blockHeader.blockNumber) vmState.chainDB.config.toFork(vmState.blockHeader.blockNumber)
vmState.gasCosts = vmState.fork.forkToSchedule vmState.gasCosts = vmState.fork.forkToSchedule
proc consensusEnginePoA*(vmState: BaseVMState): bool =
let chainId = PublicNetwork(vmState.chainDB.config.chainId)
# PoA consensus engine have no reward for miner
result = chainId in {GoerliNet, RinkebyNet, KovanNet}
proc getSignature(bytes: openArray[byte], output: var Signature): bool =
let sig = Signature.fromRaw(bytes)
if sig.isOk:
output = sig[]
return true
return false
proc headerHashOriExtraData(vmState: BaseVMState): Hash256 =
var tmp = vmState.blockHeader
tmp.extraData.setLen(tmp.extraData.len-65)
result = keccak256.digest(rlp.encode(tmp))
proc getPubkey(sigRaw: openArray[byte], vmState: BaseVMState, output: var EthAddress): bool =
var sig: Signature
if sigRaw.getSignature(sig):
let headerHash = headerHashOriExtraData(vmState)
let pubkey = recover(sig, headerHash)
if pubkey.isOk:
output = pubkey[].toCanonicalAddress()
result = true
proc getMinerAddress*(vmState: BaseVMState): EthAddress =
if not vmState.consensusEnginePoA:
return vmState.blockHeader.coinbase
template data: untyped =
vmState.blockHeader.extraData
let len = data.len
doAssert(len >= 65)
var miner: EthAddress
if getPubkey(data.toOpenArray(len - 65, len-1), vmState, miner):
result = miner
else:
raise newException(ValidationError, "Could not derive miner address from header extradata")
proc updateBlockHeader*(vmState: BaseVMState, header: BlockHeader) = proc updateBlockHeader*(vmState: BaseVMState, header: BlockHeader) =
vmState.blockHeader = header vmState.blockHeader = header
vmState.touchedAccounts.clear() vmState.touchedAccounts.clear()