Skip to content

Commit

Permalink
Bugfixes: namecoin works now!
Browse files Browse the repository at this point in the history
  • Loading branch information
vbuterin committed Apr 8, 2014
1 parent 1588f77 commit 477d75b
Showing 3 changed files with 130 additions and 82 deletions.
23 changes: 12 additions & 11 deletions pyethereum/blocks.py
Original file line number Diff line number Diff line change
@@ -64,7 +64,7 @@ def __init__(self, data=None):
def get_index(self,address,index):
if len(address) == 40: address = address.decode('hex')
acct = self.state.get(address) or ['','','','']
return decode_int(acct[index])
return acct[index]

# set_index(bin or hex, int, bin)
def set_index(self,address,index,value):
@@ -77,13 +77,13 @@ def set_index(self,address,index,value):
def delta_index(self,address,index,value):
if len(address) == 40: address = address.decode('hex')
acct = self.state.get(address) or ['','','','']
if decode_int(acct[index]) < value:
if decode_int(acct[index]) + value < 0:
return False
acct[index] = encode_int(decode_int(acct[index])+value)
self.state.update(address,acct)
return True

def coerce_to_enc(n):
def coerce_to_enc(self,n):
return encode_int(n) if isinstance(n,(int,long)) else n
def get_nonce(self,address):
return decode_int(self.get_index(address,NONCE_INDEX))
@@ -96,16 +96,18 @@ def set_balance(self,address,value):
def delta_balance(self,address,value):
return self.delta_index(address,BALANCE_INDEX,value)
def get_code(self,address):
return DB('statedb').get(self.get_index(address,CODE_INDEX))
codehash = self.get_index(address,CODE_INDEX)
return DB('statedb').get(codehash) if codehash else ''
def set_code(self,address,value):
DB('statedb').put(sha3(value),value)
self.set_index(address,CODE_INDEX,sha3(value))
def get_storage(self,address):
return Trie('statedb',self.get_index(address,STORAGE_INDEX))
def get_storage_data(self,address,index):
t = Trie('statedb',self.get_index(address,STORAGE_INDEX))
return decode_int(t.get(coerce_to_enc(index)))
return decode_int(self.get_storage(address).get(self.coerce_to_enc(index)))
def set_storage_data(self,address,index,val):
t = Trie('statedb',get_index(address,STORAGE_INDEX))
t.update(coerce_to_enc(index))
t = Trie('statedb',self.get_index(address,STORAGE_INDEX))
t.update(self.coerce_to_enc(index),encode_int(val))
self.set_index(address,STORAGE_INDEX,t.root)

# Revert computation
@@ -138,7 +140,7 @@ def to_dict(self):
t = Trie('statedb',state[s][STORAGE_INDEX])
o = [0] * ACCT_RLP_LENGTH
o[NONCE_INDEX] = decode_int(state[s][NONCE_INDEX])
o[BALANCE_INDEX] = decode_int(state[s][NONCE_INDEX])
o[BALANCE_INDEX] = decode_int(state[s][BALANCE_INDEX])
o[CODE_INDEX] = state[s][CODE_INDEX]
o[STORAGE_INDEX] = t.to_dict(True)
nstate[s.encode('hex')] = o
@@ -160,8 +162,7 @@ def to_dict(self):
def genesis(cls,initial_alloc):
block = cls()
for addr in initial_alloc:
addr2 = addr.decode('hex') if len(addr) == 40 else addr
block.state.update(addr2,['',encode_int(initial_alloc[addr]),'',''])
block.set_balance(addr,initial_alloc[addr])
return block

def hash(self):
164 changes: 99 additions & 65 deletions pyethereum/processblock.py
Original file line number Diff line number Diff line change
@@ -11,11 +11,11 @@
from utils import int_to_big_endian as encode_int
from utils import sha3, privtoaddr

statedb = DB('statedb')

def encoded_plus(a,b):
return encode_int(decode_int(a) + decode_int(b))

debug = 1

# params

GSTEP = 1
@@ -81,17 +81,29 @@ def __init__(self,**kwargs):

def apply_msg(block,tx,msg):
snapshot = block.snapshot()
code = statedb.get(block.get_code(msg.sender))
code = block.get_code(msg.to)
# Transfer value, instaquit if not enough
block.delta_balance(msg.to,msg.value)
o = block.delta_balance(msg.sender,-msg.value)
if not o:
return 0, msg.gas, []
compustate = Compustate(gas=msg.gas)
# Main loop
if debug:
print map(ord,code)
while 1:
if debug:
print {
"Storage": block.get_storage(msg.to).to_dict(),
"Stack": compustate.stack,
"Memory": compustate.memory,
"PC": compustate.pc,
"Gas": compustate.gas,
}
o = apply_op(block,tx,msg,code,compustate)
if o is not None:
if debug:
print 'done',o
if o == OUT_OF_GAS:
block.revert(snapshot)
return 0, 0, []
@@ -102,7 +114,7 @@ def create_contract(block,tx,msg):
snapshot = block.snapshot()
sender = msg.sender.decode('hex') if len(msg.sender) == 40 else msg.sender
nonce = encode_int(block.get_nonce(msg.sender))
recvaddr = sha3(rlp.encode([sender,nonce]))
recvaddr = sha3(rlp.encode([sender,nonce]))[12:]
code = msg.data
# Transfer value, instaquit if not enough
block.delta_balance(recvaddr,msg.value)
@@ -128,9 +140,9 @@ def get_op_data(code,index):
opcode = ord(code[index]) if index < len(code) else 0
if opcode < 96 or opcode == 255:
if opcode in opcodes: return opcodes[opcode]
else: return 'INVALID'
elif opcode < 128: return 'PUSH'+str(opcode-95)
else: return 'INVALID'
else: return 'INVALID',0,0
elif opcode < 128: return 'PUSH'+str(opcode-95),0,1
else: return 'INVALID',0,0

def calcfee(block,tx,msg,compustate,op):
stk, mem = compustate.stack, compustate.memory
@@ -156,121 +168,132 @@ def calcfee(block,tx,msg,compustate,op):
elif op == 'CREATE':
m_extend = max(0,stk[-2]+stk[-3]-len(mem))
return GCREATE + stk[-2] + m_extend * GMEMORY
elif op == 'RETURN':
m_extend = max(0,stk[-1] + stk[-2] - len(mem))
return GSTEP + m_extend * GMEMORY
elif op == 'STOP' or op == 'INVALID':
return GSTOP
else:
return GSTEP

# multi pop
def multipop(stack,pops):
o = []
for i in range(pops): o.push(stack.pop())
for i in range(pops): o.append(stack.pop())
return o

# Does not include paying opfee
def apply_op(block,tx,msg,code,compustate):
op, in_args, out_args = get_op_data(code,compustate.pc)
if debug:
print op, in_args, out_args
# empty stack error
if in_args > len(compustate.stack):
return []
stackargs = []
for i in range(in_args):
stackargs.push(stack.pop())
# out of gas error
fee = calcfee(block,tx,msg,compustate,op)
if fee > compustate.gas:
return OUT_OF_GAS
stackargs = []
for i in range(in_args):
stackargs.append(compustate.stack.pop())
# Apply operation
newgas = compustate.gas - fee
newpc = compustate.pc + 1
oldgas = compustate.gas
oldpc = compustate.pc
compustate.gas -= fee
compustate.pc += 1
stk = compustate.stack
mem = compustate.memory
if op == 'ADD':
stk.push((stackargs[0] + stackargs[1]) % 2**256)
if op == 'STOP':
return []
elif op == 'ADD':
stk.append((stackargs[0] + stackargs[1]) % 2**256)
elif op == 'SUB':
stk.push((stackargs[0] - stackargs[1]) % 2**256)
stk.append((stackargs[0] - stackargs[1]) % 2**256)
elif op == 'MUL':
stk.push((stackargs[0] * stackargs[1]) % 2**256)
stk.append((stackargs[0] * stackargs[1]) % 2**256)
elif op == 'DIV':
stk.push(stackargs[0] / stackargs[1])
stk.append(stackargs[0] / stackargs[1])
elif op == 'MOD':
stk.push(stackargs[0] % stackargs[1])
stk.append(stackargs[0] % stackargs[1])
elif op == 'SDIV':
if stackargs[0] >= 2**255: stackargs[0] -= 2**256
if stackargs[1] >= 2**255: stackargs[1] -= 2**256
stk.push((stackargs[0] / stackargs[1]) % 2**256)
stk.append((stackargs[0] / stackargs[1]) % 2**256)
elif op == 'SMOD':
if stackargs[0] >= 2**255: stackargs[0] -= 2**256
if stackargs[1] >= 2**255: stackargs[1] -= 2**256
stk.push((stackargs[0] % stackargs[1]) % 2**256)
stk.append((stackargs[0] % stackargs[1]) % 2**256)
elif op == 'EXP':
stk.push(pow(stackargs[0],stackargs[1],2**256))
stk.append(pow(stackargs[0],stackargs[1],2**256))
elif op == 'NEG':
stk.push(2**256 - stackargs[0])
stk.append(2**256 - stackargs[0])
elif op == 'LT':
stk.push(1 if stackargs[0] < stackargs[1] else 0)
stk.append(1 if stackargs[0] < stackargs[1] else 0)
elif op == 'GT':
stk.push(1 if stackargs[0] > stackargs[1] else 0)
stk.append(1 if stackargs[0] > stackargs[1] else 0)
elif op == 'EQ':
stk.push(1 if stackargs[0] == stackargs[1] else 0)
stk.append(1 if stackargs[0] == stackargs[1] else 0)
elif op == 'NOT':
stk.push(0 if stackargs[0] else 1)
stk.append(0 if stackargs[0] else 1)
elif op == 'AND':
stk.push(stackargs[0] & stackargs[1])
stk.append(stackargs[0] & stackargs[1])
elif op == 'OR':
stk.push(stackargs[0] | stackargs[1])
stk.append(stackargs[0] | stackargs[1])
elif op == 'XOR':
stk.push(stackargs[0] ^ stackargs[1])
stk.append(stackargs[0] ^ stackargs[1])
elif op == 'BYTE':
if stackargs[0] >= 32: stk.push(0)
else: stk.push((stackargs[1] / 256**stackargs[0]) % 256)
if stackargs[0] >= 32: stk.append(0)
else: stk.append((stackargs[1] / 256**stackargs[0]) % 256)
elif op == 'SHA3':
if len(mem) < stackargs[0] + stackargs[1]:
mem.extend([0] * (stackargs[0] + stackargs[1] - len(mem)))
data = ''.join(map(chr,mem[stackargs[0]:stackargs[0] + stackargs[1]]))
stk.push(decode(sha3(data),256))
stk.append(decode(sha3(data),256))
elif op == 'ADDRESS':
stk.push(msg.to)
stk.append(msg.to)
elif op == 'BALANCE':
stk.push(block.get_balance(msg.to))
stk.append(block.get_balance(msg.to))
elif op == 'ORIGIN':
stk.push(tx.sender)
stk.append(tx.sender)
elif op == 'CALLER':
stk.push(msg.sender)
stk.append(msg.sender)
elif op == 'CALLVALUE':
stk.push(msg.value)
elif op == 'CALLDATA':
if stackargs[-1] >= len(msg.data): stk.push(0)
stk.append(msg.value)
elif op == 'CALLDATALOAD':
if stackargs[0] >= len(msg.data): stk.append(0)
else:
dat = ''.join(map(chr,msg.data[stackargs[-1]:stackargs[-1]+32]))
stk.push(decode(dat+'\x00'*(32-len(dat)),256))
dat = msg.data[stackargs[0]:stackargs[0]+32]
stk.append(decode_int(dat+'\x00'*(32-len(dat))))
elif op == 'CALLDATASIZE':
stk.push(len(msg.data))
stk.append(len(msg.data))
elif op == 'GASPRICE':
stk.push(tx.gasprice)
stk.append(tx.gasprice)
elif op == 'PREVHASH':
stk.push(block.prevhash)
stk.append(block.prevhash)
elif op == 'COINBASE':
stk.push(block.coinbase)
stk.append(block.coinbase)
elif op == 'TIMESTAMP':
stk.push(block.timestamp)
stk.append(block.timestamp)
elif op == 'NUMBER':
stk.push(block.number)
stk.append(block.number)
elif op == 'DIFFICULTY':
stk.push(block.difficulty)
stk.append(block.difficulty)
elif op == 'GASLIMIT':
stk.push(block.gaslimit)
stk.append(block.gaslimit)
elif op == 'POP':
pass
elif op == 'DUP':
stk.push(stackargs[0])
stk.push(stackargs[0])
stk.append(stackargs[0])
stk.append(stackargs[0])
elif op == 'SWAP':
stk.push(stackargs[0])
stk.push(stackargs[1])
stk.append(stackargs[0])
stk.append(stackargs[1])
elif op == 'MLOAD':
if len(mem) < stackargs[0] + 32:
mem.extend([0] * (stackargs[0] + 32 - len(mem)))
data = ''.join(map(chr,mem[stackargs[0]:stackargs[0] + 32]))
stk.push(decode(data,256))
stk.append(decode(data,256))
elif op == 'MSTORE':
if len(mem) < stackargs[0] + 32:
mem.extend([0] * (stackargs[0] + 32 - len(mem)))
@@ -283,24 +306,24 @@ def apply_op(block,tx,msg,code,compustate):
mem.extend([0] * (stackargs[0] + 1 - len(mem)))
mem[stackargs[0]] = stackargs[1] % 256
elif op == 'SLOAD':
stk.push(block.get_storage_data(msg.to,stackargs[0]))
stk.append(block.get_storage_data(msg.to,stackargs[0]))
elif op == 'SSTORE':
block.set_storage_data(msg.to,stackargs[0],stackargs[1])
elif op == 'JUMP':
newpc = stackargs[0]
compustate.pc = stackargs[0]
elif op == 'JUMPI':
if stackargs[1]: newpc = stackargs[0]
if stackargs[1]: compustate.pc = stackargs[0]
elif op == 'PC':
stk.push(compustate.pc)
stk.append(compustate.pc)
elif op == 'MSIZE':
stk.push(len(mem))
stk.append(len(mem))
elif op == 'GAS':
stk.push(compustate.gas)
stk.append(oldgas)
elif op[:4] == 'PUSH':
pushnum = int(op[4:])
newpc = compustate.pc + 1 + pushnum
dat = code[compustate.pc + 1: compustate.pc + 1 + pushnum]
stk.push(decode(dat+'\x00'*(32-len(dat)),256))
compustate.pc = oldpc + 1 + pushnum
dat = code[oldpc + 1: oldpc + 1 + pushnum]
stk.append(decode_int(dat))
elif op == 'CREATE':
if len(mem) < stackargs[2] + stackargs[3]:
mem.extend([0] * (stackargs[2] + stackargs[3] - len(mem)))
@@ -313,8 +336,19 @@ def apply_op(block,tx,msg,code,compustate):
mem.extend([0] * (stackargs[3] + stackargs[4] - len(mem)))
if len(mem) < stackargs[5] + stackargs[6]:
mem.extend([0] * (stackargs[5] + stackargs[6] - len(mem)))
to = stackhash[0]
to = encode_int(stackhash[0])
to = (('\x00' * (32 - len(to))) + to)[12:]
value = stackhash[1]
gas = stackhash[2]
data = ''.join(map(chr,mem[stackhash[3]:stackhash[3]+stackhash[4]]))
apply_msg(block,tx,Message(msg.to,to,value,gas,data))
elif op == 'RETURN':
if len(mem) < stackargs[0] + stackargs[1]:
mem.extend([0] * (stackargs[0] + stackargs[1] - len(mem)))
return mem[stackargs[0]:stackargs[0] + stackargs[1]]
elif op == 'SUICIDE':
to = encode_int(stackhash[0])
to = (('\x00' * (32 - len(to))) + to)[12:]
block.delta_balance(to,block.get_balance(msg.to))
block.state.update(msg.to,'')
return []
Loading
Oops, something went wrong.

0 comments on commit 477d75b

Please sign in to comment.