Created
June 19, 2023 16:30
-
-
Save amiller/2c7914959bd41537089256348ff290de to your computer and use it in GitHub Desktop.
Off-chain linear scan ORAM token
This file contains hidden or 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
Struct AddrBal = { address addr; uint balance }; | |
enum RequestType = { TRANSFER; DEPOSIT; WITHDRAW }; | |
Struct Request = { RequestType type, address from; address to; uint amt; bytes32 memo } | |
Struct Response = { uint seqNo, bool status, uint amt, string response }; | |
contract { | |
// Key for encryption | |
bytes32 key; | |
// Checkpoint public state | |
AddrBal[] checkpoint public; | |
uint checkpointSeq public; | |
// List of pending commands (public is only allowed to read the type, sender) | |
Request[] requests; | |
function getRequest(uint seqno) returns (RequestType type, from); | |
// Processed responses (will always be <= size of requests) | |
Response[] responses public; | |
////////////// Submitting requests | |
event RequestSubmitted(RequestType type, address from, uint seqno); | |
function submitDepositRequest() payable public { | |
requests.push(Request(DEPOSIT, msg.sender, address(0), “”); | |
Emit RequestSubmitted(DEPOSIT, msg.sender, requests.length); | |
} | |
function submitXferRequest(addr to, uint amount, bytes32 memo) { | |
requests.push(Request(TRANSFER, msg.sender, to, amount, memo); | |
emit RequestSubmitted(TRANSFER, msg.sender, requests.length); | |
} | |
function submitWdrawRequest(uint amt) { | |
requests.push(Request(WITHDRAW, msg.sender, address(0), “”); | |
emit RequestSubmitted(WITHDRAW, msg.sender, requests.length); | |
} | |
///////////////////////// Interface between on-chain and off-chain | |
function getCheckpoint() returns(bytes) view { | |
ciph = oasis.encrypt( checkpointSeq, checkpoint, tag=”checkpoint”) | |
return ciph; | |
} | |
event ResponseCommitted(Response resp); | |
function commitResponse(bytes ciph) public { | |
// This is automatically checking authentication | |
Response resp = oasis.decrypt(key, ciph, tag=Response); | |
require(resp.seqNo == responses.length + 1); // Processes strictly in order | |
responses.push(resp); | |
Request request = requests[resp.seqNo]; | |
If (request.type == DEPOSIT) { | |
} else if (request.type == TRANSFER) { | |
} else if (request.type == WITHDRAW) { | |
Address addr = request.from; | |
transfer(addr, resp.amt); | |
} | |
emit ResponseCommitted(resp); | |
} | |
function writeCheckpoint(bytes ciph) { | |
// Decryption is automatically checking a MAC, this is authenticated encryption | |
(newSeq, newCheckpoint) := oasis.decrypt(key, ciph, tag=Checkpoint) | |
require(newSeq >= checkpointSeq); | |
checkpointSeq = newSeq; | |
checkpoint = newCheckpoint; | |
} | |
///////////// Off-chain computation | |
function processNext(bytes ciph) returns(bytes newciph, bytes respciph) public view { | |
(oldSeq, checkpoint) = oasis.decrypt(key, ciph, tag=”checkpoint”) | |
seqNo = oldSeq+1; | |
Request req = requests[seqNo]; | |
Response r; | |
If (req.type == TRANSFER) { | |
bool balanceOk = True; | |
For (uint i = 0; i < checkpoint.length; i++) { | |
bool b = (checkpoint[i].addr == req.from); | |
balanceOk &= (!b or checkpoints[i].balance >= req.amt)); | |
checkpoints[i].balance -= (req.amt) * (b * balanceOk); | |
} | |
For (uint i = 0; i < checkpoint.length; i++) { | |
bool b = (checkpoint[i].addr == req.from to); | |
checkpoints[i].balance += (req.amt) * b * balanceOK; | |
} | |
r = Response(seqNo, balanceOk, 0, “xfer ok”); | |
} else if (req.type == DEPOSIT) { | |
For (uint i = 0; i < checkpoint.length; i++) { | |
bool b = (checkpoint[i].addr == req.from); | |
checkpoints[i].balance += (req.amt) * b | |
} | |
r = Response(seqNo, True, 0, “”); | |
} else if (req.type == WITHDRAW) { | |
bool balanceOk = True; | |
For (uint i = 0; i < checkpoint.length; i++) { | |
bool b = (checkpoint[i].addr == req.from); | |
balanceOk &= (!b or checkpoints[i].balance >= req.amt)); | |
checkpoints[i].balance -= (req.amt) * (b * balanceOk); | |
} | |
r = Response(seqNo, balanceOk, req.amt * balanceOk, “”); | |
} | |
newciph = oasis.encrypt(key, checkpointSeq+1, checkpoint, tag=”checkpoint”) | |
respciph = oasis.encrypt(key, checkpointSeq+1, resp) | |
return (newciph, respciph) | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment