diff --git a/contracts/MIPSMemory.sol b/contracts/MIPSMemory.sol index f922c50f6a7dae03b2d32bed1bb42465eed9bf17..790aae10465dc0e8e10a4bf6bdb8c9437ff64945 100644 --- a/contracts/MIPSMemory.sol +++ b/contracts/MIPSMemory.sol @@ -36,13 +36,19 @@ contract MIPSMemory { } // one per owner (at a time) - mapping(address => uint64[25]) public largePreimage; - // TODO: also track the offset into the largePreimage to know what to store - function AddLargePreimageInit() public { + struct LargePreimage { + uint offset; + } + mapping(address => LargePreimage) public largePreimage; + // sadly due to soldiity limitations this can't be in the LargePreimage struct + mapping(address => uint64[25]) public largePreimageState; + + function AddLargePreimageInit(uint offset) public { Lib_Keccak256.CTX memory c; Lib_Keccak256.keccak_init(c); - largePreimage[msg.sender] = c.A; + largePreimageState[msg.sender] = c.A; + largePreimage[msg.sender].offset = offset; } // TODO: input 136 bytes, as many times as you'd like @@ -50,18 +56,26 @@ contract MIPSMemory { function AddLargePreimageUpdate(uint64[17] calldata data) public { // sha3_process_block Lib_Keccak256.CTX memory c; - c.A = largePreimage[msg.sender]; + c.A = largePreimageState[msg.sender]; for (uint i = 0; i < 17; i++) { c.A[i] ^= data[i]; } Lib_Keccak256.sha3_permutation(c); - largePreimage[msg.sender] = c.A; + largePreimageState[msg.sender] = c.A; } // TODO: input <136 bytes and do the end of hash | 0x01 / | 0x80 - function AddLargePreimageFinal() public view returns (bytes32) { + function AddLargePreimageFinal(uint64[17] calldata data) public view returns (bytes32) { Lib_Keccak256.CTX memory c; - c.A = largePreimage[msg.sender]; + c.A = largePreimageState[msg.sender]; + + // TODO: check data is valid as the final block + // maybe even modify it + for (uint i = 0; i < 17; i++) { + c.A[i] ^= data[i]; + } + Lib_Keccak256.sha3_permutation(c); + // TODO: do this properly and save the hash // when this is updated, it won't be "view" return Lib_Keccak256.get_hash(c); diff --git a/test/libkeccak.js b/test/libkeccak.js index cfe0a119cd4866555152a1becd7ad9bcfbaba1c1..90ca9856956b47e11ba3ca61ff74e8c75a829c18 100644 --- a/test/libkeccak.js +++ b/test/libkeccak.js @@ -1,6 +1,9 @@ const { keccak256 } = require("@ethersproject/keccak256"); const { expect } = require("chai"); +const empty = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]; +const endEmpty = [0x1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,"0x8000000000000000"]; + describe("MIPSMemory contract", function () { it("Keccak should work", async function () { const [owner] = await ethers.getSigners(); @@ -9,20 +12,22 @@ describe("MIPSMemory contract", function () { const mm = await MIPSMemory.deploy(); console.log("deployed at", mm.address, "by", owner.address); - await mm.AddLargePreimageInit(); + await mm.AddLargePreimageInit(0); console.log("preimage initted"); + // empty + expect(await mm.AddLargePreimageFinal(endEmpty)).to.equal(keccak256(new Uint8Array(0))); + // block size is 136 - //const a = ["0x0100000000000000",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0x80]; - const a = [0x1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,"0x8000000000000000"]; - await mm.AddLargePreimageUpdate(a); + await mm.AddLargePreimageUpdate(empty); + + const hash = await mm.AddLargePreimageFinal(endEmpty); console.log("preimage updated"); /*var tst1 = await mm.largePreimage(owner.address, 0); console.log(tst);*/ - const hash = await mm.AddLargePreimageFinal(); - const realhash = keccak256(new Uint8Array(0)); + const realhash = keccak256(new Uint8Array(136)); console.log("comp hash is", hash); console.log("real hash is", realhash); expect(hash).to.equal(realhash);