Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

etf.js V2: IDN Randomness beacon #13

Open
wants to merge 38 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
5f8e657
v2 initial commit
driemworks May 28, 2024
38d3321
add beacon sim, add skeleton for encrypt, add subscribe to justifs (#10)
driemworks Jun 4, 2024
83e347f
implemented decrypt function
colemanirby Jun 6, 2024
76130b0
pushing updated tests
colemanirby Jun 7, 2024
f2e074f
updated mock and test for encryption
colemanirby Jun 10, 2024
6e8707a
removed unused import in mock test. Updated decrypt to only retrieve …
colemanirby Jun 11, 2024
bf46066
move all text encoding into enrypt func
driemworks Jun 17, 2024
894e152
cleanup, make constnts
driemworks Jun 17, 2024
3d3d54e
beacon sim test WIP: output of beacon sim to be updated
driemworks Jun 18, 2024
968fbd2
fixed mock justification test
colemanirby Jun 21, 2024
5437927
removed unnecessary tests
colemanirby Jun 27, 2024
13a192d
updated decryption test and etf-sdk mock
colemanirby Jun 28, 2024
68c3e05
Code and import cleanup
colemanirby Jun 28, 2024
399b1da
Missed file from code cleanup
colemanirby Jun 28, 2024
39bfda3
pushing initial changes. Encrypt function still pending
colemanirby Aug 1, 2024
2fdad60
updated ibePubKey to use that of the beacon's pub key
colemanirby Aug 1, 2024
745c03b
pushing intermediate changes
colemanirby Aug 20, 2024
4daeab1
estiamte validator set id, refactoring
driemworks Aug 20, 2024
65b99a5
updated tests for earlyDecrypt function
colemanirby Aug 20, 2024
6f4f2dd
fix merge conflict
driemworks Aug 20, 2024
90cd665
update example
driemworks Aug 20, 2024
6b224f5
Merge branch 'dev' of github.com:ideal-lab5/etf.js into dev
driemworks Aug 20, 2024
068cd3e
use key field from hkdf output
driemworks Aug 20, 2024
b71ec5b
updated function names to tle, tld, and decrypt. Updated tests.
colemanirby Aug 20, 2024
cc3c9b4
moved objects into types.ts
colemanirby Aug 20, 2024
3e5cf7b
updated formatting
colemanirby Aug 20, 2024
07784eb
tld WIP: decryption fails due to invalid sigs
driemworks Aug 20, 2024
5961718
remove encoding when calling encrypt, add docs, example works
driemworks Aug 20, 2024
e5abab9
pushing delay_tx function. Testing and review pending
colemanirby Aug 20, 2024
8663973
Updated return types for tle, tld, decrypt, and delay
colemanirby Aug 21, 2024
a2eea42
Removed unnecessary TLECiphertext type
colemanirby Aug 21, 2024
26cb99a
removed TLECiphertext import
colemanirby Aug 21, 2024
d29520a
updated tests
colemanirby Aug 21, 2024
2ea7349
update delayed tx example
driemworks Aug 23, 2024
b7afd42
bump version
driemworks Sep 20, 2024
7b88726
merge dev
driemworks Sep 20, 2024
441be0e
fix: expect UInt8Array for tlock encryption
driemworks Sep 30, 2024
dd9d865
bump version
driemworks Sep 30, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# ETF.JS SDK

This is a javascript SDK to encrypt and decrypt messages with the ETF network. In particular, it lets users read slot secrets from the ETF network, encrypt messages to future slots, and decrypt from historical slots.
##### "Encryption to the Future"

This is an SDK for use within js/ts application to interact with the [Ideal Network](https://github.com/ideal-lab5/ideal-network).

## Installation

Expand Down
19 changes: 0 additions & 19 deletions docs/slot_schedules.md

This file was deleted.

38 changes: 20 additions & 18 deletions examples/react-delayed-txs/src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,9 @@ import { hexToU8a } from '@polkadot/util'
function App() {
const [etf, setEtf] = useState(null)
const [alice, setAlice] = useState(null)
const [threshold, setThreshold] = useState(2)
const [latestSlot, setLatestSlot] = useState(null)

const [latestSignature, setLatestSignature] = useState('');
const [latestBlock, setLatestBlock] = useState(null)

const [when, setWhen] = useState(0);

Expand All @@ -31,40 +32,41 @@ function App() {
const keyring = new Keyring()
const alice = keyring.addFromUri('//Bob', { name: 'Bob' }, 'sr25519')
setAlice(alice)

etf.eventEmitter.on('blockHeader', () => {
setLatestSlot(etf.latestSlot)
})
// stream incoming justifications and use the signature
etf.subscribeBeacon((justification) => {
setLatestBlock(parseInt(justification.commitment.blockNumber.replace(",", "")))
setLatestSignature(justification.signaturesCompact)
});
}
setup()
}, [])

/**
* Encrypt the current inputMessage textbox
* @param {*} e
*/
async function delay() {
// the call to delay
let innerCall = etf.api.tx.balances
.transferKeepAlive('5CMHXGNmDzSpQotcBUUPXyR8jRqfKttXuU87QraJrydrMdcz', 1000);
let deadline = etf.latestBlockNumber + 2;
.transferKeepAlive('5ETohe6skHTgZV97b5eZBfs48V6YzEGUhv9eeH6a3Ua7UNAc', 1000000);
let deadline = latestBlock + 5;
// prepare delayed call
let outerCall = etf.delay(innerCall, 127, deadline);
await outerCall.call.signAndSend(alice, result => {
if (result.status.isInBlock) {
setWhen(outerCall.block)
console.log(outerCall.block)
console.log('in block')
}
etf.delay(innerCall, 127, deadline, "testSeed").then(async outerCall => {
await outerCall.signAndSend(alice, result => {
if (result.status.isInBlock) {
setWhen(outerCall.block)
console.log('in block')
}
});
});

}

return (
<div className="App">
<div className="header">
Delayed Transactions Balance Transfer
<div>
Latest Block : {latestSlot === null ? 'Loading...' : latestSlot.slot}
Latest Block : { latestBlock }
</div>
</div>
<div className="encrypt-body">
Expand All @@ -76,7 +78,7 @@ function App() {
>Encrypt</button>
</div>
<div>
{ etf == null ? '' : when > etf.latestBlockNumber ?
{ etf == null ? '' : when > latestBlock ?
<span>
Balance transfer scheduled for block { when }
</span> : <span></span> }
Expand Down
217 changes: 186 additions & 31 deletions examples/react-delayed-txs/src/resources/etfTestSpecRaw.json

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions examples/react-tlock/.babelrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"presets": ["@babel/preset-env"]
}

3 changes: 2 additions & 1 deletion examples/react-tlock/src/App.css
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ td {
}

.data-display {
float: left;
/* float: left; */
display: grid;
padding: 10px;
}

Expand Down
180 changes: 105 additions & 75 deletions examples/react-tlock/src/App.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Etf } from '@ideallabs/etf.js'
import { Etf, Justfication } from '@ideallabs/etf.js'
import './App.css'
import React, { useEffect, useState } from 'react'

Expand All @@ -7,51 +7,92 @@ import chainSpec from './resources/etfTestSpecRaw.json';
function App() {
const [etf, setEtf] = useState(null)

const [latestSlot, setLatestSlot] = useState(null)
const [latestSignature, setLatestSignature] = useState('');
const [latestBlock, setLatestBlock] = useState(null)
const [distance, setDistance] = useState(5)
const [blockNumber, setBlockNumber] = useState(5)

const [ciphertexts, setCiphertexts] = useState([]);

const [decrypted, setDecrypted] = useState('')

useEffect(() => {
const setup = async () => {

// let etf = new Etf("wss://etf1.idealabs.network:443")
let etf = new Etf("ws://127.0.0.1:9944")
await etf.init(chainSpec)
setEtf(etf)

etf.eventEmitter.on('blockHeader', () => {
setLatestSlot(etf.latestSlot)
setLatestBlock(etf.latestBlockNumber);
})
// stream incoming justifications and use the signature
etf.subscribeBeacon((justification) => {
setLatestBlock(parseInt(justification.commitment.blockNumber.replace(",", "")))
setLatestSignature(justification.signaturesCompact)
});
}
setup()
}, [])

// const { xxhashAsU8a, blake2AsU8a } = require('@polkadot/util-crypto');
// const { stringToU8a, u8aToHex, bnToU8a } = require('@polkadot/util');

// function get_runtime_storage_parameter_with_key(
// module_name,
// function_name,
// key
// ) {
// // We use xxhash 128 for strings the runtime developer can control
// let module_hash = xxhashAsU8a(module_name, 128);
// let function_hash = xxhashAsU8a(function_name, 128);
// let key_hash = xxhashAsU8a(key, 128);

// // Special syntax to concatenate Uint8Array
// let final_key = new Uint8Array([
// ...module_hash,
// ...function_hash,
// ...key_hash,
// ]);

// // Return a hex string
// return u8aToHex(final_key);
// }

/**
* Encrypt the current inputMessage textbox
* @param {*} e
*/
async function encrypt(e) {
// let since = await etf.api.query.scheduler.incompleteSince();
// let test = await etf.api.query.scheduler.agenda(1);
// console.log('**********************')
// console.log(test);
// console.log('**********************')
e.preventDefault();
let t = new TextEncoder()

// let since = await etf.api.query.scheduler.incompleteSince();
// let storageKey = get_runtime_storage_parameter_with_key("Scheduler", "Agenda", bnToU8a(2000));
// console.log(storageKey)
// const agendaStorageHash = xxhashAsHex(stringToU8a("Scheduler Agenda"), 128);

// let storageAt = await etf.api.rpc.state.getStorage(storageKey);
// console.log('storage at ')
// console.log(storageAt.toHuman());

// each entry is a block number that has scheduled transactions
let entries = await etf.api.query.scheduler.agenda.entries();
entries.forEach(([key, value]) => {
console.log(key);
console.log(value.toHuman());
//
});

// we do not want to bind the message to the state
const inputElement = document.getElementById('inputMessage')
const inputMessage = inputElement.value
inputElement.value = ''
let deadline = latestBlock + parseInt(distance);

let deadline = parseInt(blockNumber);

try {
let out = etf.encrypt(t.encode(inputMessage), 1, [deadline], "testSeed")
let o = {
ciphertext: out.aes_ct.ciphertext,
nonce: out.aes_ct.nonce,
capsule: out.etf_ct,
deadline: deadline,
};
setCiphertexts([...ciphertexts, o]);
let out = await etf.timelockEncrypt(inputMessage, deadline, "testSeed")
setCiphertexts([...ciphertexts, { ct: out, deadline }]);
} catch (e) {
console.log(e)
}
Expand All @@ -60,15 +101,10 @@ function App() {
/**
* Attempt to decrypt something
*/
async function decrypt(ciphertext) {
async function decrypt(ciphertext, when) {
try {
let res = await etf.decrypt(
ciphertext.ciphertext,
ciphertext.nonce,
ciphertext.capsule,
[ciphertext.deadline],
)
let message = String.fromCharCode(...res.message)
let res = await etf.timelockDecrypt(ciphertext, when)
let message = String.fromCharCode(...res)
setDecrypted(message)
} catch (e) {
console.error(e)
Expand All @@ -78,56 +114,50 @@ function App() {
return (
<div className="App">
<div className="header">
EtF Js Timelock Encryption Example
<div>
Latest Block:{' '}
{latestBlock === null || latestBlock === undefined
? 'Loading...'
: latestBlock}
ETF.js Timelock Encryption Example
</div>
<div className='body'>
<div className='data-display'>
<span>Latest Block {JSON.stringify(latestBlock)} </span>
<span>Latest Signature {JSON.stringify(latestSignature)} </span>
</div>
<div>
Latest Slot:{' '}
{latestSlot === null || latestSlot === undefined
? 'Loading...'
: latestSlot.slot}
<div className="ciphertext-display">
Your encrypted messages
{ciphertexts && ciphertexts.map((info, idx) => {
return (
<div key={idx} className="encrypted-message-data-display">
<span>deadline: {info.deadline}</span>
<button onClick={() => decrypt(info.ct, info.deadline)}>Decrypt</button>
</div>
)
})}
<div>{decrypted}</div>
</div>
<div className="encrypt-body">
<span>Write a message</span>
<textarea
id="inputMessage"
name="secret-message"
cols="40"
rows="5"
></textarea>
<form className="form">
<label htmlFor="blocknumber">Block Number</label>
<input
id="block_number"
type="number"
onChange={(e) => setBlockNumber(e.target.value)}
value={blockNumber}
placeholder=""
/>
<input
className="button"
type="submit"
onClick={encrypt}
value="Encrypt"
/>
</form>
</div>
</div>
<div className="data-display">
Your encrypted messages
{ciphertexts && ciphertexts.map((info, idx) => {
return (
<div key={idx} className="encrypted-message-data-display">
<span>deadline: { info.deadline }</span>
<button onClick={() => decrypt(info)}>Decrypt</button>
</div>
)
})}
<div>{decrypted}</div>
</div>
<div className="encrypt-body">
<span>Write a message</span>
<textarea
id="inputMessage"
name="secret-message"
cols="40"
rows="5"
></textarea>
<form className="form">
<label htmlFor="distance">Distance</label>
<input
id="distance"
type="number"
onChange={(e) => setDistance(e.target.value)}
value={distance}
placeholder=""
/>
<input
className="button"
type="submit"
onClick={encrypt}
value="Encrypt"
/>
</form>
</div>
</div>
)
Expand Down
Loading