Work on text fitures and decompiling bytecode
This commit is contained in:
parent
925eb627a5
commit
0d31382e3d
|
@ -0,0 +1,7 @@
|
||||||
|
import vm/code_stream, opcode_values
|
||||||
|
|
||||||
|
var c = newCodeStream("\x60\x00\x60\x00\x60\x00\x60\x00\x67\x06\xf0\x5b\x59\xd3\xb2\x00\x00\x33\x60\xc8\x5a\x03\xf1")
|
||||||
|
|
||||||
|
let opcodes = c.decompile()
|
||||||
|
for op in opcodes:
|
||||||
|
echo op[0], " ", op[1], " ", op[2]
|
|
@ -0,0 +1 @@
|
||||||
|
-p:"../src"
|
|
@ -1,5 +1,5 @@
|
||||||
import
|
import
|
||||||
logging, constants, utils/header
|
logging, constants, utils / header, ttmath
|
||||||
|
|
||||||
type
|
type
|
||||||
CountableList*[T] = ref object
|
CountableList*[T] = ref object
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import
|
import
|
||||||
tables,
|
tables, ttmath,
|
||||||
logging, constants, errors, validation, utils / [hexadecimal]
|
logging, constants, errors, validation, utils / hexadecimal, vm / base, db / db_chain
|
||||||
|
|
||||||
type
|
type
|
||||||
BlockHeader* = ref object
|
BlockHeader* = ref object
|
||||||
|
@ -18,6 +18,9 @@ type
|
||||||
importBlock*: bool
|
importBlock*: bool
|
||||||
validateBlock*: bool
|
validateBlock*: bool
|
||||||
db*: BaseChainDB
|
db*: BaseChainDB
|
||||||
|
fundedAddress*: string
|
||||||
|
fundedAddressInitialBalance*: int
|
||||||
|
fundedAddressPrivateKey*: string
|
||||||
|
|
||||||
GenesisParams* = ref object
|
GenesisParams* = ref object
|
||||||
blockNumber*: Int256
|
blockNumber*: Int256
|
||||||
|
@ -25,11 +28,11 @@ type
|
||||||
gasLimit*: Int256
|
gasLimit*: Int256
|
||||||
parentHash*: string
|
parentHash*: string
|
||||||
coinbase*: string
|
coinbase*: string
|
||||||
nonce: string
|
nonce*: string
|
||||||
mixHash: string
|
mixHash*: string
|
||||||
extraData: string
|
extraData*: string
|
||||||
timestamp: int,
|
timestamp*: int
|
||||||
stateRoot: string
|
stateRoot*: string
|
||||||
|
|
||||||
FundedAddress* = ref object
|
FundedAddress* = ref object
|
||||||
balance*: Int256
|
balance*: Int256
|
||||||
|
@ -40,6 +43,8 @@ type
|
||||||
proc configureChain*(name: string, blockNumber: Int256, vm: VM, importBlock: bool = true, validateBlock: bool = true): Chain =
|
proc configureChain*(name: string, blockNumber: Int256, vm: VM, importBlock: bool = true, validateBlock: bool = true): Chain =
|
||||||
new(result)
|
new(result)
|
||||||
result.vmsByRange = @[(blockNumber: blockNumber, vm: vm)]
|
result.vmsByRange = @[(blockNumber: blockNumber, vm: vm)]
|
||||||
|
result.importBlock = importBlock
|
||||||
|
result.validateBlock = validateBlock
|
||||||
|
|
||||||
proc fromGenesis*(
|
proc fromGenesis*(
|
||||||
chain: Chain,
|
chain: Chain,
|
||||||
|
@ -48,13 +53,18 @@ proc fromGenesis*(
|
||||||
genesisState: Table[string, FundedAddress]): Chain =
|
genesisState: Table[string, FundedAddress]): Chain =
|
||||||
## Initialize the Chain from a genesis state
|
## Initialize the Chain from a genesis state
|
||||||
var stateDB = chaindb.getStateDB(BLANK_ROOT_HASH)
|
var stateDB = chaindb.getStateDB(BLANK_ROOT_HASH)
|
||||||
for account, accountData in genesisState:
|
# TODO
|
||||||
stateDB.setBalance(account, accountData.balance)
|
# for account, accountData in genesisState:
|
||||||
stateDB.setNonce(account, accountData.nonce)
|
# stateDB.setBalance(account, accountData.balance)
|
||||||
stateDB.setCode(account, accountData.code)
|
# stateDB.setNonce(account, accountData.nonce)
|
||||||
|
# stateDB.setCode(account, accountData.code)
|
||||||
|
|
||||||
new(result)
|
new(result)
|
||||||
result.db = chainDB
|
result.db = chainDB
|
||||||
result.header = BlockHeader()
|
result.header = BlockHeader()
|
||||||
result.logger = logging.getLogger("evm.chain.chain.Chain")
|
result.logger = logging.getLogger("evm.chain.chain.Chain")
|
||||||
chainDB.persistBlockToDB(result.getBlock())
|
result.importBlock = chain.importBlock
|
||||||
|
result.validateBlock = chain.validateBlock
|
||||||
|
result.vmsByRange = chain.vmsByRange
|
||||||
|
# TODO
|
||||||
|
# chainDB.persistBlockToDB(result.getBlock)
|
||||||
|
|
|
@ -191,7 +191,7 @@ let
|
||||||
GENESIS_COINBASE* = ZERO_ADDRESS
|
GENESIS_COINBASE* = ZERO_ADDRESS
|
||||||
GENESIS_NONCE* = "\x00\x00\x00\x00\x00\x00\x00B"
|
GENESIS_NONCE* = "\x00\x00\x00\x00\x00\x00\x00B"
|
||||||
GENESIS_MIX_HASH* = ZERO_HASH32
|
GENESIS_MIX_HASH* = ZERO_HASH32
|
||||||
GENESIS_EXTRA_DATA = ""
|
GENESIS_EXTRA_DATA* = ""
|
||||||
|
|
||||||
EMPTYSHA3 = "\xc5\xd2F\x01\x86\xf7#<\x92~}\xb2\xdc\xc7\x03\xc0\xe5\x00\xb6S\xca\x82';{\xfa\xd8\x04]\x85\xa4p"
|
EMPTYSHA3 = "\xc5\xd2F\x01\x86\xf7#<\x92~}\xb2\xdc\xc7\x03\xc0\xe5\x00\xb6S\xca\x82';{\xfa\xd8\x04]\x85\xa4p"
|
||||||
BLANK_ROOT_HASH* = "V\xe8\x1f\x17\x1b\xccU\xa6\xff\x83E\xe6\x92\xc0\xf8n[H\xe0\x1b\x99l\xad\xc0\x01b/\xb5\xe3c\xb4!"
|
BLANK_ROOT_HASH* = "V\xe8\x1f\x17\x1b\xccU\xa6\xff\x83E\xe6\x92\xc0\xf8n[H\xe0\x1b\x99l\xad\xc0\x01b/\xb5\xe3c\xb4!"
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
import tables, ttmath
|
||||||
|
|
||||||
|
type
|
||||||
|
MemoryDB* = ref object
|
||||||
|
kvStore*: Table[string, Int256]
|
||||||
|
|
||||||
|
proc newMemoryDB*(kvStore: Table[string, Int256]): MemoryDB =
|
||||||
|
MemoryDB(kvStore: kvStore)
|
||||||
|
|
||||||
|
proc newMemoryDB*: MemoryDB =
|
||||||
|
MemoryDB(kvStore: initTable[string, Int256]())
|
||||||
|
|
||||||
|
proc get*(db: MemoryDB, key: string): Int256 =
|
||||||
|
db.kvStore[key]
|
||||||
|
|
||||||
|
proc set*(db: var MemoryDB, key: string, value: Int256) =
|
||||||
|
db.kvStore[key] = value
|
||||||
|
|
||||||
|
proc exists*(db: MemoryDB, key: string): bool =
|
||||||
|
db.kvStore.hasKey(key)
|
||||||
|
|
||||||
|
proc delete*(db: var MemoryDB, key: string) =
|
||||||
|
db.kvStore.del(key)
|
|
@ -1,12 +1,15 @@
|
||||||
|
import strformat, tables, ttmath, state_db, backends / memory_backend
|
||||||
|
|
||||||
type
|
type
|
||||||
BaseChainDB* = ref object
|
BaseChainDB* = ref object
|
||||||
|
db*: MemoryDB
|
||||||
# TODO db*: JournalDB
|
# TODO db*: JournalDB
|
||||||
|
|
||||||
# proc makeBaseChainDB*(db: MemoryDB): BaseChainDB =
|
proc newBaseChainDB*(db: MemoryDB): BaseChainDB =
|
||||||
# result.db = JournalDB(db)
|
result.db = db
|
||||||
|
|
||||||
# proc exists*(self: BaseChainDB; key: cstring): bool =
|
proc exists*(self: BaseChainDB; key: string): bool =
|
||||||
# return self.db.exists(key)
|
return self.db.exists(key)
|
||||||
|
|
||||||
# proc getCanonicalHead*(self: BaseChainDB): BlockHeader =
|
# proc getCanonicalHead*(self: BaseChainDB): BlockHeader =
|
||||||
# if notself.exists(CANONICALHEADHASHDBKEY):
|
# if notself.exists(CANONICALHEADHASHDBKEY):
|
||||||
|
@ -145,7 +148,7 @@ type
|
||||||
# proc clear*(self: BaseChainDB): void =
|
# proc clear*(self: BaseChainDB): void =
|
||||||
# self.db.clear()
|
# self.db.clear()
|
||||||
|
|
||||||
# proc getStateDb*(self: BaseChainDB; stateRoot: cstring; readOnly: bool): AccountStateDB =
|
method getStateDb*(self: BaseChainDB; stateRoot: string; readOnly: bool = false): AccountStateDB =
|
||||||
# return AccountStateDB()
|
return newAccountStateDB(initTable[string, Int256]())
|
||||||
|
|
||||||
# var CANONICALHEADHASHDBKEY = cstring"v1:canonical_head_hash"
|
# var CANONICALHEADHASHDBKEY = cstring"v1:canonical_head_hash"
|
|
@ -1,5 +1,5 @@
|
||||||
import
|
import
|
||||||
../logging, ../constants, ../errors, ../transaction, ../computation, "../block", ../vm_state, ../vm_state_transactions, ../db/chain, ../utils/header
|
../logging, ../constants, ../errors, ../transaction, ../computation, "../block", ../vm_state, ../vm_state_transactions, ../db/db_chain, ../utils/header
|
||||||
|
|
||||||
type
|
type
|
||||||
VM* = ref object of RootObj
|
VM* = ref object of RootObj
|
||||||
|
|
|
@ -94,3 +94,19 @@ proc isValidOpcode*(c: var CodeStream, position: int): bool =
|
||||||
return false
|
return false
|
||||||
else:
|
else:
|
||||||
return true
|
return true
|
||||||
|
|
||||||
|
proc decompile*(original: CodeStream): seq[(int, Op, string)] =
|
||||||
|
# behave as https://etherscan.io/opcode-tool
|
||||||
|
# TODO
|
||||||
|
result = @[]
|
||||||
|
var c = newCodeStream(original.bytes)
|
||||||
|
while true:
|
||||||
|
var op = c.next
|
||||||
|
if op >= PUSH1 and op <= PUSH32:
|
||||||
|
let bytes = c.read(op.int - 95)
|
||||||
|
result.add((c.pc - 1, op, "0x" & bytes.mapIt($(it.BiggestInt.toHex(2))).join("")))
|
||||||
|
elif op != Op.Stop:
|
||||||
|
result.add((c.pc - 1, op, ""))
|
||||||
|
else:
|
||||||
|
result.add((-1, Op.STOP, ""))
|
||||||
|
break
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import
|
import
|
||||||
strformat,
|
strformat,
|
||||||
constants, errors, vm_state, transaction, utils/header
|
constants, errors, ttmath, vm_state, transaction, utils/header
|
||||||
|
|
||||||
proc validateFrontierTransaction*(vmState: BaseVmState, transaction: BaseTransaction) =
|
proc validateFrontierTransaction*(vmState: BaseVmState, transaction: BaseTransaction) =
|
||||||
let gasCost = transaction.gas * transaction.gasPrice
|
let gasCost = transaction.gas * transaction.gasPrice
|
||||||
|
@ -9,7 +9,7 @@ proc validateFrontierTransaction*(vmState: BaseVmState, transaction: BaseTransac
|
||||||
# senderBalance = db.getBalance(transaction.sender)
|
# senderBalance = db.getBalance(transaction.sender)
|
||||||
senderBalance = gasCost # TODO
|
senderBalance = gasCost # TODO
|
||||||
if senderBalance < gasCost:
|
if senderBalance < gasCost:
|
||||||
raise newException(ValidationError, %"Sender account balance cannot afford txn gas: {transaction.sender}")
|
raise newException(ValidationError, &"Sender account balance cannot afford txn gas: {transaction.sender}")
|
||||||
|
|
||||||
let totalCost = transaction.value + gasCost
|
let totalCost = transaction.value + gasCost
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import
|
import
|
||||||
logging, constants, errors, vm_state, utils/header, db/chain
|
logging, constants, errors, vm_state, utils/header, db/db_chain
|
||||||
|
|
||||||
type
|
type
|
||||||
FrontierVMState* = object of BaseVMState
|
FrontierVMState* = object of BaseVMState
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import
|
import
|
||||||
logging, constants, errors, "block", vm / [base, stack], db / chain, utils / header,
|
logging, constants, errors, ttmath, "block", vm / [base, stack], db / db_chain, utils / header,
|
||||||
frontier_block, frontier_vm_state, frontier_validation
|
frontier_block, frontier_vm_state, frontier_validation
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import
|
import
|
||||||
strformat, tables,
|
strformat, tables,
|
||||||
logging, constants, ttmath, errors, transaction, db/chain, utils/state, utils/header
|
logging, constants, ttmath, errors, transaction, db/db_chain, utils/state, utils/header
|
||||||
|
|
||||||
type
|
type
|
||||||
BaseVMState* = ref object of RootObj
|
BaseVMState* = ref object of RootObj
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import
|
import
|
||||||
strformat, tables,
|
strformat, tables,
|
||||||
logging, constants, errors, computation, transaction, vm_state, "block", db/chain, utils/state, utils/header
|
logging, constants, errors, computation, transaction, vm_state, "block", db / db_chain, utils / [state, header]
|
||||||
|
|
||||||
method executeTransaction(vmState: var BaseVMState, transaction: BaseTransaction): (BaseComputation, Header) =
|
method executeTransaction(vmState: var BaseVMState, transaction: BaseTransaction): (BaseComputation, Header) =
|
||||||
# Execute the transaction in the vm
|
# Execute the transaction in the vm
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
import unittest, strformat, tables, constants, chain, ttmath, vm / forks / frontier / vm, utils / [header, address], db / db_chain, db / backends / memory_backend
|
||||||
|
|
||||||
|
proc chainWithoutBlockValidation: Chain =
|
||||||
|
result = configureChain("TestChain", GENESIS_BLOCK_NUMBER, newFrontierVM(Header(), newBaseChainDB(newMemoryDB())), false, false)
|
||||||
|
let privateKey = "0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8" # TODO privateKey(decodeHex("0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8"))
|
||||||
|
let fundedAddr = privateKey # privateKey.publicKey.toCanonicalAddress
|
||||||
|
let initialBalance = 100_000_000
|
||||||
|
let genesisParams = GenesisParams(
|
||||||
|
blockNumber: GENESIS_BLOCK_NUMBER,
|
||||||
|
difficulty: GENESIS_DIFFICULTY,
|
||||||
|
gasLimit: GENESIS_GAS_LIMIT,
|
||||||
|
parentHash: GENESIS_PARENT_HASH,
|
||||||
|
coinbase: GENESIS_COINBASE,
|
||||||
|
nonce: GENESIS_NONCE,
|
||||||
|
mixHash: GENESIS_MIX_HASH,
|
||||||
|
extraData: GENESIS_EXTRA_DATA,
|
||||||
|
timestamp: 1501851927,
|
||||||
|
stateRoot: "0x9d354f9b5ba851a35eced279ef377111387197581429cfcc7f744ef89a30b5d4") #.decodeHex)
|
||||||
|
let genesisState = {"fundedAddr": FundedAddress(balance: initialBalance.int256, nonce: 0, code: "")}.toTable()
|
||||||
|
result = fromGenesis(
|
||||||
|
result,
|
||||||
|
newBaseChainDB(newMemoryDB()),
|
||||||
|
genesisParams,
|
||||||
|
genesisState)
|
||||||
|
result.fundedAddress = fundedAddr
|
||||||
|
result.fundedAddressInitialBalance = initialBalance
|
||||||
|
result.fundedAddressPrivateKey = privateKey
|
||||||
|
|
Loading…
Reference in New Issue