-
-
Save amiller/cdc42df919a9b1dcf7df to your computer and use it in GitHub Desktop.
ethereum examples
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Serpent examples |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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