Commit e422747c authored by George Hotz's avatar George Hotz

refactor for dynamic exec, still need to add oracle

parent b64dafff
......@@ -82,11 +82,11 @@ contract Challenge {
}
// helper function to determine what nodes we need
function CallWithTrieNodes(bytes calldata dat, bytes[] calldata nodes) public {
function CallWithTrieNodes(address target, bytes calldata dat, bytes[] calldata nodes) public {
for (uint i = 0; i < nodes.length; i++) {
mem.AddTrieNode(nodes[i]);
}
(bool success, bytes memory revertData) = address(this).call(dat);
(bool success, bytes memory revertData) = target.call(dat);
// TODO: better way to revert?
if (!success) {
uint256 revertDataLength = revertData.length;
......
......@@ -3,6 +3,7 @@ pragma solidity ^0.7.3;
import "./lib/Lib_Keccak256.sol";
import "./lib/Lib_MerkleTrie.sol";
import { Lib_BytesUtils } from "./lib/Lib_BytesUtils.sol";
contract MIPSMemory {
mapping(bytes32 => bytes) public trie;
......@@ -12,16 +13,39 @@ contract MIPSMemory {
}
struct Preimage {
uint length;
uint64 length;
mapping(uint => uint64) data;
}
mapping(bytes32 => Preimage) public preimage;
function GetPreimage(bytes32 outhash, uint offset) public view returns (uint, uint32) {
// TODO: can share code with getTrieNode
function MissingPreimageRevert(bytes32 outhash, uint offset) internal pure {
bytes memory node = Lib_BytesUtils.toNibbles(abi.encodePacked(outhash, offset));
for (uint i = 0; i < node.length; i++) {
if (node[i] < bytes1(uint8(10))) {
node[i] = bytes1(uint8(node[i]) + uint8(0x30));
} else {
node[i] = bytes1(uint8(node[i]) + uint8(0x61-10));
}
}
revert(string(node));
}
function GetPreimageLength(bytes32 outhash) public view returns (uint32) {
uint64 data = preimage[outhash].length;
if (data == 0) {
MissingPreimageRevert(outhash, 0);
}
return uint32(data);
}
function GetPreimage(bytes32 outhash, uint offset) public view returns (uint32) {
uint64 data = preimage[outhash].data[offset];
require(data > 0, "offset not loaded");
return (preimage[outhash].length, uint32(data));
if (data == 0) {
MissingPreimageRevert(outhash, offset);
}
return uint32(data);
}
function AddPreimage(bytes calldata anything, uint offset) public {
......@@ -29,8 +53,8 @@ contract MIPSMemory {
uint len = anything.length;
require(offset < len, "offset can't be longer than input");
Preimage storage p = preimage[keccak256(anything)];
require(p.length == 0 || p.length == len, "length is somehow wrong");
p.length = len;
require(p.length == 0 || uint32(p.length) == len, "length is somehow wrong");
p.length = (1 << 32) | uint64(uint32(len));
p.data[offset] = (1 << 32) |
((len <= (offset+0) ? 0 : uint32(uint8(anything[offset+0]))) << 24) |
((len <= (offset+1) ? 0 : uint32(uint8(anything[offset+1]))) << 16) |
......@@ -76,7 +100,7 @@ contract MIPSMemory {
largePreimage[msg.sender].len += 136;
}
function AddLargePreimageFinal(bytes calldata idat) public view returns (bytes32, uint, uint32) {
function AddLargePreimageFinal(bytes calldata idat) public view returns (bytes32, uint32, uint32) {
require(idat.length < 136, "final must be less than 136");
int offset = int(largePreimage[msg.sender].offset) - int(largePreimage[msg.sender].len);
require(offset < int(idat.length), "offset must be less than length");
......@@ -99,19 +123,20 @@ contract MIPSMemory {
Lib_Keccak256.sha3_permutation(c);
bytes32 outhash = Lib_Keccak256.get_hash(c);
return (outhash, len, data);
require(len < 0x10000000, "max length is 32-bit");
return (outhash, uint32(len), data);
}
function AddLargePreimageFinalSaved(bytes calldata idat) public {
bytes32 outhash;
uint len;
uint32 len;
uint32 data;
(outhash, len, data) = AddLargePreimageFinal(idat);
Preimage storage p = preimage[outhash];
require(p.length == 0 || p.length == len, "length is somehow wrong");
require(p.length == 0 || uint32(p.length) == len, "length is somehow wrong");
require(largePreimage[msg.sender].offset < len, "offset is somehow beyond length");
p.length = len;
p.length = (1 << 32) | uint64(len);
p.data[largePreimage[msg.sender].offset] = (1 << 32) | data;
}
......@@ -192,12 +217,9 @@ contract MIPSMemory {
return 0;
}
if (addr == 0x31000000) {
return uint32(preimage[pihash].length);
return uint32(GetPreimageLength(pihash));
}
uint offset = addr-0x31000004;
uint64 data = preimage[pihash].data[offset];
require(data > 0, "offset not loaded");
return uint32(data);
return GetPreimage(pihash, addr-0x31000004);
}
bool exists;
......
......@@ -29,7 +29,7 @@ async function main() {
let finalTrie = getTrieAtStep(blockNumberN, step+1)
let preimages = Object.assign({}, startTrie['preimages'], finalTrie['preimages']);
let nodes = await getTrieNodesForCall(c, cdat, preimages)
let nodes = await getTrieNodesForCall(c, c.address, cdat, preimages)
for (n of nodes) {
await mm.AddTrieNode(n)
}
......
......@@ -30,7 +30,7 @@ async function main() {
let args = [blockNumberN, blockNp1Rlp, assertionRoot, finalSystemState, finalTrie['step']]
let cdat = c.interface.encodeFunctionData("InitiateChallenge", args)
let nodes = await getTrieNodesForCall(c, cdat, preimages)
let nodes = await getTrieNodesForCall(c, c.address, dat, preimages)
// run "on chain"
for (n of nodes) {
......
......@@ -56,13 +56,13 @@ async function deployed() {
return [c,m,mm]
}
async function getTrieNodesForCall(c, cdat, preimages) {
async function getTrieNodesForCall(c, caddress, cdat, preimages) {
let nodes = []
while (1) {
try {
// TODO: make this eth call?
// needs something like InitiateChallengeWithTrieNodesj
let calldata = c.interface.encodeFunctionData("CallWithTrieNodes", [cdat, nodes])
let calldata = c.interface.encodeFunctionData("CallWithTrieNodes", [caddress, cdat, nodes])
ret = await ethers.provider.call({
to:c.address,
data:calldata
......
......@@ -32,7 +32,7 @@ describe("Challenge contract", function () {
let args = [blockNumberN, blockNp1Rlp, assertionRoot, finalSystemState, finalTrie['step']]
let cdat = c.interface.encodeFunctionData("InitiateChallenge", args)
let nodes = await getTrieNodesForCall(c, cdat, preimages)
let nodes = await getTrieNodesForCall(c, c.address, cdat, preimages)
// run "on chain"
for (n of nodes) {
......
......@@ -43,19 +43,21 @@ describe("MIPSMemory contract", function () {
let dathash = keccak256(dat)
const tst = await mm.AddLargePreimageFinal(dat)
expect(tst[0]).to.equal(dathash)
expect(tst[1].toNumber()).to.equal(11)
expect(tst[1]).to.equal(11)
expect(tst[2]).to.equal(0x6f20776f)
await mm.AddLargePreimageFinalSaved(dat)
await mm.AddPreimage(dat, 0)
let retl = await mm.GetPreimageLength(dathash)
let ret = await mm.GetPreimage(dathash, 4)
expect(ret[0].toNumber()).to.equal(11)
expect(ret[1]).to.equal(0x6f20776f)
expect(retl).to.equal(11)
expect(ret).to.equal(0x6f20776f)
// other type
retl = await mm.GetPreimageLength(dathash)
ret = await mm.GetPreimage(dathash, 0)
expect(ret[0].toNumber()).to.equal(11)
expect(ret[1]).to.equal(0x68656c6c)
expect(retl).to.equal(11)
expect(ret).to.equal(0x68656c6c)
})
});
\ No newline at end of file
const { expect } = require("chai")
const { deploy, getTrieNodesForCall } = require("../scripts/lib")
const trieAdd = {"root":"0x22ffce7c56d926c2d8d6337d8917fa0e1880e1869e189c15385ead63c6c45b93","preimages":{"0x044371dc86fb8c621bc84b69dce16de366de1126777250888b17416d0bd11279":"+FPGIIQ8EL//xiCENhD/8MYghDQRAAHGIIQ8CP//xiCENQj//cYghDQJAAPGIIQBCVAgxiCELUIAAcYghK4CAAjGIISuEQAExiCEA+AACICAgICAgA==","0x0fdfcc24b1b21d78ef2b7c6503eb9354677743685c2d00a14a8b502a177911b0":"+HGgL4Jb+u0gEWM4e9G4lO/GsyUEY/heVoGOAfiI04qPXfSgLCZprT7WBOLipiwJxxI0vy09rw9iPR+x0p/Xz1p3X5WgaNY/x30waJPsd6PWg76b094l8vUmmL6XB1XdUFy+xfWAgICAgICAgICAgICAgA==","0x11228d4f4a028a9088e6ec0aa6513e0d4731d9dc488e2af1957e46ba80624a69":"5oQAAAAAoARDcdyG+4xiG8hLadzhbeNm3hEmd3JQiIsXQW0L0RJ5","0x22ffce7c56d926c2d8d6337d8917fa0e1880e1869e189c15385ead63c6c45b93":"+FGgESKNT0oCipCI5uwKplE+DUcx2dxIjirxlX5GuoBiSmmAgKBv5gezlmGtxjQAs8Du76D93mAxExw5qWgAZjJQp1xmfICAgICAgICAgICAgIA=","0x2c2669ad3ed604e2e2a62c09c71234bf2d3daf0f623d1fb1d29fd7cf5a775f95":"+HHGIIQAAAAAxiCEAAAAAMYghAAAAADGIIQAAAAAxiCEAAAAAMYghAAAAADGIIQAAAAAxiCEAAAAAMYghAAAAADGIIQAAAAAxiCEAAAAAMYghAAAAADGIIQAAAAAxiCEAAAAAMYghAAAAADGIIRerQAAgA==","0x2f825bfaed201163387bd1b894efc6b3250463f85e56818e01f888d38a8f5df4":"+HHGIIQAAAAAxiCEAAAAAMYghAAAAADGIIQAAAAAxiCEAAAAAMYghAAAAADGIIQAAAAAxiCEAAAAAMYghAAAAADGIIQAAAAAxiCEAAAAAMYghAAAAADGIIQAAAAAxiCEAAAAAMYghAAAAADGIIQAAAAAgA==","0x68d63fc77d306893ec77a3d683be9bd3de25f2f52698be970755dd505cbec5f5":"6cYghAAAAADGIIQAAAAAxiCEAAAAAMYghAAAAACAgICAgICAgICAgICA","0x6fe607b39661adc63400b3c0eeefa0fdde6031131c39a96800663250a75c667c":"5YMQAACgD9/MJLGyHXjvK3xlA+uTVGd3Q2hcLQChSotQKhd5EbA="}};
const trieOracle = {"root":"0x26595bd4f73f14273d9f43f0c5253eef964f4581d5e293cded54d23f1cf3db5f","step":-1,"preimages":{"0x0fdfcc24b1b21d78ef2b7c6503eb9354677743685c2d00a14a8b502a177911b0":"+HGgL4Jb+u0gEWM4e9G4lO/GsyUEY/heVoGOAfiI04qPXfSgLCZprT7WBOLipiwJxxI0vy09rw9iPR+x0p/Xz1p3X5WgaNY/x30waJPsd6PWg76b094l8vUmmL6XB1XdUFy+xfWAgICAgICAgICAgICAgA==","0x16e7f9821e0a3a2fc92d337f6d269c4c0ddb4d5c10a04b49d368643c9818ec1d":"5YMQAACgoLKCLk7kk3rBB2CtW7YQizz670HG0TNCobpfs/1MJqs=","0x26595bd4f73f14273d9f43f0c5253eef964f4581d5e293cded54d23f1cf3db5f":"+FGgFuf5gh4KOi/JLTN/bSacTA3bTVwQoEtJ02hkPJgY7B2AgKBv5gezlmGtxjQAs8Du76D93mAxExw5qWgAZjJQp1xmfICAgICAgICAgICAgIA=","0x2c2669ad3ed604e2e2a62c09c71234bf2d3daf0f623d1fb1d29fd7cf5a775f95":"+HHGIIQAAAAAxiCEAAAAAMYghAAAAADGIIQAAAAAxiCEAAAAAMYghAAAAADGIIQAAAAAxiCEAAAAAMYghAAAAADGIIQAAAAAxiCEAAAAAMYghAAAAADGIIQAAAAAxiCEAAAAAMYghAAAAADGIIRerQAAgA==","0x2f825bfaed201163387bd1b894efc6b3250463f85e56818e01f888d38a8f5df4":"+HHGIIQAAAAAxiCEAAAAAMYghAAAAADGIIQAAAAAxiCEAAAAAMYghAAAAADGIIQAAAAAxiCEAAAAAMYghAAAAADGIIQAAAAAxiCEAAAAAMYghAAAAADGIIQAAAAAxiCEAAAAAMYghAAAAADGIIQAAAAAgA==","0x65c024ed3b68b3f86a44f6af5179e4ad055ac046ac2e954355d476c611947b16":"+HHGIISuCAAQxiCEPAhCpcYghDUI7F/GIISuCAAUxiCEPAgDu8YghDUI+iXGIISuCAAYxiCEPAhMsMYghDUIH63GIISuCAAcxiCEJAIPtMYghAAAAAzGIIQ8ETEAxiCEjigAAMYghCQMAAvGIIQBDGgjgA==","0x68d63fc77d306893ec77a3d683be9bd3de25f2f52698be970755dd505cbec5f5":"6cYghAAAAADGIIQAAAAAxiCEAAAAAMYghAAAAACAgICAgICAgICAgICA","0x6fe607b39661adc63400b3c0eeefa0fdde6031131c39a96800663250a75c667c":"5YMQAACgD9/MJLGyHXjvK3xlA+uTVGd3Q2hcLQChSotQKhd5EbA=","0x8cd6ed962850eebdb5bf360b496b5ab3425659a8ba3d115d5bb71055981a6bc2":"+F/GIIQtogABxiCEjigABMYghDwMaGXGIIQ1jGxsxiCEAQxoI8YghC2jAAHGIIQAQxAkxiCEPBC//8YghDYQ//DGIIQ0EQABxiCErgIACMYghK4RAATGIIQD4AAIgICAgA==","0xa0b2822e4ee4937ac10760ad5bb6108b3cfaef41c6d13342a1ba5fb3fd4c26ab":"+HGgt8fQkZe4faINYK98tz2Czvb1LZ/LaDPtw0E2aioQ4lagZcAk7Ttos/hqRPavUXnkrQVawEasLpVDVdR2xhGUexagjNbtlihQ7r21vzYLSWtas0JWWai6PRFdW7cQVZgaa8KAgICAgICAgICAgICAgA==","0xb7c7d09197b87da20d60af7cb73d82cef6f52d9fcb6833edc341366a2a10e256":"+HHGIIQ8EDAAxiCENhAQAMYghDwIRxfGIIQ1CDKFxiCErggAAMYghDwIqNfGIIQ1CDQexiCErggABMYghDwIXpfGIIQ1CC/GxiCErggACMYghDwIdyjGIIQ1CGOExiCErggADMYghDwI+ALGIIQ1CPjvgA=="}};
async function dynamicExecWithTrie(c, m, mm, root, preimages) {
let mdat = m.interface.encodeFunctionData("Step", [root])
let nodes = await getTrieNodesForCall(c, m.address, mdat, preimages)
for (n of nodes) {
await mm.AddTrieNode(n)
}
let ret = await m.Step(root)
const receipt = await ret.wait()
for (l of receipt.logs) {
if (l.topics[0] == "0x86b89b5c9818dbbf520dd979a5f250d357508fe11b9511d4a43fd9bc6aa1be70") {
root = l.data
}
}
return root
}
// really a copy of mips_test_execwtrie
describe("Exec with trie dynamic", function () {
beforeEach(async function () {
[c, m, mm] = await deploy()
})
it("add should work", async function () {
let root = trieAdd['root']
for (let i = 0; i < 12; i++) {
root = await dynamicExecWithTrie(c, m, mm, root, trieAdd['preimages'])
console.log(i, root)
}
})
/*it("oracle should work", async function () {
let root = trieOracle['root']
let pc = 0, out1, out2
while (pc != 0x5ead0000) {
root = await dynamicExecWithTrie(c, m, mm, root, trieOracle['preimages'])
pc = await mm.ReadMemory(root, 0xc0000080)
out1 = await mm.ReadMemory(root, 0xbffffff4)
out2 = await mm.ReadMemory(root, 0xbffffff8)
console.log(root, pc, out1, out2)
}
expect(out1).to.equal(1)
expect(out2).to.equal(1)
}).timeout(120000)*/
})
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment