diff --git a/snapshot/air-scripts/timestamp_getter.ts_getter.air b/snapshot/air-scripts/timestamp_getter.ts_getter.air deleted file mode 100644 index 235a09a..0000000 --- a/snapshot/air-scripts/timestamp_getter.ts_getter.air +++ /dev/null @@ -1,54 +0,0 @@ -(xor - (seq - (seq - (seq - (seq - (seq - (seq - (seq - (call %init_peer_id% ("getDataSrv" "-relay-") [] -relay-) - (call %init_peer_id% ("getDataSrv" "node") [] node) - ) - (call %init_peer_id% ("getDataSrv" "n_neighborhood") [] n_neighborhood) - ) - (call %init_peer_id% ("getDataSrv" "n_returnvalues") [] n_returnvalues) - ) - (call -relay- ("op" "noop") []) - ) - (xor - (seq - (seq - (seq - (call node ("op" "string_to_b58") [node] k) - (call node ("kad" "neighborhood") [k false] nodes) - ) - (fold nodes n - (par - (seq - (xor - (call n ("peer" "timestamp_ms") [] $res) - (null) - ) - (call node ("op" "noop") []) - ) - (next n) - ) - ) - ) - (call node ("op" "identity") [$res.$.[9]!]) - ) - (seq - (call -relay- ("op" "noop") []) - (call %init_peer_id% ("errorHandlingSrv" "error") [%last_error% 1]) - ) - ) - ) - (call -relay- ("op" "noop") []) - ) - (xor - (call %init_peer_id% ("callbackSrv" "response") [$res]) - (call %init_peer_id% ("errorHandlingSrv" "error") [%last_error% 2]) - ) - ) - (call %init_peer_id% ("errorHandlingSrv" "error") [%last_error% 3]) -) diff --git a/snapshot/aqua-scripts/timestamp_getter.aqua b/snapshot/aqua-scripts/timestamp_getter.aqua index 8cbd012..0458405 100644 --- a/snapshot/aqua-scripts/timestamp_getter.aqua +++ b/snapshot/aqua-scripts/timestamp_getter.aqua @@ -1,31 +1,24 @@ -import "builtin.aqua" --- import "@fluencelabs/aqua-lib/builtin.aqua" - --- const nsize = 20 - -data TSResult: - timestamp: u64 - peer_id: string +import "@fluencelabs/aqua-lib/builtin.aqua" service OpTS("op"): identity(s: u64) - array(a: string, b: u64) -> TSResult + array(a: string, b: u64) -> []string + +service ToU32("op"): + identity(x:u32) -> u32 + +func ts_getter(node: string, n_neighbors:u32) -> []u64: + res: *u64 + none_bool: *bool + nsize: *u32 + nsize <- ToU32.identity(n_neighbors) --- func ts_getter(node: string, n_neighborhood: u32, n_returnvalues: u32) -> []u64: -- ]TSResult: -func ts_getter(node: string) -> []u64: -- ]TSResult: - res: *u64 --TResult - on node: k <- Op.string_to_b58(node) - -- nodes <- Kademlia.neighborhood(k, false, 20) - nodes <- Kademlia.neighborhood(k, false) + nodes <- Kademlia.neighborhood(k, none_bool, nsize) for n <- nodes par: on n: try: res <- Peer.timestamp_ms() - -- res <- OpTS.array(n, Peer.timestamp_ms()) - - -- OpTs.identity(res!Op.array_length(nodes)) - -- OpTS.identity(res!n_returnvalues) OpTS.identity(res!9) <- res \ No newline at end of file diff --git a/snapshot/aqua-scripts/timestamp_getter_extended.aqua b/snapshot/aqua-scripts/timestamp_getter_extended.aqua new file mode 100644 index 0000000..b289fea --- /dev/null +++ b/snapshot/aqua-scripts/timestamp_getter_extended.aqua @@ -0,0 +1,30 @@ +import "@fluencelabs/aqua-lib/builtin.aqua" + +data TSResult: + timestamp: u64 + peer_id: string + +service OpTS("op"): + identity(s: []string) + array(a: string, b: u64) -> []string + +service ToU32("op"): + identity(u: u32) -> u32 + + +func ts_getter(node: string, n_neighbors: u32) -> [][]string: + res: *[]string + none: *bool + nsize: *u32 + nsize <- ToU32.identity(n_neighbors) + + on node: + k <- Op.string_to_b58(node) + nodes <- Kademlia.neighborhood(k, none, nsize) + for n <- nodes par: + on n: + try: + ts <- Peer.timestamp_ms() + res <- OpTS.array(n, ts) + OpTS.identity(res!9) + <- res \ No newline at end of file diff --git a/snapshot/ts-validator/.gitignore b/snapshot/ts-validator/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/snapshot/ts-validator/.gitignore @@ -0,0 +1 @@ +/target diff --git a/snapshot/ts-validator/Cargo.toml b/snapshot/ts-validator/Cargo.toml new file mode 100644 index 0000000..d97fc1f --- /dev/null +++ b/snapshot/ts-validator/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "ts-validator" +version = "0.1.0" +edition = "2018" + +[dependencies] +serde_json = "1.0.64" +blake3 = "0.3.8" +libsecp256k1 = "0.5.0" +libp2p = "0.39.1" diff --git a/snapshot/ts-validator/src/main.rs b/snapshot/ts-validator/src/main.rs new file mode 100644 index 0000000..c6c8fcf --- /dev/null +++ b/snapshot/ts-validator/src/main.rs @@ -0,0 +1,146 @@ +use blake3; +use libp2p::{identity, PeerId}; +use serde_json; +use std::time::{Duration, SystemTime, UNIX_EPOCH}; + +// 1 minute in millis -- margin +- now for timestamp validation +static TS_DELTA: u32 = 60_000 as u32; + +#[derive(Debug)] +struct TSValidator { + peer_id: String, + doc_hash: Vec, + signed_hash: Vec, + node_ts: u128, + valid: bool, +} + +impl TSValidator { + pub fn create(keypair: identity::Keypair, json_string: String) -> Result { + let now_utc: u128 = SystemTime::now() + .duration_since(UNIX_EPOCH) + .unwrap() + .as_millis(); + + let json_doc: serde_json::Value = + serde_json::from_str(&json_string).expect("Invalid json string"); + if json_doc["timestamp"] == serde_json::Value::Null { + return Err("Missing timestamp key in json doc"); + } + + let proposed_ts = json_doc["timestamp"].as_u64().unwrap() as u128; + + let peer_id = keypair.public().into_peer_id().to_base58(); + let doc_hash = blake3::hash(&json_string.as_bytes()); + let signed_hash = keypair.sign(doc_hash.as_bytes()).unwrap(); + + let valid_proposal = Self::ts_validator(proposed_ts, now_utc, TS_DELTA).unwrap(); + + let res = TSValidator { + peer_id, + doc_hash: doc_hash.as_bytes().to_vec(), + signed_hash, + node_ts: now_utc, + valid: valid_proposal, + }; + + Ok(res) + } + + fn ts_validator(proposed_ts: u128, now_ts: u128, ts_delta: u32) -> Result { + let lower_threshold = now_ts - ts_delta as u128; + let upper_threshold = now_ts + ts_delta as u128; + if lower_threshold <= proposed_ts && proposed_ts <= upper_threshold { + return Ok(true); + } else { + Ok(false) + } + } +} + +fn main() { + println!("hello signing builtin wip"); + let now_utc: u128 = SystemTime::now() + .duration_since(UNIX_EPOCH) + .unwrap() + .as_millis(); + let json_string = serde_json::json!({ "timestamp": now_utc as u64 }).to_string(); + println!("json string: {}", json_string); + + let keypair = identity::Keypair::generate_secp256k1(); + + let res = TSValidator::create(keypair, json_string); + + println!("res: {:?}", res); +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_validate_good() { + assert!(true); + let now_utc: u128 = SystemTime::now() + .duration_since(UNIX_EPOCH) + .unwrap() + .as_millis(); + let json_string = serde_json::json!({ "timestamp": now_utc as u64 }).to_string(); + + let keypair = identity::Keypair::generate_secp256k1(); + + let res = TSValidator::create(keypair.clone(), json_string.clone()); + + assert!(res.is_ok()); + let res = res.unwrap(); + assert!(res.valid); + + let doc_hash = blake3::hash(&json_string.as_bytes()); + let verified = keypair + .public() + .verify(doc_hash.as_bytes(), &res.signed_hash); + assert!(verified); + } + + #[test] + fn test_validate_bad_proposal() { + assert!(true); + let now_utc: u128 = SystemTime::now() + .duration_since(UNIX_EPOCH) + .unwrap() + .as_millis(); + + let too_old_utc = now_utc - (2 * TS_DELTA) as u128; + let too_new_utc = now_utc + (2 * TS_DELTA) as u128; + + let keypair = identity::Keypair::generate_secp256k1(); + + let json_string = serde_json::json!({ "timestamp": too_old_utc as u64 }).to_string(); + let res = TSValidator::create(keypair.clone(), json_string); + assert!(res.is_ok()); + let res = res.unwrap(); + assert!(!res.valid); + + let json_string = serde_json::json!({ "timestamp": too_new_utc as u64 }).to_string(); + let res = TSValidator::create(keypair, json_string); + assert!(res.is_ok()); + let res = res.unwrap(); + assert!(!res.valid); + } + + #[test] + fn test_validate_missing_timestamp() { + assert!(true); + let now_utc: u128 = SystemTime::now() + .duration_since(UNIX_EPOCH) + .unwrap() + .as_millis(); + let json_string = serde_json::json!({ "time-stamp": now_utc as u64 }).to_string(); + + let keypair = identity::Keypair::generate_secp256k1(); + + let res = TSValidator::create(keypair, json_string); + + assert!(res.is_err()); + } +} diff --git a/snapshot/typescript/dist/air-scripts/timestamp_getter.js b/snapshot/typescript/dist/air-scripts/timestamp_getter.js index 1489c8c..677849b 100644 --- a/snapshot/typescript/dist/air-scripts/timestamp_getter.js +++ b/snapshot/typescript/dist/air-scripts/timestamp_getter.js @@ -48,7 +48,7 @@ function ts_getter(client, node, config) { request = new api_unstable_1.RequestFlowBuilder() .disableInjections() .withTTL((config === null || config === void 0 ? void 0 : config.ttl) || 5000) - .withRawScript("\n(xor\n (seq\n (seq\n (seq\n (seq\n (seq\n (call %init_peer_id% (\"getDataSrv\" \"-relay-\") [] -relay-)\n (call %init_peer_id% (\"getDataSrv\" \"node\") [] node)\n )\n (call -relay- (\"op\" \"noop\") [])\n )\n (xor\n (seq\n (seq\n (seq\n (call node (\"op\" \"string_to_b58\") [node] k)\n (call node (\"kad\" \"neighborhood\") [k false] nodes)\n )\n (fold nodes n\n (par\n (seq\n (xor\n (call n (\"peer\" \"timestamp_ms\") [] $res)\n (null)\n )\n (call node (\"op\" \"noop\") [])\n )\n (next n)\n )\n )\n )\n (call node (\"op\" \"identity\") [$res.$.[9]!])\n )\n (seq\n (call -relay- (\"op\" \"noop\") [])\n (call %init_peer_id% (\"errorHandlingSrv\" \"error\") [%last_error% 1])\n )\n )\n )\n (call -relay- (\"op\" \"noop\") [])\n )\n (xor\n (call %init_peer_id% (\"callbackSrv\" \"response\") [$res])\n (call %init_peer_id% (\"errorHandlingSrv\" \"error\") [%last_error% 2])\n )\n )\n (call %init_peer_id% (\"errorHandlingSrv\" \"error\") [%last_error% 3])\n)\n\n ") + .withRawScript("\n(xor\n (seq\n (seq\n (seq\n (seq\n (seq\n (seq\n (call %init_peer_id% (\"getDataSrv\" \"-relay-\") [] -relay-)\n (call %init_peer_id% (\"getDataSrv\" \"node\") [] node)\n )\n (call %init_peer_id% (\"op\" \"identity\") [100] $nsize)\n )\n (call -relay- (\"op\" \"noop\") [])\n )\n (xor\n (seq\n (seq\n (seq\n (call node (\"op\" \"string_to_b58\") [node] k)\n (call node (\"kad\" \"neighborhood\") [k $none $nsize] nodes)\n )\n (fold nodes n\n (par\n (seq\n (xor\n (seq\n (call n (\"peer\" \"timestamp_ms\") [] ts)\n (call n (\"op\" \"array\") [n ts] $res)\n )\n (null)\n )\n (call node (\"op\" \"noop\") [])\n )\n (next n)\n )\n )\n )\n (call node (\"op\" \"identity\") [$res.$.[9]!])\n )\n (seq\n (call -relay- (\"op\" \"noop\") [])\n (call %init_peer_id% (\"errorHandlingSrv\" \"error\") [%last_error% 1])\n )\n )\n )\n (call -relay- (\"op\" \"noop\") [])\n )\n (xor\n (call %init_peer_id% (\"callbackSrv\" \"response\") [$res])\n (call %init_peer_id% (\"errorHandlingSrv\" \"error\") [%last_error% 2])\n )\n )\n (call %init_peer_id% (\"errorHandlingSrv\" \"error\") [%last_error% 3])\n)\n\n ") .configHandler(function (h) { h.on('getDataSrv', '-relay-', function () { return client.relayPeerId; diff --git a/snapshot/typescript/dist/index.js b/snapshot/typescript/dist/index.js index d2d44ff..c1f3b76 100644 --- a/snapshot/typescript/dist/index.js +++ b/snapshot/typescript/dist/index.js @@ -55,25 +55,28 @@ var fluence_1 = require("@fluencelabs/fluence"); var fluence_network_environment_1 = require("@fluencelabs/fluence-network-environment"); // import { ethers } from "ethers"; var timestamp_getter_1 = require("./timestamp_getter"); +// simple timestamp diff calculator and counter function timestamp_delta(proposal_ts_ms, network_ts_ms) { + // acceptable deviation for proposed timestamp from network timestamps var acceptable_ts_diff = 60 * 1000; // 1 Minute + // valid and invalid array counters var valid_ts = []; var invalid_ts = []; + // if proposed timestamp <= network timestamp + acceptable delta + // we have a valid proposed timestamp for (var _i = 0, network_ts_ms_1 = network_ts_ms; _i < network_ts_ms_1.length; _i++) { var t = network_ts_ms_1[_i]; - var threshold_ts = t + acceptable_ts_diff; - console.log(t, threshold_ts); - if (threshold_ts > proposal_ts_ms) { - // results.get("valid"); // .valid_ts.push(t); + var upper_threshold = t + acceptable_ts_diff; + var lower_threshold = t - acceptable_ts_diff; + // console.log(t, threshold_ts); + if (lower_threshold <= proposal_ts_ms && proposal_ts_ms <= upper_threshold) { valid_ts.push(t); } else { - // results.set("invalid", invalid_ts.push(t)); invalid_ts.push(t); } } - console.log("valid_ts: ", valid_ts); - console.log("invalid_ts: ", invalid_ts); + // return results as a map for further, e..g, consensus, processing var results = new Map(); results.set("valid", valid_ts); results.set("invalid", invalid_ts); @@ -82,37 +85,34 @@ function timestamp_delta(proposal_ts_ms, network_ts_ms) { function main() { var _a, _b; return __awaiter(this, void 0, void 0, function () { - var fluence, network_result, now, utc_ts, ts_diffs, valid_ts, invalid_ts; + var fluence, now, utc_ts, network_result, ts_diffs, valid_ts, invalid_ts; return __generator(this, function (_c) { switch (_c.label) { - case 0: - console.log("hello"); - return [4 /*yield*/, fluence_1.createClient(fluence_network_environment_1.krasnodar[2])]; + case 0: return [4 /*yield*/, fluence_1.createClient(fluence_network_environment_1.krasnodar[2])]; case 1: fluence = _c.sent(); - return [4 /*yield*/, timestamp_getter_1.ts_getter(fluence, fluence_network_environment_1.krasnodar[2].peerId)]; - case 2: - network_result = _c.sent(); - console.log(network_result); - console.log(network_result[5]); now = new Date; utc_ts = Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate(), now.getUTCHours(), now.getUTCMinutes(), now.getUTCSeconds(), now.getUTCMilliseconds()); - console.log(utc_ts); + console.log("proxy for EIP712 proposed timestamp (utc): ", utc_ts); + return [4 /*yield*/, timestamp_getter_1.ts_getter(fluence, fluence_network_environment_1.krasnodar[2].peerId, Number(20))]; + case 2: + network_result = _c.sent(); ts_diffs = timestamp_delta(utc_ts, network_result); - console.log(ts_diffs); + // exceedingly simple consensus calculator + // if 2/3 of ts deltas are valid, we have consensus for a valid proposed timestamp if (ts_diffs.has("valid") && ts_diffs.has("invalid")) { valid_ts = (_a = ts_diffs.get("valid")) === null || _a === void 0 ? void 0 : _a.length; invalid_ts = (_b = ts_diffs.get("invalid")) === null || _b === void 0 ? void 0 : _b.length; - console.log(valid_ts, invalid_ts); if (valid_ts !== undefined && invalid_ts !== undefined && (valid_ts / (valid_ts + invalid_ts)) >= (2 / 3)) { - console.log("consensus"); + console.log("We have network consensus and accept the proposed timestamp ", utc_ts); + console.log("Now, the client can sign the EIP712 document."); } else { - console.log("no consensus"); + console.log("We do not have network consensus and reject the proposed timestamp ", utc_ts); } } else { - console.log("error: something went wrong with getting our timestamp validated"); + console.log("Error: Something went wrong with getting our timestamp validated."); } return [2 /*return*/]; } diff --git a/snapshot/typescript/dist/index_extended.js b/snapshot/typescript/dist/index_extended.js new file mode 100644 index 0000000..90b9ccd --- /dev/null +++ b/snapshot/typescript/dist/index_extended.js @@ -0,0 +1,127 @@ +"use strict"; +/* + * Copyright 2021 Fluence Labs Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var __generator = (this && this.__generator) || function (thisArg, body) { + var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; + return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; + function verb(n) { return function (v) { return step([n, v]); }; } + function step(op) { + if (f) throw new TypeError("Generator is already executing."); + while (_) try { + if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; + if (y = 0, t) op = [op[0] & 2, t.value]; + switch (op[0]) { + case 0: case 1: t = op; break; + case 4: _.label++; return { value: op[1], done: false }; + case 5: _.label++; y = op[1]; op = [0]; continue; + case 7: op = _.ops.pop(); _.trys.pop(); continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } + if (t[2]) _.ops.pop(); + _.trys.pop(); continue; + } + op = body.call(thisArg, _); + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; + } +}; +Object.defineProperty(exports, "__esModule", { value: true }); +var fluence_1 = require("@fluencelabs/fluence"); +var fluence_network_environment_1 = require("@fluencelabs/fluence-network-environment"); +// import { ethers } from "ethers"; +var timestamp_getter_extended_1 = require("./timestamp_getter_extended"); +function timestamp_delta(proposal_ts_ms, network_ts_ms) { + var acceptable_ts_diff = 60 * 1000; // 1 Minute + var valid_ts = []; + var invalid_ts = []; + for (var _i = 0, network_ts_ms_1 = network_ts_ms; _i < network_ts_ms_1.length; _i++) { + var t = network_ts_ms_1[_i]; + var upper_threshold = t + acceptable_ts_diff; + var lower_threshold = t - acceptable_ts_diff; + // console.log(t, threshold_ts); + if (lower_threshold <= proposal_ts_ms && proposal_ts_ms <= upper_threshold) { + valid_ts.push(t); + } + else { + invalid_ts.push(t); + } + } + console.log("valid_ts: ", valid_ts); + console.log("invalid_ts: ", invalid_ts); + var results = new Map(); + results.set("valid", valid_ts); + results.set("invalid", invalid_ts); + return results; +} +function main() { + var _a, _b; + return __awaiter(this, void 0, void 0, function () { + var fluence, now, utc_ts, network_result, ts_results, ts_diffs, valid_ts, invalid_ts; + return __generator(this, function (_c) { + switch (_c.label) { + case 0: + console.log("hello"); + return [4 /*yield*/, fluence_1.createClient(fluence_network_environment_1.krasnodar[2])]; + case 1: + fluence = _c.sent(); + now = new Date; + utc_ts = Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate(), now.getUTCHours(), now.getUTCMinutes(), now.getUTCSeconds(), now.getUTCMilliseconds()); + console.log(utc_ts); + return [4 /*yield*/, timestamp_getter_extended_1.ts_getter(fluence, fluence_network_environment_1.krasnodar[2].peerId, Number(20))]; + case 2: + network_result = _c.sent(); + console.log(network_result); + ts_results = network_result.map(function (a) { return Number(a[1]); }); + console.log(ts_results); + ts_diffs = timestamp_delta(utc_ts, ts_results); + console.log(ts_diffs); + if (ts_diffs.has("valid") && ts_diffs.has("invalid")) { + valid_ts = (_a = ts_diffs.get("valid")) === null || _a === void 0 ? void 0 : _a.length; + invalid_ts = (_b = ts_diffs.get("invalid")) === null || _b === void 0 ? void 0 : _b.length; + console.log(valid_ts, invalid_ts); + if (valid_ts !== undefined && invalid_ts !== undefined && (valid_ts / (valid_ts + invalid_ts)) >= (2 / 3)) { + console.log("consensus"); + } + else { + console.log("no consensus"); + } + } + else { + console.log("error: something went wrong with getting our timestamp validated"); + } + return [2 /*return*/]; + } + }); + }); +} +main() + .then(function () { return process.exit(0); }) + .catch(function (error) { + console.error(error); + process.exit(1); +}); diff --git a/snapshot/typescript/dist/timestamp_getter.js b/snapshot/typescript/dist/timestamp_getter.js index 9f3ee63..497411c 100644 --- a/snapshot/typescript/dist/timestamp_getter.js +++ b/snapshot/typescript/dist/timestamp_getter.js @@ -38,7 +38,7 @@ var __generator = (this && this.__generator) || function (thisArg, body) { Object.defineProperty(exports, "__esModule", { value: true }); exports.ts_getter = void 0; var api_unstable_1 = require("@fluencelabs/fluence/dist/api.unstable"); -function ts_getter(client, node, config) { +function ts_getter(client, node, n_neighbors, config) { return __awaiter(this, void 0, void 0, function () { var request, promise; return __generator(this, function (_a) { @@ -47,12 +47,13 @@ function ts_getter(client, node, config) { promise = new Promise(function (resolve, reject) { var r = new api_unstable_1.RequestFlowBuilder() .disableInjections() - .withRawScript("\n(xor\n (seq\n (seq\n (seq\n (seq\n (seq\n (call %init_peer_id% (\"getDataSrv\" \"-relay-\") [] -relay-)\n (call %init_peer_id% (\"getDataSrv\" \"node\") [] node)\n )\n (call -relay- (\"op\" \"noop\") [])\n )\n (xor\n (seq\n (seq\n (seq\n (call node (\"op\" \"string_to_b58\") [node] k)\n (call node (\"kad\" \"neighborhood\") [k false] nodes)\n )\n (fold nodes n\n (par\n (seq\n (xor\n (call n (\"peer\" \"timestamp_ms\") [] $res)\n (null)\n )\n (call node (\"op\" \"noop\") [])\n )\n (next n)\n )\n )\n )\n (call node (\"op\" \"identity\") [$res.$.[9]!])\n )\n (seq\n (call -relay- (\"op\" \"noop\") [])\n (call %init_peer_id% (\"errorHandlingSrv\" \"error\") [%last_error% 1])\n )\n )\n )\n (call -relay- (\"op\" \"noop\") [])\n )\n (xor\n (call %init_peer_id% (\"callbackSrv\" \"response\") [$res])\n (call %init_peer_id% (\"errorHandlingSrv\" \"error\") [%last_error% 2])\n )\n )\n (call %init_peer_id% (\"errorHandlingSrv\" \"error\") [%last_error% 3])\n)\n\n ") + .withRawScript("\n(xor\n (seq\n (seq\n (seq\n (seq\n (seq\n (seq\n (seq\n (call %init_peer_id% (\"getDataSrv\" \"-relay-\") [] -relay-)\n (call %init_peer_id% (\"getDataSrv\" \"node\") [] node)\n )\n (call %init_peer_id% (\"getDataSrv\" \"n_neighbors\") [] n_neighbors)\n )\n (call %init_peer_id% (\"op\" \"identity\") [n_neighbors] $nsize)\n )\n (call -relay- (\"op\" \"noop\") [])\n )\n (xor\n (seq\n (seq\n (seq\n (call node (\"op\" \"string_to_b58\") [node] k)\n (call node (\"kad\" \"neighborhood\") [k $none_bool $nsize] nodes)\n )\n (fold nodes n\n (par\n (seq\n (xor\n (call n (\"peer\" \"timestamp_ms\") [] $res)\n (null)\n )\n (call node (\"op\" \"noop\") [])\n )\n (next n)\n )\n )\n )\n (call node (\"op\" \"identity\") [$res.$.[9]!])\n )\n (seq\n (call -relay- (\"op\" \"noop\") [])\n (call %init_peer_id% (\"errorHandlingSrv\" \"error\") [%last_error% 1])\n )\n )\n )\n (call -relay- (\"op\" \"noop\") [])\n )\n (xor\n (call %init_peer_id% (\"callbackSrv\" \"response\") [$res])\n (call %init_peer_id% (\"errorHandlingSrv\" \"error\") [%last_error% 2])\n )\n )\n (call %init_peer_id% (\"errorHandlingSrv\" \"error\") [%last_error% 3])\n)\n\n ") .configHandler(function (h) { h.on('getDataSrv', '-relay-', function () { return client.relayPeerId; }); h.on('getDataSrv', 'node', function () { return node; }); + h.on('getDataSrv', 'n_neighbors', function () { return n_neighbors; }); h.onEvent('callbackSrv', 'response', function (args) { var res = args[0]; resolve(res); diff --git a/snapshot/typescript/dist/timestamp_getter_extended.js b/snapshot/typescript/dist/timestamp_getter_extended.js new file mode 100644 index 0000000..7ad260a --- /dev/null +++ b/snapshot/typescript/dist/timestamp_getter_extended.js @@ -0,0 +1,84 @@ +"use strict"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var __generator = (this && this.__generator) || function (thisArg, body) { + var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; + return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; + function verb(n) { return function (v) { return step([n, v]); }; } + function step(op) { + if (f) throw new TypeError("Generator is already executing."); + while (_) try { + if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; + if (y = 0, t) op = [op[0] & 2, t.value]; + switch (op[0]) { + case 0: case 1: t = op; break; + case 4: _.label++; return { value: op[1], done: false }; + case 5: _.label++; y = op[1]; op = [0]; continue; + case 7: op = _.ops.pop(); _.trys.pop(); continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } + if (t[2]) _.ops.pop(); + _.trys.pop(); continue; + } + op = body.call(thisArg, _); + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; + } +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.ts_getter = void 0; +var api_unstable_1 = require("@fluencelabs/fluence/dist/api.unstable"); +function ts_getter(client, node, n_neighbors, config) { + return __awaiter(this, void 0, void 0, function () { + var request, promise; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + promise = new Promise(function (resolve, reject) { + var r = new api_unstable_1.RequestFlowBuilder() + .disableInjections() + .withRawScript("\n(xor\n (seq\n (seq\n (seq\n (seq\n (seq\n (seq\n (seq\n (call %init_peer_id% (\"getDataSrv\" \"-relay-\") [] -relay-)\n (call %init_peer_id% (\"getDataSrv\" \"node\") [] node)\n )\n (call %init_peer_id% (\"getDataSrv\" \"n_neighbors\") [] n_neighbors)\n )\n (call %init_peer_id% (\"op\" \"identity\") [n_neighbors] $nsize)\n )\n (call -relay- (\"op\" \"noop\") [])\n )\n (xor\n (seq\n (seq\n (seq\n (call node (\"op\" \"string_to_b58\") [node] k)\n (call node (\"kad\" \"neighborhood\") [k $none $nsize] nodes)\n )\n (fold nodes n\n (par\n (seq\n (xor\n (seq\n (call n (\"peer\" \"timestamp_ms\") [] ts)\n (call n (\"op\" \"array\") [n ts] $res)\n )\n (null)\n )\n (call node (\"op\" \"noop\") [])\n )\n (next n)\n )\n )\n )\n (call node (\"op\" \"identity\") [$res.$.[9]!])\n )\n (seq\n (call -relay- (\"op\" \"noop\") [])\n (call %init_peer_id% (\"errorHandlingSrv\" \"error\") [%last_error% 1])\n )\n )\n )\n (call -relay- (\"op\" \"noop\") [])\n )\n (xor\n (call %init_peer_id% (\"callbackSrv\" \"response\") [$res])\n (call %init_peer_id% (\"errorHandlingSrv\" \"error\") [%last_error% 2])\n )\n )\n (call %init_peer_id% (\"errorHandlingSrv\" \"error\") [%last_error% 3])\n)\n\n ") + .configHandler(function (h) { + h.on('getDataSrv', '-relay-', function () { + return client.relayPeerId; + }); + h.on('getDataSrv', 'node', function () { return node; }); + h.on('getDataSrv', 'n_neighbors', function () { return n_neighbors; }); + h.onEvent('callbackSrv', 'response', function (args) { + var res = args[0]; + resolve(res); + }); + h.onEvent('errorHandlingSrv', 'error', function (args) { + // assuming error is the single argument + var err = args[0]; + reject(err); + }); + }) + .handleScriptError(reject) + .handleTimeout(function () { + reject('Request timed out for ts_getter'); + }); + if (config === null || config === void 0 ? void 0 : config.ttl) { + r.withTTL(config.ttl); + } + request = r.build(); + }); + return [4 /*yield*/, client.initiateFlow(request)]; + case 1: + _a.sent(); + return [2 /*return*/, promise]; + } + }); + }); +} +exports.ts_getter = ts_getter; diff --git a/snapshot/typescript/dist/typescript/index.js b/snapshot/typescript/dist/typescript/index.js index 7e22025..26dce1e 100644 --- a/snapshot/typescript/dist/typescript/index.js +++ b/snapshot/typescript/dist/typescript/index.js @@ -1,6 +1,6 @@ "use strict"; /* - * Copyright 2020 Fluence Labs Limited + * Copyright 2021 Fluence Labs Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -51,58 +51,78 @@ var __generator = (this && this.__generator) || function (thisArg, body) { } }; Object.defineProperty(exports, "__esModule", { value: true }); -// const { create, globSource, urlSource } = require('ipfs-http-client'); -// const all = require('it-all'); -// const uint8ArrayConcat = require('uint8arrays/concat') -// import { timestamp_getter } from "timestamp_getter"; -var local = [ - { - peerId: "12D3KooWHBG9oaVx4i3vi6c1rSBUm7MLBmyGmmbHoZ23pmjDCnvK", - multiaddr: "/ip4/127.0.0.1/tcp/9990/ws/p2p/12D3KooWHBG9oaVx4i3vi6c1rSBUm7MLBmyGmmbHoZ23pmjDCnvK" - }, - { - peerId: "12D3KooWRABanQHUn28dxavN9ZS1zZghqoZVAYtFpoN7FdtoGTFv", - multiaddr: "/ip4/127.0.0.1/tcp/9991/ws/p2p/12D3KooWRABanQHUn28dxavN9ZS1zZghqoZVAYtFpoN7FdtoGTFv" - }, - { - peerId: "12D3KooWFpQ7LHxcC9FEBUh3k4nSCC12jBhijJv3gJbi7wsNYzJ5", - multiaddr: "/ip4/127.0.0.1/tcp/9992/ws/p2p/12D3KooWFpQ7LHxcC9FEBUh3k4nSCC12jBhijJv3gJbi7wsNYzJ5" - }, -]; +var fluence_1 = require("@fluencelabs/fluence"); +var fluence_network_environment_1 = require("@fluencelabs/fluence-network-environment"); +// import { ethers } from "ethers"; +var timestamp_getter_1 = require("./timestamp_getter"); +function timestamp_delta(proposal_ts_ms, network_ts_ms) { + var acceptable_ts_diff = 60 * 1000; // 1 Minute + var valid_ts = []; + var invalid_ts = []; + for (var _i = 0, network_ts_ms_1 = network_ts_ms; _i < network_ts_ms_1.length; _i++) { + var t = network_ts_ms_1[_i]; + var threshold_ts = t + acceptable_ts_diff; + console.log(t, threshold_ts); + if (threshold_ts > proposal_ts_ms) { + // results.get("valid"); // .valid_ts.push(t); + valid_ts.push(t); + } + else { + // results.set("invalid", invalid_ts.push(t)); + invalid_ts.push(t); + } + } + console.log("valid_ts: ", valid_ts); + console.log("invalid_ts: ", invalid_ts); + var results = new Map(); + results.set("valid", valid_ts); + results.set("invalid", invalid_ts); + return results; +} function main() { return __awaiter(this, void 0, void 0, function () { + var fluence, network_result; return __generator(this, function (_a) { - console.log("hello"); - // setLogLevel('DEBUG'); - // const fluence = await createClient(testNet[1]); - // console.log("created a fluence client %s with relay %s", fluence.selfPeerId, fluence.relayPeerId); - /* - let ipfsAddr = 'https://stage.fluence.dev:15001'; - let ipfsMultiaddr = '/ip4/134.209.186.43/tcp/4001/p2p/12D3KooWEhCqQ9NBnmtSfNeXSNfhgccmH86xodkCUxZNEXab6pkw'; - const ipfs = create(ipfsAddr); - console.log("created ipfs client"); - - await ipfs.id(); - console.log("connected to ipfs"); - - let source = urlSource('https://images.adsttc.com/media/images/5ecd/d4ac/b357/65c6/7300/009d/large_jpg/02C.jpg?1590547607'); - const file = await ipfs.add(source); - console.log("uploaded file:", file); - - let files = await ipfs.get(file.cid); - for await (const file of files) { - const content = uint8ArrayConcat(await all(file.content)); - console.log("downloaded file of length ", content.length); + switch (_a.label) { + case 0: + console.log("hello"); + return [4 /*yield*/, fluence_1.createClient(fluence_network_environment_1.krasnodar[2])]; + case 1: + fluence = _a.sent(); + return [4 /*yield*/, timestamp_getter_1.ts_getter(fluence, fluence_network_environment_1.krasnodar[2].peerId)]; + case 2: + network_result = _a.sent(); + console.log(network_result); + console.log(network_result[5]); + /* + var now = new Date; + var utc_ts = Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate(), + now.getUTCHours(), now.getUTCMinutes(), now.getUTCSeconds(), now.getUTCMilliseconds()); + console.log(utc_ts); + + const ts_diffs = timestamp_delta(utc_ts, network_result); + console.log(ts_diffs); + + if (ts_diffs.has("valid") && ts_diffs.has("invalid")) { + let valid_ts = ts_diffs.get("valid")?.length; + let invalid_ts = ts_diffs.get("invalid")?.length; + + console.log(valid_ts, invalid_ts); + + if (valid_ts !== undefined && invalid_ts !== undefined && (valid_ts / (valid_ts + invalid_ts)) >= (2 / 3)) { + console.log("consensus"); + } + else { + console.log("no consensus"); + } + + } + else { + console.log("error: something went wrong with getting our timestamp validated"); + } + */ + return [2 /*return*/]; } - - console.log("file hash: ", file.cid); - let getResult = await get_from(fluence, testNet[2].peerId, file.cid.toString(), ipfsMultiaddr, { ttl: 10000 }); - console.log("Ipfs.get", getResult); - - let putResult = await put(fluence, testNet[2].peerId, getResult.path, { ttl: 10000 }); - console.log("Ipfs.put", putResult); - */ - return [2 /*return*/]; }); }); } diff --git a/snapshot/typescript/dist/typescript/timestamp_getter.js b/snapshot/typescript/dist/typescript/timestamp_getter.js index 1489c8c..d66ffa4 100644 --- a/snapshot/typescript/dist/typescript/timestamp_getter.js +++ b/snapshot/typescript/dist/typescript/timestamp_getter.js @@ -45,10 +45,9 @@ function ts_getter(client, node, config) { switch (_a.label) { case 0: promise = new Promise(function (resolve, reject) { - request = new api_unstable_1.RequestFlowBuilder() + var r = new api_unstable_1.RequestFlowBuilder() .disableInjections() - .withTTL((config === null || config === void 0 ? void 0 : config.ttl) || 5000) - .withRawScript("\n(xor\n (seq\n (seq\n (seq\n (seq\n (seq\n (call %init_peer_id% (\"getDataSrv\" \"-relay-\") [] -relay-)\n (call %init_peer_id% (\"getDataSrv\" \"node\") [] node)\n )\n (call -relay- (\"op\" \"noop\") [])\n )\n (xor\n (seq\n (seq\n (seq\n (call node (\"op\" \"string_to_b58\") [node] k)\n (call node (\"kad\" \"neighborhood\") [k false] nodes)\n )\n (fold nodes n\n (par\n (seq\n (xor\n (call n (\"peer\" \"timestamp_ms\") [] $res)\n (null)\n )\n (call node (\"op\" \"noop\") [])\n )\n (next n)\n )\n )\n )\n (call node (\"op\" \"identity\") [$res.$.[9]!])\n )\n (seq\n (call -relay- (\"op\" \"noop\") [])\n (call %init_peer_id% (\"errorHandlingSrv\" \"error\") [%last_error% 1])\n )\n )\n )\n (call -relay- (\"op\" \"noop\") [])\n )\n (xor\n (call %init_peer_id% (\"callbackSrv\" \"response\") [$res])\n (call %init_peer_id% (\"errorHandlingSrv\" \"error\") [%last_error% 2])\n )\n )\n (call %init_peer_id% (\"errorHandlingSrv\" \"error\") [%last_error% 3])\n)\n\n ") + .withRawScript("\n(xor\n (seq\n (seq\n (seq\n (seq\n (seq\n (seq\n (call %init_peer_id% (\"getDataSrv\" \"-relay-\") [] -relay-)\n (call %init_peer_id% (\"getDataSrv\" \"node\") [] node)\n )\n (call %init_peer_id% (\"op\" \"identity\") [100] $nsize)\n )\n (call -relay- (\"op\" \"noop\") [])\n )\n (xor\n (seq\n (seq\n (seq\n (call node (\"op\" \"string_to_b58\") [node] k)\n (call node (\"kad\" \"neighborhood\") [k $none $nsize] nodes)\n )\n (fold nodes n\n (par\n (seq\n (xor\n (seq\n (call n (\"peer\" \"timestamp_ms\") [] ts)\n (call n (\"op\" \"array\") [n ts] $res)\n )\n (null)\n )\n (call node (\"op\" \"noop\") [])\n )\n (next n)\n )\n )\n )\n (call node (\"op\" \"identity\") [$res.$.[9]!])\n )\n (seq\n (call -relay- (\"op\" \"noop\") [])\n (call %init_peer_id% (\"errorHandlingSrv\" \"error\") [%last_error% 1])\n )\n )\n )\n (call -relay- (\"op\" \"noop\") [])\n )\n (xor\n (call %init_peer_id% (\"callbackSrv\" \"response\") [$res])\n (call %init_peer_id% (\"errorHandlingSrv\" \"error\") [%last_error% 2])\n )\n )\n (call %init_peer_id% (\"errorHandlingSrv\" \"error\") [%last_error% 3])\n)\n\n ") .configHandler(function (h) { h.on('getDataSrv', '-relay-', function () { return client.relayPeerId; @@ -67,8 +66,11 @@ function ts_getter(client, node, config) { .handleScriptError(reject) .handleTimeout(function () { reject('Request timed out for ts_getter'); - }) - .build(); + }); + if (config === null || config === void 0 ? void 0 : config.ttl) { + r.withTTL(config.ttl); + } + request = r.build(); }); return [4 /*yield*/, client.initiateFlow(request)]; case 1: diff --git a/snapshot/typescript/index.ts b/snapshot/typescript/index.ts index e373953..3a61ba7 100644 --- a/snapshot/typescript/index.ts +++ b/snapshot/typescript/index.ts @@ -19,31 +19,33 @@ import { krasnodar, Node } from "@fluencelabs/fluence-network-environment"; // import { ethers } from "ethers"; import { ts_getter } from "./timestamp_getter"; - +// simple timestamp diff calculator and counter function timestamp_delta(proposal_ts_ms: number, network_ts_ms: number[]): Map> { + // acceptable deviation for proposed timestamp from network timestamps const acceptable_ts_diff: number = 60 * 1_000; // 1 Minute + + // valid and invalid array counters let valid_ts: Array = []; let invalid_ts: Array = []; + // if proposed timestamp <= network timestamp + acceptable delta + // we have a valid proposed timestamp for (var t of network_ts_ms) { - let threshold_ts: number = t + acceptable_ts_diff; - console.log(t, threshold_ts); + let upper_threshold: number = t + acceptable_ts_diff; + let lower_threshold: number = t - acceptable_ts_diff; + // console.log(t, threshold_ts); - if (threshold_ts > proposal_ts_ms) { - // results.get("valid"); // .valid_ts.push(t); + if (lower_threshold <= proposal_ts_ms && proposal_ts_ms <= upper_threshold) { valid_ts.push(t); } else { - // results.set("invalid", invalid_ts.push(t)); invalid_ts.push(t); } } - console.log("valid_ts: ", valid_ts); - console.log("invalid_ts: ", invalid_ts); - + // return results as a map for further, e..g, consensus, processing let results = new Map>(); results.set("valid", valid_ts); results.set("invalid", invalid_ts); @@ -51,39 +53,41 @@ function timestamp_delta(proposal_ts_ms: number, network_ts_ms: number[]): Map= (2 / 3)) { - console.log("consensus"); + console.log("We have network consensus and accept the proposed timestamp ", utc_ts); + console.log("Now, the client can sign the EIP712 document."); } else { - console.log("no consensus"); + console.log("We do not have network consensus and reject the proposed timestamp ", utc_ts); } - } else { - console.log("error: something went wrong with getting our timestamp validated"); + console.log("Error: Something went wrong with getting our timestamp validated."); } return; diff --git a/snapshot/typescript/index_extended.ts b/snapshot/typescript/index_extended.ts new file mode 100644 index 0000000..c88d3f9 --- /dev/null +++ b/snapshot/typescript/index_extended.ts @@ -0,0 +1,100 @@ +/* + * Copyright 2021 Fluence Labs Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { createClient, setLogLevel, FluenceClient } from "@fluencelabs/fluence"; +import { krasnodar, Node } from "@fluencelabs/fluence-network-environment"; +// import { ethers } from "ethers"; +import { ts_getter } from "./timestamp_getter_extended"; + + +function timestamp_delta(proposal_ts_ms: number, network_ts_ms: Array): Map> { + + const acceptable_ts_diff: number = 60 * 1_000; // 1 Minute + let valid_ts: Array = []; + let invalid_ts: Array = []; + + for (var t of network_ts_ms) { + let upper_threshold: number = t + acceptable_ts_diff; + let lower_threshold: number = t - acceptable_ts_diff; + // console.log(t, threshold_ts); + + if (lower_threshold <= proposal_ts_ms && proposal_ts_ms <= upper_threshold) { + valid_ts.push(t); + } + else { + invalid_ts.push(t); + } + + } + + console.log("valid_ts: ", valid_ts); + console.log("invalid_ts: ", invalid_ts); + + let results = new Map>(); + results.set("valid", valid_ts); + results.set("invalid", invalid_ts); + return results +} + +async function main() { + console.log("hello"); + // setLogLevel('DEBUG'); + const fluence = await createClient(krasnodar[2]); + // console.log("created a fluence client %s with relay %s", fluence.selfPeerId, fluence.relayPeerId); + + var now = new Date; + var utc_ts = Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate(), + now.getUTCHours(), now.getUTCMinutes(), now.getUTCSeconds(), + now.getUTCMilliseconds()); + console.log(utc_ts); + + const network_result = await ts_getter(fluence, krasnodar[2].peerId, Number(20)); + console.log(network_result); + + const ts_results: number[] = network_result.map(a => Number(a[1])); + console.log(ts_results); + + const ts_diffs = timestamp_delta(utc_ts, ts_results); + console.log(ts_diffs); + + if (ts_diffs.has("valid") && ts_diffs.has("invalid")) { + let valid_ts = ts_diffs.get("valid")?.length; + let invalid_ts = ts_diffs.get("invalid")?.length; + + console.log(valid_ts, invalid_ts); + + if (valid_ts !== undefined && invalid_ts !== undefined && (valid_ts / (valid_ts + invalid_ts)) >= (2 / 3)) { + console.log("consensus"); + } + else { + console.log("no consensus"); + } + + } + else { + console.log("error: something went wrong with getting our timestamp validated"); + } + + return; +} + +main() + .then(() => process.exit(0)) + .catch(error => { + console.error(error); + process.exit(1); + }); + diff --git a/snapshot/typescript/timestamp_getter.ts b/snapshot/typescript/timestamp_getter.ts index 4e5f77f..00ce2fa 100644 --- a/snapshot/typescript/timestamp_getter.ts +++ b/snapshot/typescript/timestamp_getter.ts @@ -12,7 +12,7 @@ import { RequestFlow } from '@fluencelabs/fluence/dist/internal/RequestFlow'; -export async function ts_getter(client: FluenceClient, node: string, config?: {ttl?: number}): Promise { +export async function ts_getter(client: FluenceClient, node: string, n_neighbors: number, config?: {ttl?: number}): Promise { let request: RequestFlow; const promise = new Promise((resolve, reject) => { const r = new RequestFlowBuilder() @@ -25,8 +25,14 @@ export async function ts_getter(client: FluenceClient, node: string, config?: {t (seq (seq (seq - (call %init_peer_id% ("getDataSrv" "-relay-") [] -relay-) - (call %init_peer_id% ("getDataSrv" "node") [] node) + (seq + (seq + (call %init_peer_id% ("getDataSrv" "-relay-") [] -relay-) + (call %init_peer_id% ("getDataSrv" "node") [] node) + ) + (call %init_peer_id% ("getDataSrv" "n_neighbors") [] n_neighbors) + ) + (call %init_peer_id% ("op" "identity") [n_neighbors] $nsize) ) (call -relay- ("op" "noop") []) ) @@ -35,7 +41,7 @@ export async function ts_getter(client: FluenceClient, node: string, config?: {t (seq (seq (call node ("op" "string_to_b58") [node] k) - (call node ("kad" "neighborhood") [k false] nodes) + (call node ("kad" "neighborhood") [k $none_bool $nsize] nodes) ) (fold nodes n (par @@ -75,6 +81,7 @@ export async function ts_getter(client: FluenceClient, node: string, config?: {t return client.relayPeerId!; }); h.on('getDataSrv', 'node', () => {return node;}); +h.on('getDataSrv', 'n_neighbors', () => {return n_neighbors;}); h.onEvent('callbackSrv', 'response', (args) => { const [res] = args; resolve(res); diff --git a/snapshot/typescript/timestamp_getter_extended.ts b/snapshot/typescript/timestamp_getter_extended.ts new file mode 100644 index 0000000..f41f2e5 --- /dev/null +++ b/snapshot/typescript/timestamp_getter_extended.ts @@ -0,0 +1,111 @@ +/** + * + * This file is auto-generated. Do not edit manually: changes may be erased. + * Generated by Aqua compiler: https://github.com/fluencelabs/aqua/. + * If you find any bugs, please write an issue on GitHub: https://github.com/fluencelabs/aqua/issues + * Aqua version: 0.1.8-161 + * + */ +import { FluenceClient, PeerIdB58 } from '@fluencelabs/fluence'; +import { RequestFlowBuilder } from '@fluencelabs/fluence/dist/api.unstable'; +import { RequestFlow } from '@fluencelabs/fluence/dist/internal/RequestFlow'; + + + +export async function ts_getter(client: FluenceClient, node: string, n_neighbors: number, config?: {ttl?: number}): Promise { + let request: RequestFlow; + const promise = new Promise((resolve, reject) => { + const r = new RequestFlowBuilder() + .disableInjections() + .withRawScript( + ` +(xor + (seq + (seq + (seq + (seq + (seq + (seq + (seq + (call %init_peer_id% ("getDataSrv" "-relay-") [] -relay-) + (call %init_peer_id% ("getDataSrv" "node") [] node) + ) + (call %init_peer_id% ("getDataSrv" "n_neighbors") [] n_neighbors) + ) + (call %init_peer_id% ("op" "identity") [n_neighbors] $nsize) + ) + (call -relay- ("op" "noop") []) + ) + (xor + (seq + (seq + (seq + (call node ("op" "string_to_b58") [node] k) + (call node ("kad" "neighborhood") [k $none $nsize] nodes) + ) + (fold nodes n + (par + (seq + (xor + (seq + (call n ("peer" "timestamp_ms") [] ts) + (call n ("op" "array") [n ts] $res) + ) + (null) + ) + (call node ("op" "noop") []) + ) + (next n) + ) + ) + ) + (call node ("op" "identity") [$res.$.[9]!]) + ) + (seq + (call -relay- ("op" "noop") []) + (call %init_peer_id% ("errorHandlingSrv" "error") [%last_error% 1]) + ) + ) + ) + (call -relay- ("op" "noop") []) + ) + (xor + (call %init_peer_id% ("callbackSrv" "response") [$res]) + (call %init_peer_id% ("errorHandlingSrv" "error") [%last_error% 2]) + ) + ) + (call %init_peer_id% ("errorHandlingSrv" "error") [%last_error% 3]) +) + + `, + ) + .configHandler((h) => { + h.on('getDataSrv', '-relay-', () => { + return client.relayPeerId!; + }); + h.on('getDataSrv', 'node', () => {return node;}); +h.on('getDataSrv', 'n_neighbors', () => {return n_neighbors;}); + h.onEvent('callbackSrv', 'response', (args) => { + const [res] = args; + resolve(res); +}); + + h.onEvent('errorHandlingSrv', 'error', (args) => { + // assuming error is the single argument + const [err] = args; + reject(err); + }); + }) + .handleScriptError(reject) + .handleTimeout(() => { + reject('Request timed out for ts_getter'); + }) + if(config?.ttl) { + r.withTTL(config.ttl) + } + request = r.build(); + }); + await client.initiateFlow(request!); + return promise; +} + \ No newline at end of file