I am working on a project that’s very similar to enigma-secret-access-control and get the following output after running “discovery test”.
root@baremetal01:/home/timecapsule# discovery test
Smart Contracts:Compiling Secret Contract “timecapsule”…
Finished release [optimized] target(s) in 0.02s
Using network ‘development’.
Compiling your contracts…
Everything is up to date, there is nothing to compile.
secp256k1 unavailable, reverting to browser version
Deploying Secret Contract “timecapsule.wasm”…
Completed. Final Task Status is 2
Secret Contract “timecapsule.wasm” deployed at Enigma address: 0x3f130d8f687e147e47d26cb0aee43528511ede5d923da8bf0daedd72586f6540
Contract: Timecapsule
✓ should execute compute task to add secret #1 (185ms)
✓ should get the pending task
Completed. Final Task Status is 2
✓ should get the confirmed task (2028ms)
✓ should execute compute task to add secret #2 (161ms)
✓ should get the pending task
Completed. Final Task Status is 2
✓ should get the confirmed task (2027ms)
✓ should execute compute task to get secret (119ms)
✓ should get the pending task
1) should get the confirmed task
Events emitted during test:
---------------------------
---------------------------
2) should get the result and verify the computation is correct
> No events were emitted
8 passing (5m)
2 failing
-
Contract: Timecapsule
should get the confirmed task:
Error: Timeout of 300000ms exceeded. For async tests and hooks, ensure “done()” is called; if returning a Promise, ensure it resolves. (/home/timecapsule/test/test_timecapsule.js)
at listOnTimeout (internal/timers.js:535:17)
at processTimers (internal/timers.js:479:7) -
Contract: Timecapsule
should get the result and verify the computation is correct:AssertionError: expected ‘FAILED’ to equal ‘SUCCESS’
- expected - actual
-FAILED
+SUCCESSat Context.it (test/test_timecapsule.js:162:31)
at processTicksAndRejections (internal/process/task_queues.js:86:5)
Below is the output from my “discovery start” process for the task that’s failing:
p2p_1 | [Mon Jan 20 2020 01:32:31 GMT+0000 (Coordinated Universal Time)] DEBUG [VERIFY_NEW_TASK] successful verification of task e3373ef16992060636c7888820dc9fab28338cf8b824772c1bbb6ab17c77b868
p2p_1 | [Mon Jan 20 2020 01:32:31 GMT+0000 (Coordinated Universal Time)] DEBUG [onVerifyTask] saved to db task e3373ef16992060636c7888820dc9fab28338cf8b824772c1bbb6ab17c77b868
contract_1 | eth_getBlockByNumber
contract_1 | eth_blockNumber
km_1 | [? ] Blocks @ previous: 159, current: 165, next: 169 [? ]
km_1 | [? ] Epoch still active [? ]
contract_1 | eth_getBlockByNumber
contract_1 | eth_getBlockByNumber
contract_1 | eth_getBlockByNumber
contract_1 | eth_getBlockByNumber
contract_1 | eth_getBlockByNumber
contract_1 | eth_call
core_1 | Error in execution of smart contract function: Error in execution of WASM code: unreachable
core_1 | 01:32:33 [INFO] compute_task() => Ok(FailedTask { result: FailedTask { output: “b8fc4394613db48efaa347328b960b72420d1c3d81296c0c3ed1f54c51782d075b4f24b432d06df5dca2dcad9c12a80297888da010083cf041e9f37f916a8970e5a36b6e66f5c9d2”, used_gas: 93275, signature: “ff5929c39e6bb3d97108800b6c3c0129ada7dcc8a454ef1417557477ee054fbe18bc13c6ea7be8a7a6f4cdc6817184e37f67234ff9a02122eda69ababf84450f1c” } })
p2p_1 | [Mon Jan 20 2020 01:32:33 GMT+0000 (Coordinated Universal Time)] DEBUG received failed result
p2p_1 | [Mon Jan 20 2020 01:32:33 GMT+0000 (Coordinated Universal Time)] INFO [TASK_FINISHED] status = [FAILED] id: e3373ef16992060636c7888820dc9fab28338cf8b824772c1bbb6ab17c77b868
p2p_1 | [Mon Jan 20 2020 01:32:33 GMT+0000 (Coordinated Universal Time)] DEBUG published [/taskresults/0.1]
contract_1 | eth_sendTransaction
contract_1 |
contract_1 | Transaction: 0xde67c279652a6a8263e7fb6e34c7e99ac51e7df377b0fbb18d3ae01e2c8e99ee
contract_1 | Gas usage: 233890
contract_1 | Block Number: 166
contract_1 | Block Time: Mon Jan 20 2020 01:32:33 GMT+0000 (Coordinated Universal Time)
contract_1 |
contract_1 | eth_getTransactionReceipt
contract_1 | eth_getBlockByNumber
contract_1 | eth_blockNumber
km_1 | [? ] Blocks @ previous: 159, current: 166, next: 169 [? ]
km_1 | [? ] Epoch still active [? ]
Below is the test script:
root@baremetal01:/home/timecapsule/test# cat test_timecapsule.js
const fs = require(‘fs’);
const path = require(‘path’);
const dotenv = require(‘dotenv’);
const TimecapsuleContract = artifacts.require(“Timecapsule”);
const { Enigma, utils, eeConstants } = require(‘enigma-js/node’);
var EnigmaContract;
if (typeof process.env.SGX_MODE === ‘undefined’ || (process.env.SGX_MODE != ‘SW’ && process.env.SGX_MODE != ‘HW’)) {
console.log(Error reading ".env" file, aborting....
);
process.exit();
} else if (process.env.SGX_MODE == ‘SW’) {
EnigmaContract = require(‘…/build/enigma_contracts/EnigmaSimulation.json’);
} else {
EnigmaContract = require(‘…/build/enigma_contracts/Enigma.json’);
}
const EnigmaTokenContract = require(‘…/build/enigma_contracts/EnigmaToken.json’);
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
const splitMessages = decryptedOutput => {
const decodedParameters = web3.eth.abi.decodeParameters(
[
{
type: ‘string’,
name: ‘concatenatedMessages’,
},
],
decryptedOutput
)
const concatenatedMessages = decodedParameters.concatenatedMessages
// Return empty array of messages if decrypted output string is empty.
if (concatenatedMessages === ‘’) {
return
}
// Otherwise return messages.
const separator = ‘|’
return decodedParameters.concatenatedMessages.split(separator)
}
let enigma = null;
contract(“Timecapsule”, accounts => {
let owner1 = accounts[0];
let task;
before(function() {
enigma = new Enigma(
web3,
EnigmaContract.networks['4447'].address,
EnigmaTokenContract.networks['4447'].address,
'http://localhost:3333', {
gas: 4712388,
gasPrice: 100000000000,
from: accounts[0],
},
);
enigma.admin();
enigma.setTaskKeyPair('cupcake');
contractAddr = fs.readFileSync('test/timecapsule.txt', 'utf-8');
})
it('should execute compute task to add secret #1', async() => {
let taskFn = 'add_secret(address,string,int64)';
let taskArgs = [
[owner1, 'address'],
["Hello world 1", 'string'],
[1579378831, 'int64'],
];
let taskGasLimit = 500000;
let taskGasPx = utils.toGrains(1);
task = await new Promise((resolve, reject) => {
enigma.computeTask(taskFn, taskArgs, taskGasLimit, taskGasPx, accounts[0], contractAddr)
.on(eeConstants.SEND_TASK_INPUT_RESULT, (result) => resolve(result))
.on(eeConstants.ERROR, (error) => reject(error))
});
});
it('should get the pending task', async () => {
task = await enigma.getTaskRecordStatus(task);
expect(task.ethStatus).to.equal(1);
});
it('should get the confirmed task', async () => {
do {
await sleep(1000);
task = await enigma.getTaskRecordStatus(task);
process.stdout.write('Waiting. Current Task Status is '+task.ethStatus+'\r');
} while (task.ethStatus !== 2);
expect(task.ethStatus).to.equal(2);
process.stdout.write('Completed. Final Task Status is '+task.ethStatus+'\n');
}, 10000);
it('should execute compute task to add secret #2', async () => {
let taskFn = 'add_secret(address,string,int64)';
let taskArgs = [
[owner1, 'address'],
["Hello world 2", 'string'],
[1579378831, 'int64'],
];
let taskGasLimit = 500000;
let taskGasPx = utils.toGrains(1);
task = await new Promise((resolve, reject) => {
enigma.computeTask(taskFn, taskArgs, taskGasLimit, taskGasPx, accounts[0], contractAddr)
.on(eeConstants.SEND_TASK_INPUT_RESULT, (result) => resolve(result))
.on(eeConstants.ERROR, (error) => reject(error))
});
});
it('should get the pending task', async () => {
task = await enigma.getTaskRecordStatus(task);
expect(task.ethStatus).to.equal(1);
});
it('should get the confirmed task', async () => {
do {
await sleep(1000);
task = await enigma.getTaskRecordStatus(task);
process.stdout.write('Waiting. Current Task Status is '+task.ethStatus+'\r');
} while (task.ethStatus !== 2);
expect(task.ethStatus).to.equal(2);
process.stdout.write('Completed. Final Task Status is '+task.ethStatus+'\n');
}, 10000);
it('should execute compute task to get secret', async () => {
let taskFn = 'reveal_expired_secrets(address)';
let taskArgs = [
[owner1, 'address'],
];
let taskGasLimit = 500000;
let taskGasPx = utils.toGrains(1);
task = await new Promise((resolve, reject) => {
enigma.computeTask(taskFn, taskArgs, taskGasLimit, taskGasPx, accounts[0], contractAddr)
.on(eeConstants.SEND_TASK_INPUT_RESULT, (result) => resolve(result))
.on(eeConstants.ERROR, (error) => reject(error))
});
});
it('should get the pending task', async () => {
task = await enigma.getTaskRecordStatus(task);
expect(task.ethStatus).to.equal(1);
});
it('should get the confirmed task', async () => {
do {
await sleep(1000);
task = await enigma.getTaskRecordStatus(task);
process.stdout.write('Waiting. Current Task Status is '+task.ethStatus+'\r');
} while (task.ethStatus !== 2);
expect(task.ethStatus).to.equal(2);
process.stdout.write('Completed. Final Task Status is '+task.ethStatus+'\n');
}, 10000);
it('should get the result and verify the computation is correct', async () => {
task = await new Promise((resolve, reject) => {
enigma.getTaskResult(task)
.on(eeConstants.GET_TASK_RESULT_RESULT, (result) => resolve(result))
.on(eeConstants.ERROR, (error) => reject(error))
});
expect(task.engStatus).to.equal('SUCCESS');
task = await enigma.decryptTaskResult(task);
Below is the secret contract:
root@baremetal01:/home/timecapsule/secret_contracts/timecapsule/src# cat lib.rs
// Built-In Attributes
#![no_std]
// Imports
extern crate eng_wasm;
extern crate eng_wasm_derive;
extern crate serde;
extern crate chrono;
use eng_wasm::*;
use eng_wasm_derive::pub_interface;
use serde::{Serialize, Deserialize};
// Encrypted state keys
static OWNER: &str = “owner”;
static SECRETS: &str = “secrets”;
// Structs
#[derive(Serialize, Deserialize)]
pub struct Secret {
secret: String,
timestamp: i64,
}
// Public struct Contract which will consist of private and public-facing secret contract functions
pub struct Contract;
impl Contract {
fn get_secrets() → Vec {
read_state!(SECRETS).unwrap_or_default()
}
}
#[pub_interface]
pub trait ContractInterface{
fn construct(owner: H160);
fn add_secret(sender: H160, secret: String, timestamp: i64);
fn reveal_expired_secrets(sender: H160) → String;
}
// Private functions accessible only by the secret contract
impl ContractInterface for Contract {
fn construct(owner: H160) {
write_state!(OWNER => owner);
}
#[no_mangle]
fn add_secret(sender: H160, secret: String, timestamp: i64) {
let owner: H160 = read_state!(OWNER).unwrap();
assert_eq!(sender, owner);
let mut _secrets = Self::get_secrets();
_secrets.push(Secret {
secret,
timestamp,
});
write_state!(SECRETS => _secrets);
}
#[no_mangle]
fn reveal_expired_secrets(sender: H160) -> String {
let owner: H160 = read_state!(OWNER).unwrap();
assert_eq!(sender, owner);
let now: i64 = chrono::offset::Utc::now().timestamp();
let mut revealed_secrets: String = String::new();
let separator = String::from("|");
let all_secrets = Self::get_secrets();
for one_secret in all_secrets {
if now > one_secret.timestamp {
revealed_secrets.push_str(&one_secret.secret);
revealed_secrets.push_str(&separator);
}
}
revealed_secrets.pop();
return revealed_secrets;
}
}
What am I doing wrong? I’ve been dealing with this for the past day and have been trial-n-erroring it by altering the secret contract’s reveal_expired_secrets function and the test script and have had no luck.