Commit 85dbf8ea authored by George Hotz's avatar George Hotz

oracle update to new format / test it

parent 2e9f39fa
......@@ -14,10 +14,25 @@ contract MIPSMemory {
// TODO: replace with mapping(bytes32 => mapping(uint, bytes4))
// to only save the part we care about
mapping(bytes32 => bytes) public preimage;
struct Preimage {
uint length;
mapping(uint => uint64) data;
}
function AddPreimage(bytes calldata anything) public {
preimage[keccak256(anything)] = anything;
mapping(bytes32 => Preimage) public preimage;
function AddPreimage(bytes calldata anything, uint offset) public {
require(offset & 3 == 0, "offset must be 32-bit aligned");
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;
p.data[offset] = (1 << 32) |
(uint32(uint8(anything[offset+0])) << 24) |
(uint32(uint8(anything[offset+1])) << 16) |
(uint32(uint8(anything[offset+2])) << 8) |
(uint32(uint8(anything[offset+3])) << 0);
}
// one per owner (at a time)
......@@ -75,12 +90,6 @@ contract MIPSMemory {
return Lib_MerkleTrie.update(tb(addr>>2), tb(value), stateHash);
}
event DidStep(bytes32 stateHash);
function WriteMemoryWithReceipt(bytes32 stateHash, uint32 addr, uint32 value) public {
bytes32 newStateHash = WriteMemory(stateHash, addr, value);
emit DidStep(newStateHash);
}
function WriteBytes32(bytes32 stateHash, uint32 addr, bytes32 val) public returns (bytes32) {
for (uint32 i = 0; i < 32; i += 4) {
uint256 tv = uint256(val>>(224-(i*8)));
......@@ -89,6 +98,18 @@ contract MIPSMemory {
return stateHash;
}
// TODO: refactor writeMemory function to not need these
event DidStep(bytes32 stateHash);
function WriteMemoryWithReceipt(bytes32 stateHash, uint32 addr, uint32 value) public {
bytes32 newStateHash = WriteMemory(stateHash, addr, value);
emit DidStep(newStateHash);
}
function WriteBytes32WithReceipt(bytes32 stateHash, uint32 addr, bytes32 value) public {
bytes32 newStateHash = WriteBytes32(stateHash, addr, value);
emit DidStep(newStateHash);
}
// needed for preimage oracle
function ReadBytes32(bytes32 stateHash, uint32 addr) public view returns (bytes32) {
uint256 ret = 0;
......@@ -114,14 +135,9 @@ contract MIPSMemory {
return uint32(preimage[pihash].length);
}
uint offset = addr-0x31000004;
uint8 a0 = uint8(preimage[pihash][offset]);
uint8 a1 = uint8(preimage[pihash][offset+1]);
uint8 a2 = uint8(preimage[pihash][offset+2]);
uint8 a3 = uint8(preimage[pihash][offset+3]);
return (uint32(a0) << 24) |
(uint32(a1) << 16) |
(uint32(a2) << 8) |
(uint32(a3) << 0);
uint64 data = preimage[pihash].data[offset];
require(data > 0, "offset must be loaded in");
return uint32(data);
}
bool exists;
......
......@@ -103,4 +103,21 @@ function getTrieAtStep(blockNumberN, step) {
return JSON.parse(fs.readFileSync(fn))
}
module.exports = { deploy, deployed, getTrieNodesForCall, getBlockRlp, getTrieAtStep }
async function writeMemory(mm, root, addr, data, bytes32=false) {
if (bytes32) {
ret = await mm.WriteBytes32WithReceipt(root, addr, data)
} else {
ret = await mm.WriteMemoryWithReceipt(root, addr, data)
}
const receipt = await ret.wait()
for (l of receipt.logs) {
if (l.topics[0] == "0x86b89b5c9818dbbf520dd979a5f250d357508fe11b9511d4a43fd9bc6aa1be70") {
root = l.data
}
}
console.log("new hash", root)
return root
}
module.exports = { deploy, deployed, getTrieNodesForCall, getBlockRlp, getTrieAtStep, writeMemory }
const { expect } = require("chai");
async function write(mm, root, addr, data) {
ret = await mm.WriteMemoryWithReceipt(root, addr, data)
const receipt = await ret.wait()
for (l of receipt.logs) {
if (l.topics[0] == "0x86b89b5c9818dbbf520dd979a5f250d357508fe11b9511d4a43fd9bc6aa1be70") {
root = l.data
}
}
console.log("new hash", root)
return root
}
const { writeMemory } = require("../scripts/lib")
function randint(n) {
return Math.floor(Math.random() * n)
......@@ -25,8 +14,8 @@ describe("MIPSMemory contract", function () {
it("write from new should work", async function() {
let root = "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"
root = await write(mm, root, 0, 1)
root = await write(mm, root, 4, 2)
root = await writeMemory(mm, root, 0, 1)
root = await writeMemory(mm, root, 4, 2)
expect(await mm.ReadMemory(root, 0)).to.equal(1)
expect(await mm.ReadMemory(root, 4)).to.equal(2)
......@@ -35,9 +24,9 @@ describe("MIPSMemory contract", function () {
await mm.AddTrieNode(new Uint8Array([0x80]))
let root = "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"
root = await write(mm, root, 0, 1)
root = await write(mm, root, 4, 2)
root = await write(mm, root, 0x40, 3)
root = await writeMemory(mm, root, 0, 1)
root = await writeMemory(mm, root, 4, 2)
root = await writeMemory(mm, root, 0x40, 3)
expect(await mm.ReadMemory(root, 0)).to.equal(1)
expect(await mm.ReadMemory(root, 4)).to.equal(2)
......@@ -46,9 +35,9 @@ describe("MIPSMemory contract", function () {
it("write other three should work", async function() {
let root = "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"
root = await write(mm, root, 0x7fffd00c, 1)
root = await write(mm, root, 0x7fffd010, 2)
root = await write(mm, root, 0x7fffcffc, 3)
root = await writeMemory(mm, root, 0x7fffd00c, 1)
root = await writeMemory(mm, root, 0x7fffd010, 2)
root = await writeMemory(mm, root, 0x7fffcffc, 3)
expect(await mm.ReadMemory(root, 0x7fffd00c)).to.equal(1)
expect(await mm.ReadMemory(root, 0x7fffd010)).to.equal(2)
......@@ -56,9 +45,9 @@ describe("MIPSMemory contract", function () {
})
it("bug found fuzzing 1", async function() {
let root = "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"
root = await write(mm, root, 0, 0)
root = await write(mm, root, 0, 1)
root = await write(mm, root, 0, 2)
root = await writeMemory(mm, root, 0, 0)
root = await writeMemory(mm, root, 0, 1)
root = await writeMemory(mm, root, 0, 2)
})
it("fuzzing should be okay", async function() {
let root = "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"
......@@ -72,14 +61,14 @@ describe("MIPSMemory contract", function () {
const key = randint(0x100)*4
const value = randint(0x100000000)
console.log("writing", key, value)
root = await write(mm, root, key, value)
root = await writeMemory(mm, root, key, value)
kv[key] = value
} else if (choice < 0.5) {
// write new high key
const key = randint(0x100)*4 + 0x10000000
const value = randint(0x100000000)
console.log("writing", key, value)
root = await write(mm, root, key, value)
root = await writeMemory(mm, root, key, value)
kv[key] = value
} else if (choice > 0.7) {
// read old key
......@@ -93,7 +82,7 @@ describe("MIPSMemory contract", function () {
const key = keys[idx]
const value = randint(0x100000000)
console.log("writing", key, value)
root = await write(mm, root, key, value)
root = await writeMemory(mm, root, key, value)
kv[key] = value
}
}
......
const { keccak256 } = require("@ethersproject/keccak256");
const { expect } = require("chai");
const { writeMemory } = require("../scripts/lib")
describe("MIPSMemory oracle", function () {
beforeEach(async function () {
const MIPSMemory = await ethers.getContractFactory("MIPSMemory")
mm = await MIPSMemory.deploy()
await mm.AddTrieNode(new Uint8Array([0x80]))
})
it("simple oracle", async function() {
// add in the preimage at offset 4
const data = [0x11,0x22,0x33,0x44,0xaa,0xbb,0xcc,0xdd]
const hash = keccak256(data)
await mm.AddPreimage(data, 4)
// write the oracle selection address
let root = "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"
root = await writeMemory(mm, root, 0x30001000, hash, true)
// length is 8
expect(await mm.ReadMemory(root, 0x31000000)).to.equal(8)
// offset 4 is 0xaabbccdd
expect(await mm.ReadMemory(root, 0x31000008)).to.equal(0xaabbccdd)
})
})
\ 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