diff --git a/packages/omgx/offchain-prototype/contracts/HelloTuring.sol b/packages/omgx/offchain-prototype/contracts/HelloTuring.sol index 63ad05377d01..56532b8fbc66 100644 --- a/packages/omgx/offchain-prototype/contracts/HelloTuring.sol +++ b/packages/omgx/offchain-prototype/contracts/HelloTuring.sol @@ -6,6 +6,7 @@ import "hardhat/console.sol"; interface Helper { function TuringCall(uint32 method_idx, bytes memory) view external returns (bytes memory); + function TuringTx(uint32 method_idx, bytes memory) external returns (bytes memory); } contract HelloTuring { @@ -47,7 +48,7 @@ contract HelloTuring { "Invalid Locale"); // Example uses "EN_US" etc locales[msg.sender] = locale; - bytes memory response = myHelper.TuringCall(0, abi.encode(locale)); + bytes memory response = myHelper.TuringTx(0, abi.encode(locale)); cachedGreetings[msg.sender] = abi.decode(response,(string)); } diff --git a/packages/omgx/offchain-prototype/contracts/TuringHelper.sol b/packages/omgx/offchain-prototype/contracts/TuringHelper.sol index 900810b6d33c..ac4b8eccad13 100644 --- a/packages/omgx/offchain-prototype/contracts/TuringHelper.sol +++ b/packages/omgx/offchain-prototype/contracts/TuringHelper.sol @@ -9,6 +9,8 @@ contract TuringHelper { TuringHelper Self; bytes[] methods; + event OffchainResponse(uint version, bytes responseData); + constructor (string memory _url) public { console.log("Deploying a helper contract with data source:", _url); data_URL = bytes(_url); @@ -173,6 +175,8 @@ contract TuringHelper { created. In the future some of this registration might be moved into l2geth, allowing for security measures such as TLS client certificates. A configurable timeout could also be added. + + This is a "view" function and may be used from eth_call. See below. */ function TuringCall(uint32 method_idx, bytes memory _payload) public view returns (bytes memory) { @@ -186,5 +190,25 @@ contract TuringHelper { bytes memory response = Self.GetResponse(method_idx, 1, _payload); return response; } + + /* Same as TuringCall() but logs the offchain response so that a future + verifier or fraud prover can replay the transaction and ensure that it + results in the same state root as during the initial execution. Note - + a future version might need to include a timestamp and/or more details + about the offchain interaction. + */ + function TuringTx(uint32 method_idx, bytes memory _payload) + public returns (bytes memory) { + require (method_idx < methods.length, "Method not registered"); + require (_payload.length > 0, "Payload length was 0"); + + /* Initiate the request. This can't be a local function call + because that would stay inside the EVM and not give l2geth + a place to intercept and re-write the call. + */ + bytes memory response = Self.GetResponse(method_idx, 1, _payload); + emit OffchainResponse(0x01, response); + return response; + } } diff --git a/packages/omgx/offchain-prototype/test/hello-test.ts b/packages/omgx/offchain-prototype/test/hello-test.ts index 1cb89a919b81..016ed0cad3ce 100644 --- a/packages/omgx/offchain-prototype/test/hello-test.ts +++ b/packages/omgx/offchain-prototype/test/hello-test.ts @@ -178,7 +178,12 @@ describe("HelloTest", function () { }) it("should allow the user to set a locale via eth_sendRawTransaction", async () => { let loc1 = await hello.SetMyLocale("FR", gasOverride) - expect(await loc1.wait()).to.be.ok + + const tr = await loc1.wait() + expect(tr).to.be.ok + console.log("FIXME - use proper API to check that receipt contains the expected OffchainRepsonse event") + const rawData = tr.events[1].data + expect(rawData.toString()).to.contain("426f6e6a6f7572206c65206d6f6e6465") // "Bonjour le monde" as hex }) it("should return the expected personal greeting", async () => { let msg1 = hello.PersonalGreeting(gasOverride) @@ -200,7 +205,8 @@ describe("HelloTest", function () { let product = hello.MultNumbers(5, 5); expect(await product).to.equal(25); }) - it("should correctly classfify the image of dog or cat", async () => { + // The "classifier" test is broken, relying on a local service which is not launched by the test harness. + it.skip("should correctly classfify the image of dog or cat", async () => { let dogClassification = hello.isCatOrDog("https://i.insider.com/5484d9d1eab8ea3017b17e29?width=1300&format=jpeg&auto=webp"); expect(await dogClassification).to.equal('dog');