Skip to content

Instantly share code, notes, and snippets.

@amiller amiller/capability_example.py Secret
Last active Oct 6, 2017

Embed
What would you like to do?
ethereum examples
Serpent examples
clist_code="""
# A Capability List system
#
# Gronvetter introduction diagram
# Alice introduces Carol to Bob.
#
# Alice --[foo->]---> Bob
# //
# //
# Carol --\=-->
#
init:
# Initial state goes here!
code:
# Ignore a message while the contract is lcoked
if contract.storage[0] == 1:
stop()
# Create a new object
if msg.data[0] == 1:
parent = msg.sender
contract.storage[0] == 1 # Lock the contract before transferring control
child = create(msg.data[1], msg.data[2], msg.data[3], ...) # TODO: fix?
contract.storage[0] = 0 # unlock the contract
# Parenthood
contract.storage[[parent,child]] = 1
# Grant a capability by introduction
if msg.data[0] == 2:
# Alice is the sender
sender = msg.sender
# Bob is the object
object = msg.data[1]
# Carol is the receiver
receiver = msg.data[2]
# To grant a capability, the sender must hold a capability
# to both the object and to the receiver
if !(contract.storage[[sender,object]] and
contract.storage[[sender,receiver]]):
return(1)
# Grant access
contract.storage[[receiver,object]] = 1
# Check a capability
if msg.data[0] == 3:
# returns 1 if the capability is granted, 0 otherwise
return contract.storage[[msg.data[1],msg.data[2]]]
# Additional rule:
# A "top level" object with no
"""
check_example = """
# Check if the sender has capability to check this object
if !call(${clist}, [3, msg.sender, this]):
stop()
...
"""
import serpent
from pyethereum import transactions, blocks, processblock, utils
processblock.print_debug = 1
code = serpent.compile(contract_code)
key = utils.sha3('cow')
addr = utils.privtoaddr(key)
genesis = blocks.genesis({ addr: 10**18 })
tx1 = transactions.contract(0,10**12,10000,0,code).sign(key)
result, contract = processblock.apply_transaction(genesis,tx1)
contract_code = """
// Reentrant contract
command = msg.data[0]
if command == 1:
contract.storage[0] = 99
contractToCall = msg.data[1]
params = [2]
#msg(200, contractToCall, 0, params, 1)
if contract.storage[0] != 99:
suicide()
if command == 2: // option 2
contract.storage[0] = -1
"""
import serpent
from pyethereum import transactions, blocks, processblock, utils
processblock.print_debug = 1
code = serpent.compile(contract_code)
key = utils.sha3('cow')
addr = utils.privtoaddr(key)
genesis = blocks.genesis({ addr: 10**18 })
tx1 = transactions.contract(0,10**12,10000,0,code).sign(key)
result, contract = processblock.apply_transaction(genesis,tx1)
#print genesis.to_dict()
tx2 = transactions.Transaction(1,10**12,2000,contract,0,
serpent.encode_datalist([1,contract])).sign(key)
result, ans = processblock.apply_transaction(genesis,tx2)
print 'result:', serpent.decode_datalist(ans)
#print genesis.to_dict()
contract_code = """
// Locked contract
if contract.storage[100] == 1:
stop # Don't enter a contract that's locked
contract.storage[100] = 1 # Lock the contract
command = msg.data[0]
if command == 1:
contract.storage[0] = 99
contractToCall = msg.data[1]
params = [2]
msg(200, contractToCall, 0, params, 1)
if contract.storage[0] != 99:
suicide()
if command == 2: // option 2
contract.storage[0] = -1
contract.storage[100] = 0 # Unlock
return(0)
"""
import serpent
from pyethereum import transactions, blocks, processblock, utils
processblock.print_debug = 1
code = serpent.compile(contract_code)
key = utils.sha3('cow')
addr = utils.privtoaddr(key)
genesis = blocks.genesis({ addr: 10**18 })
tx1 = transactions.contract(0,10**12,10000,0,code).sign(key)
result, contract = processblock.apply_transaction(genesis,tx1)
#print genesis.to_dict()
tx2 = transactions.Transaction(1,10**12,10000,contract,0,
serpent.encode_datalist([1,contract])).sign(key)
result, ans = processblock.apply_transaction(genesis,tx2)
print 'result:', serpent.decode_datalist(ans)
#print genesis.to_dict()
namecoin_code = """
// Namecoin
if !contract.storage[msg.data[0]]: # Is the key not yet taken?
# Then take it!
contract.storage[msg.data[0]] = msg.data[1]
return(1)
else:
return(0) // Otherwise do nothing
"""
import serpent
from pyethereum import transactions, blocks, processblock, utils
processblock.print_debug = 1
code = serpent.compile(namecoin_code)
key = utils.sha3('cow')
addr = utils.privtoaddr(key)
genesis = blocks.genesis({ addr: 10**18 })
tx1 = transactions.contract(0,10**12,10000,0,code).sign(key)
result, contract = processblock.apply_transaction(genesis,tx1)
print genesis.to_dict()
tx2 = transactions.Transaction(1,10**12,10000,contract,0,
serpent.encode_datalist(['george',45])).sign(key)
result, ans = processblock.apply_transaction(genesis,tx2)
serpent.decode_datalist(ans)
print genesis.to_dict()
contract_code = """
//
// A message queue contract
init:
contract.storage[0] = 0 # Starts unlocked
contract.storage[1] = 3 # Queue head
contract.storage[2] = 3 # Queue tail
code:
command = msg.data[0]
if command == 1: # Append to queue
error = 0
tail = contract.storage[2]
# First element is a contract address
contract = msg.data[1]
# Second element is gas price
gasprice = msg.data[2]
# Third element is gas cost
gascost = msg.data[3]
# Fourth element is value
value = msg.data[4]
# Fifth element is argument data
argument = msg.data[5]
# Assign a fixed fee for whoever *executes* this transaction
fee = 200
# Check that the msg value is enough
if msg.value < gascost + value + fee:
return(1) # Insufficient value
# Push this message to the end of the queue
contract.storage[tail*5+0] = contract
contract.storage[tail*5+1] = gasprice
contract.storage[tail*5+2] = gascost
contract.storage[tail*5+3] = value
contract.storage[tail*5+4] = argument
contract.storage[2] += 1
return(0)
if command == 2: # Execute the front of queue
# CRITICAL SECTION - Shouldn't be reentrant
# Don't enter a contract that's locked
if contract.storage[0] == 1:
return(1)
# Lock the contract
contract.storage[0] = 1
head = contract.storage[1]
tail = contract.storage[2]
if head >= tail: # The queue is empty, nothing to execute
contract.storage[0] = 0
return(2)
contract = contract.storage[head*5+0]
gasprice = contract.storage[head*5+1]
gascost = contract.storage[head*5+2]
value = contract.storage[head*5+3]
argument = contract.storage[head*5+4]
# Check the gas price is low enough
if tx.gasprice > gasprice:
contract.storage[0] = 0
return(3) # Wrong gas price
# Check the gas is sufficient to finish the transaction
if tx.gas < gascost + 200 # (remainder)
contract.storage[0] = 0
return(4) # Insufficient gas
# Call the contract
msg(gascost, contract, value, argument)
# Return fee
send(msg.sender, fee + gascost)
# Clear the storage and advance the queue
contract.storage[tail] = 0
contract.storage[1] += 1
# Unlock the queue
contract.storage[0] = 0
# END CRITICAL SECTION
return(0)
"""
second_contract_code = """
code:
if msg.data[0] > 0:
contract.storage[0] = msg.data[0]
else:
return(contract.storage[0])
"""
import serpent
from pyethereum import transactions, blocks, processblock, utils
#processblock.print_debug = 1
key = utils.sha3('cow')
addr = utils.privtoaddr(key)
genesis = blocks.genesis({ addr: 10**18 })
code = serpent.compile(contract_code)
tx1 = transactions.contract(0,10**12,10000,0,code).sign(key)
result, contract = processblock.apply_transaction(genesis,tx1)
print 'contract1', contract
#print genesis.to_dict()
code = serpent.compile(second_contract_code)
tx1 = transactions.contract(1,10**12,10000,0,code).sign(key)
result, contract2 = processblock.apply_transaction(genesis,tx1)
print 'contract2', contract2
# Register a message in the message queue
tx2 = transactions.Transaction(2,10**12,10**5,contract,3000,
serpent.encode_datalist([1,contract2,10**12,300,200,80])).sign(key)
result, ans = processblock.apply_transaction(genesis,tx2)
print 'result:', serpent.decode_datalist(ans)
# Cause the message queue to pop
tx2 = transactions.Transaction(3,10**12,10**5,contract,3000,
serpent.encode_datalist([2])).sign(key)
result, ans = processblock.apply_transaction(genesis,tx2)
print 'result:', serpent.decode_datalist(ans)
#
tx2 = transactions.Transaction(4,10**12,10**5,contract2,3000,
serpent.encode_datalist([0])).sign(key)
result, ans = processblock.apply_transaction(genesis,tx2)
print 'Value after message is applied:', serpent.decode_datalist(ans)
#print genesis.to_dict()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.