aboutsummaryrefslogtreecommitdiffstats
path: root/Godeps/_workspace/src/github.com/ethereum/serpent-go/serpent/examples/eth15/shadowchain.se
diff options
context:
space:
mode:
Diffstat (limited to 'Godeps/_workspace/src/github.com/ethereum/serpent-go/serpent/examples/eth15/shadowchain.se')
-rw-r--r--Godeps/_workspace/src/github.com/ethereum/serpent-go/serpent/examples/eth15/shadowchain.se166
1 files changed, 166 insertions, 0 deletions
diff --git a/Godeps/_workspace/src/github.com/ethereum/serpent-go/serpent/examples/eth15/shadowchain.se b/Godeps/_workspace/src/github.com/ethereum/serpent-go/serpent/examples/eth15/shadowchain.se
new file mode 100644
index 000000000..1e466a355
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/ethereum/serpent-go/serpent/examples/eth15/shadowchain.se
@@ -0,0 +1,166 @@
+# Exists in state:
+# (i) last committed block
+# (ii) chain of uncommitted blocks (linear only)
+# (iii) transactions, each tx with an associated block number
+#
+# Uncommitted block =
+# [ numtxs, numkvs, tx1 (N words), tx2 (N words) ..., [k1, v1], [k2, v2], [k3, v3] ... ]
+#
+# Block checking process
+#
+# Suppose last committed state is m
+# Last uncommitted state is n
+# Contested block is b
+#
+# 1. Temporarily apply all state transitions from
+# m to b
+# 2. Run code, get list of changes
+# 3. Check is list of changes matches deltas
+# * if yes, do nothing
+# * if no, set last uncommitted state to pre-b
+#
+# Storage variables:
+#
+# Last committed block: 0
+# Last uncommitted block: 1
+# Contract holding code: 2
+# Uncommitted map: 3
+# Transaction length (parameter): 4
+# Block b: 2^160 + b * 2^40:
+# + 1: submission blknum
+# + 2: submitter
+# + 3: data in uncommitted block format above
+# Last committed storage:
+# sha3(k): index k
+
+# Initialize: [0, c, txlength], set address of the code-holding contract and the transaction
+# length
+if not contract.storage[2]:
+ contract.storage[2] = msg.data[1]
+ contract.storage[4] = msg.data[2]
+ stop
+
+# Sequentially commit all uncommitted blocks that are more than 1000 mainchain-blocks old
+last_committed_block = contract.storage[0]
+last_uncommitted_block = contract.storage[1]
+lcb_storage_index = 2^160 + last_committed_block * 2^40
+while contract.storage[lcb_storage_index + 1] < block.number - 1000 and last_committed_block < last_uncommitted_block:
+ kvpairs = contract.storage[lcb_storage_index]
+ i = 0
+ while i < kvpairs:
+ k = contract.storage[lcb_storage_index + 3 + i * 2]
+ v = contract.storage[lcb_storage_index + 4 + i * 2]
+ contract.storage[sha3(k)] = v
+ i += 1
+ last_committed_block += 1
+ lcb_storage_index += 2^40
+contract.storage[0] = last_committed_block
+
+
+# Propose block: [ 0, block number, data in block format above ... ]
+if msg.data[0] == 0:
+ blknumber = msg.data[1]
+ # Block number must be correct
+ if blknumber != contract.storage[1]:
+ stop
+ # Deposit requirement
+ if msg.value < 10^19:
+ stop
+ # Store the proposal in storage as
+ # [ 0, main-chain block number, sender, block data...]
+ start_index = 2^160 + blknumber * 2^40
+ numkvs = (msg.datasize - 2) / 2
+ contract.storage[start_index + 1] = block.number
+ 1ontract.storage[start_index + 2] = msg.sender
+ i = 0
+ while i < msg.datasize - 2:
+ contract.storage[start_index + 3 + i] = msg.data[2 + i]
+ i += 1
+ contract.storage[1] = blknumber + 1
+
+# Challenge block: [ 1, b ]
+elif msg.data[0] == 1:
+ blknumber = msg.data[1]
+ txwidth = contract.storage[4]
+ last_uncommitted_block = contract.storage[1]
+ last_committed_block = contract.storage[0]
+ # Cannot challenge nonexistent or committed blocks
+ if blknumber <= last_uncommitted_block or blknumber > last_committed_block:
+ stop
+ # Create a contract to serve as a map that maintains keys and values
+ # temporarily
+ tempstore = create('map.se')
+ contract.storage[3] = tempstore
+ # Unquestioningly apply the state transitions from the last committed block
+ # up to b
+ b = last_committed_block
+ cur_storage_index = 2^160 + last_committed_block * 2^40
+ while b < blknumber:
+ numtxs = contract.storage[cur_storage_index + 3]
+ numkvs = contract.storage[cur_storage_index + 4]
+ kv0index = cur_storage_index + 5 + numtxs * txwidth
+ i = 0
+ while i < numkvs:
+ k = contract.storage[kv0index + i * 2]
+ v = contract.storage[kx0index + i * 2 + 1]
+ call(tempstore, [1, k, v], 3)
+ i += 1
+ b += 1
+ cur_storage_index += 2^40
+ # Run the actual code, and see what state transitions it outputs
+ # The way that the code is expected to work is to:
+ #
+ # (1) take as input the list of transactions (the contract should
+ # use msg.datasize to determine how many txs there are, and it should
+ # be aware of the value of txwidth)
+ # (2) call this contract with [2, k] to read current state data
+ # (3) call this contract with [3, k, v] to write current state data
+ # (4) return as output a list of all state transitions that it made
+ # in the form [kvcount, k1, v1, k2, v2 ... ]
+ #
+ # The reason for separating (2) from (3) is that sometimes the state
+ # transition may end up changing a given key many times, and we don't
+ # need to inefficiently store that in storage
+ numkvs = contract.storage[cur_storage_index + 3]
+ numtxs = contract.storage[cur_storage_index + 4]
+ # Populate input array
+ inpwidth = numtxs * txwidth
+ inp = array(inpwidth)
+ i = 0
+ while i < inpwidth:
+ inp[i] = contract.storage[cur_storage_index + 5 + i]
+ i += 1
+ out = call(contract.storage[2], inp, inpwidth, numkvs * 2 + 1)
+ # Check that the number of state transitions is the same
+ if out[0] != kvcount:
+ send(msg.sender, 10^19)
+ contract.storage[0] = last_committed_block
+ stop
+ kv0index = cur_storage_index + 5 + numtxs * txwidth
+ i = 0
+ while i < kvcount:
+ # Check that each individual state transition matches
+ k = contract.storage[kv0index + i * 2 + 1]
+ v = contract.storage[kv0index + i * 2 + 2]
+ if k != out[i * 2 + 1] or v != out[i * 2 + 2]:
+ send(msg.sender, 10^19)
+ contract.storage[0] = last_committed_block
+ stop
+ i += 1
+ # Suicide tempstore
+ call(tempstore, 2)
+
+
+# Read data [2, k]
+elif msg.data[0] == 2:
+ tempstore = contract.storage[3]
+ o = call(tempstore, [0, msg.data[1]], 2, 2)
+ if o[0]:
+ return(o[1])
+ else:
+ return contract.storage[sha3(msg.data[1])]
+
+# Write data [3, k, v]
+elif msg.data[0] == 3:
+ tempstore = contract.storage[3]
+ call(tempstore, [1, msg.data[1], msg.data[2]], 3, 2)