initial make_receipt
This commit is contained in:
parent
f8d3d0e721
commit
ad1202f98a
|
@ -20,6 +20,7 @@ requires "nim >= 0.18.1",
|
|||
"eth_p2p",
|
||||
"eth_keyfile",
|
||||
"eth_keys",
|
||||
"eth_bloom",
|
||||
"https://github.com/status-im/nim-bncurve >= 1.0.1"
|
||||
|
||||
proc buildBinary(name: string, srcDir = ".", lang = "c") =
|
||||
|
|
|
@ -186,14 +186,19 @@ proc headerExists*(self: BaseChainDB; blockHash: Hash256): bool =
|
|||
## Returns True if the header with the given block hash is in our DB.
|
||||
self.db.contains(genericHashKey(blockHash).toOpenArray)
|
||||
|
||||
iterator getReceipts*(self: BaseChainDB; header: BlockHeader; receiptClass: typedesc): Receipt =
|
||||
proc persistReceipts*(self: BaseChainDB, receipts: openArray[Receipt]) =
|
||||
var trie = initHexaryTrie(self.db)
|
||||
for idx, rec in receipts:
|
||||
trie.put(rlp.encode(idx).toRange, rlp.encode(rec).toRange)
|
||||
|
||||
iterator getReceipts*(self: BaseChainDB; header: BlockHeader): Receipt =
|
||||
var receiptDb = initHexaryTrie(self.db, header.receiptRoot)
|
||||
var receiptIdx = 0
|
||||
while true:
|
||||
let receiptKey = rlp.encode(receiptIdx).toRange
|
||||
if receiptKey in receiptDb:
|
||||
let receiptData = receiptDb.get(receiptKey)
|
||||
yield rlp.decode(receiptData, receiptClass)
|
||||
yield rlp.decode(receiptData, Receipt)
|
||||
else:
|
||||
break
|
||||
inc receiptIdx
|
||||
|
|
|
@ -1,6 +1,35 @@
|
|||
import ../db/[db_chain, state_db], eth_common, chronicles, ../vm_state, ../vm_types, ../transaction, ranges,
|
||||
../vm/[computation, interpreter_dispatch, message], ../constants, stint, nimcrypto,
|
||||
../vm_state_transactions, sugar, ../utils, eth_trie/db, ../tracer, ./executor, json
|
||||
../vm_state_transactions, sugar, ../utils, eth_trie/db, ../tracer, ./executor, json,
|
||||
eth_bloom
|
||||
|
||||
type
|
||||
# these types need to eradicated
|
||||
# once eth_bloom and eth_common sync'ed
|
||||
Bloom = eth_common.BloomFilter
|
||||
LogsBloom = eth_bloom.BloomFilter
|
||||
|
||||
func logsBloom(logs: openArray[Log]): LogsBloom =
|
||||
for log in logs:
|
||||
result.incl log.address
|
||||
for topic in log.topics:
|
||||
result.incl topic
|
||||
|
||||
func createBloom*(receipts: openArray[Receipt]): Bloom =
|
||||
var bloom: LogsBloom
|
||||
for receipt in receipts:
|
||||
bloom.value = bloom.value or logsBloom(receipt.logs).value
|
||||
result = bloom.value.toByteArrayBE
|
||||
|
||||
proc makeReceipt(vmState: BaseVMState, stateRoot: Hash256, cumulativeGasUsed: GasInt): Receipt =
|
||||
# TODO: post byzantium fork use status instead of rootHash
|
||||
# currently, vmState.rootHash vs stateDb.rootHash can be different
|
||||
# need to wait #188 solved
|
||||
#result.stateRootOrStatus = hashOrStatus(vmState.blockHeader.stateRoot)
|
||||
result.stateRootOrStatus = hashOrStatus(stateRoot)
|
||||
result.cumulativeGasUsed = cumulativeGasUsed
|
||||
result.logs = vmState.getAndClearLogEntries()
|
||||
result.bloom = logsBloom(result.logs).value.toByteArrayBE
|
||||
|
||||
type
|
||||
Chain* = ref object of AbstractChainDB
|
||||
|
@ -30,7 +59,7 @@ method getSuccessorHeader*(c: Chain, h: BlockHeader, output: var BlockHeader): b
|
|||
method getBlockBody*(c: Chain, blockHash: KeccakHash): BlockBodyRef =
|
||||
result = nil
|
||||
|
||||
method persistBlocks*(c: Chain, headers: openarray[BlockHeader], bodies: openarray[BlockBody]) =
|
||||
method persistBlocks*(c: Chain, headers: openarray[BlockHeader], bodies: openarray[BlockBody]): bool =
|
||||
# Run the VM here
|
||||
assert(headers.len == bodies.len)
|
||||
|
||||
|
@ -45,6 +74,7 @@ method persistBlocks*(c: Chain, headers: openarray[BlockHeader], bodies: openarr
|
|||
assert(head.blockNumber == headers[i].blockNumber - 1)
|
||||
var stateDb = newAccountStateDB(c.db.db, head.stateRoot, c.db.pruneTrie)
|
||||
var gasReward = 0.u256
|
||||
var receipts = newSeq[Receipt](bodies[i].transactions.len)
|
||||
|
||||
assert(bodies[i].transactions.calcTxRoot == headers[i].txRoot)
|
||||
|
||||
|
@ -52,16 +82,21 @@ method persistBlocks*(c: Chain, headers: openarray[BlockHeader], bodies: openarr
|
|||
# assert(head.blockNumber == headers[i].blockNumber - 1)
|
||||
let vmState = newBaseVMState(head, c.db)
|
||||
assert(bodies[i].transactions.len != 0)
|
||||
var cumulativeGasUsed = GasInt(0)
|
||||
|
||||
if bodies[i].transactions.len != 0:
|
||||
trace "Has transactions", blockNumber = headers[i].blockNumber, blockHash = headers[i].blockHash
|
||||
|
||||
for t in bodies[i].transactions:
|
||||
for txIndex, tx in bodies[i].transactions:
|
||||
var sender: EthAddress
|
||||
if t.getSender(sender):
|
||||
gasReward += processTransaction(stateDb, t, sender, vmState)
|
||||
if tx.getSender(sender):
|
||||
let txFee = processTransaction(stateDb, tx, sender, vmState)
|
||||
gasReward += txFee
|
||||
let gasUsed = (txFee div tx.gasPrice.u256).truncate(GasInt)
|
||||
cumulativeGasUsed += gasUsed
|
||||
else:
|
||||
assert(false, "Could not get sender")
|
||||
receipts[txIndex] = makeReceipt(vmState, stateDb.rootHash, cumulativeGasUsed)
|
||||
|
||||
var mainReward = blockReward + gasReward
|
||||
#echo "mainReward = ", mainReward , " with blockReward = ", blockReward, " and gasReward = ", gasReward
|
||||
|
@ -87,10 +122,24 @@ method persistBlocks*(c: Chain, headers: openarray[BlockHeader], bodies: openarr
|
|||
|
||||
assert(headers[i].stateRoot == stateDb.rootHash)
|
||||
|
||||
let bloom = createBloom(receipts)
|
||||
if headers[i].bloom != bloom:
|
||||
debug "wrong bloom in block", blockNumber = headers[i].blockNumber
|
||||
assert(headers[i].bloom == bloom)
|
||||
|
||||
let receiptRoot = calcReceiptRoot(receipts)
|
||||
if headers[i].receiptRoot != receiptRoot:
|
||||
debug "wrong receipt in block", blockNumber = headers[i].blockNumber, receiptRoot, valid=headers[i].receiptRoot
|
||||
echo "CA:", receipts
|
||||
return false
|
||||
assert(headers[i].receiptRoot == receiptRoot)
|
||||
|
||||
discard c.db.persistHeaderToDb(headers[i])
|
||||
assert(c.db.getCanonicalHead().blockHash == headers[i].blockHash)
|
||||
|
||||
c.db.persistTransactions(headers[i].blockNumber, bodies[i].transactions)
|
||||
c.db.persistReceipts(receipts)
|
||||
|
||||
transaction.commit()
|
||||
result = true
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import ../db/[db_chain, state_db], ../transaction, eth_common,
|
||||
../vm_state, ../vm_types, ../vm_state_transactions, ranges,
|
||||
chronicles, ../vm/[computation, interpreter_dispatch, message]
|
||||
chronicles, ../vm/[computation, interpreter_dispatch, message],
|
||||
../rpc/hexstrings, byteutils, nimcrypto
|
||||
|
||||
proc processTransaction*(db: var AccountStateDB, t: Transaction, sender: EthAddress, vmState: BaseVMState): UInt256 =
|
||||
## Process the transaction, write the results to db.
|
||||
|
@ -64,5 +65,4 @@ proc processTransaction*(db: var AccountStateDB, t: Transaction, sender: EthAddr
|
|||
refund += t.value
|
||||
|
||||
db.addBalance(sender, refund)
|
||||
|
||||
return gasUsed.u256 * t.gasPrice.u256
|
||||
|
|
|
@ -26,7 +26,6 @@ proc newBaseComputation*(vmState: BaseVMState, blockNumber: UInt256, message: Me
|
|||
result.gasMeter.init(message.gas)
|
||||
result.children = @[]
|
||||
result.accountsToDelete = initTable[EthAddress, EthAddress]()
|
||||
result.logEntries = @[]
|
||||
result.code = newCodeStream(message.code)
|
||||
# result.rawOutput = "0x"
|
||||
result.gasCosts =
|
||||
|
@ -261,8 +260,8 @@ proc registerAccountForDeletion*(c: var BaseComputation, beneficiary: EthAddress
|
|||
"registered for deletion multiple times")
|
||||
c.accountsToDelete[c.msg.storageAddress] = beneficiary
|
||||
|
||||
proc addLogEntry*(c: var BaseComputation, account: EthAddress, topics: seq[UInt256], data: seq[byte]) =
|
||||
c.logEntries.add((account, topics, data))
|
||||
proc addLogEntry*(c: var BaseComputation, log: Log) {.inline.} =
|
||||
c.vmState.addLogEntry(log)
|
||||
|
||||
# many methods are basically TODO, but they still return valid values
|
||||
# in order to test some existing code
|
||||
|
@ -275,13 +274,6 @@ func getAccountsForDeletion*(c: BaseComputation): seq[EthAddress] =
|
|||
for account in c.accountsToDelete.keys:
|
||||
result.add(account)
|
||||
|
||||
proc getLogEntries*(c: BaseComputation): seq[(string, seq[UInt256], string)] =
|
||||
# TODO
|
||||
if c.isError:
|
||||
result = @[]
|
||||
else:
|
||||
result = @[]
|
||||
|
||||
proc getGasRefund*(c: BaseComputation): GasInt =
|
||||
if c.isError:
|
||||
result = 0
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
# Macros to facilitate opcode procs creation
|
||||
|
||||
import
|
||||
macros, strformat, stint,
|
||||
macros, strformat, stint, eth_common,
|
||||
../../computation, ../../stack, ../../code_stream,
|
||||
../../../constants, ../../../vm_types, ../../memory,
|
||||
../../../errors, ../../message, ../../interpreter/[gas_meter, opcode_values],
|
||||
|
@ -108,20 +108,18 @@ proc logImpl(c: var BaseComputation, opcode: Op, topicCount: int) =
|
|||
if memPos < 0 or len < 0:
|
||||
raise newException(OutOfBoundsRead, "Out of bounds memory access")
|
||||
|
||||
var topics = newSeqOfCap[UInt256](topicCount)
|
||||
var log: Log
|
||||
log.topics = newSeqOfCap[Topic](topicCount)
|
||||
for i in 0 ..< topicCount:
|
||||
topics.add(c.stack.popInt())
|
||||
log.topics.add(c.stack.popTopic())
|
||||
c.gasMeter.consumeGas(
|
||||
c.gasCosts[opcode].m_handler(c.memory.len, memPos, len),
|
||||
reason="Memory expansion, Log topic and data gas cost")
|
||||
|
||||
c.memory.extend(memPos, len)
|
||||
let logData = c.memory.read(memPos, len)
|
||||
addLogEntry(
|
||||
c,
|
||||
account = c.msg.storageAddress,
|
||||
topics = topics,
|
||||
data = logData)
|
||||
log.data = c.memory.read(memPos, len)
|
||||
log.address = c.msg.storageAddress
|
||||
c.addLogEntry(log)
|
||||
|
||||
template genLog*() =
|
||||
proc log0*(c: var BaseComputation) {.inline.} = logImpl(c, Log0, 0)
|
||||
|
|
|
@ -33,6 +33,7 @@ proc toStackElement(v: MDigest, elem: var StackElement) {.inline.} = elem.initFr
|
|||
proc fromStackElement(elem: StackElement, v: var UInt256) {.inline.} = v = elem
|
||||
proc fromStackElement(elem: StackElement, v: var EthAddress) {.inline.} = v[0 .. ^1] = elem.toByteArrayBE().toOpenArray(12, 31)
|
||||
proc fromStackElement(elem: StackElement, v: var Hash256) {.inline.} = v.data = elem.toByteArrayBE()
|
||||
proc fromStackElement(elem: StackElement, v: var Topic) {.inline.} = v = elem.toByteArrayBE()
|
||||
|
||||
proc toStackElement(v: openarray[byte], elem: var StackElement) {.inline.} =
|
||||
# TODO: This needs to go
|
||||
|
@ -87,6 +88,9 @@ proc popInt*(stack: var Stack, numItems: static[int]): auto {.inline.} =
|
|||
proc popAddress*(stack: var Stack): EthAddress {.inline.} =
|
||||
popAux(stack, result)
|
||||
|
||||
proc popTopic*(stack: var Stack): Topic {.inline.} =
|
||||
popAux(stack, result)
|
||||
|
||||
proc newStack*(): Stack =
|
||||
new(result)
|
||||
result.values = @[]
|
||||
|
|
|
@ -33,6 +33,7 @@ proc newBaseVMState*(header: BlockHeader, chainDB: BaseChainDB, tracerFlags: set
|
|||
result.chaindb = chainDB
|
||||
result.tracer.initTracer(tracerFlags)
|
||||
result.tracingEnabled = TracerFlags.EnableTracing in tracerFlags
|
||||
result.logEntries = @[]
|
||||
|
||||
method blockhash*(vmState: BaseVMState): Hash256 =
|
||||
vmState.blockHeader.hash
|
||||
|
@ -116,3 +117,14 @@ proc beginTransaction*(vmState: BaseVMState): DbTransaction =
|
|||
proc getTracingResult*(vmState: BaseVMState): JsonNode =
|
||||
assert(vmState.tracingEnabled)
|
||||
vmState.tracer.trace
|
||||
|
||||
proc addLogEntry*(vmState: BaseVMState, log: Log) =
|
||||
vmState.logEntries.add(log)
|
||||
|
||||
proc getAndClearLogEntries*(vmState: BaseVMState): seq[Log] =
|
||||
shallowCopy(result, vmState.logEntries)
|
||||
vmState.logEntries = @[]
|
||||
|
||||
proc clearLogs*(vmState: BaseVMState) =
|
||||
# call this when computation error
|
||||
vmState.logEntries.setLen(0)
|
||||
|
|
|
@ -115,6 +115,7 @@ proc applyCreateTransaction*(db: var AccountStateDB, t: Transaction, vmState: Ba
|
|||
debug "execComputation() error", isError = c.isError
|
||||
if c.tracingEnabled:
|
||||
c.traceError()
|
||||
vmState.clearLogs()
|
||||
return t.gasLimit.u256 * t.gasPrice.u256
|
||||
|
||||
method executeTransaction(vmState: BaseVMState, transaction: Transaction): (BaseComputation, BlockHeader) {.base.}=
|
||||
|
|
|
@ -15,13 +15,13 @@ import
|
|||
type
|
||||
BaseVMState* = ref object of RootObj
|
||||
prevHeaders* : seq[BlockHeader]
|
||||
# receipts*:
|
||||
chaindb* : BaseChainDB
|
||||
accessLogs* : AccessLogs
|
||||
blockHeader* : BlockHeader
|
||||
name* : string
|
||||
tracingEnabled*: bool
|
||||
tracer* : TransactionTracer
|
||||
logEntries* : seq[Log]
|
||||
|
||||
AccessLogs* = ref object
|
||||
reads*: Table[string, string]
|
||||
|
@ -53,7 +53,6 @@ type
|
|||
rawOutput*: seq[byte]
|
||||
returnData*: seq[byte]
|
||||
error*: Error
|
||||
logEntries*: seq[(EthAddress, seq[UInt256], seq[byte])]
|
||||
shouldEraseReturnData*: bool
|
||||
accountsToDelete*: Table[EthAddress, EthAddress]
|
||||
opcodes*: Table[Op, proc(computation: var BaseComputation){.nimcall.}]
|
||||
|
|
Loading…
Reference in New Issue