Skip to content

Commit

Permalink
Merge pull request #55 from Chia-Network/20231114-wasm-support-uint8-…
Browse files Browse the repository at this point in the history
…array

20231114 wasm support uint8 array
  • Loading branch information
prozacchiwawa authored Nov 15, 2023
2 parents a8bfff9 + 7bb85ba commit b37adad
Show file tree
Hide file tree
Showing 6 changed files with 63 additions and 23 deletions.
7 changes: 6 additions & 1 deletion wasm/src/jsval.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use js_sys::JSON::stringify;
use js_sys::{Array, BigInt, Object, Reflect};
use js_sys::{Array, BigInt, Object, Reflect, Uint8Array};
use wasm_bindgen::JsCast;

use num_bigint::ToBigInt;
Expand Down Expand Up @@ -190,6 +190,11 @@ pub fn sexp_from_js_object(sstart: Srcloc, v: &JsValue) -> Option<Rc<SExp>> {
.and_then(|o| Object::try_from(&o).cloned())
.and_then(|o| location(&o))
.unwrap_or_else(|| sstart.clone());
if Uint8Array::instanceof(v) {
// Explicitly handle uint8array conversion.
let as_uint8array = Uint8Array::unchecked_from_js(v.clone());
return Some(Rc::new(SExp::Atom(loc, as_uint8array.to_vec())));
}
get_property(o, "pair")
.and_then(|p| {
let pa = Array::from(&p);
Expand Down
14 changes: 7 additions & 7 deletions wasm/src/objects.rs
Original file line number Diff line number Diff line change
Expand Up @@ -281,21 +281,21 @@ interface ITuple {
interface IProgram {
toString(): string;
as_pair(): ITuple;
listp(): bool;
nullp(): bool;
listp(): boolean;
nullp(): boolean;
as_int(): number;
as_bigint(): bigint;
as_bin(): [Uint8Array];
as_bin(): Uint8Array;
first(): IProgram;
rest(): IProgram;
cons(p: IProgram): IProgram;
run(code: IProgram, env: IProgram): [number, IProgram];
run(env: IProgram): [number, IProgram];
list_len(): number;
equal_to(other: IProgram): bool;
equal_to(other: IProgram): boolean;
as_javascript(): any;
curry(args: [IProgram]): IProgram;
sha256tree(): [Uint8Array];
uncurry_error(): [IProgram];
sha256tree(): Uint8Array;
uncurry_error(): [IProgram, Array<IProgram>];
uncurry(): [IProgram, Array<IProgram>|null];
}
"#;
Expand Down
2 changes: 1 addition & 1 deletion wasm/tests/clvm-tools-interface/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"start": "webpack serve --config webpack.config.demo.js",
"build": "webpack && tsc",
"build:demo": "webpack --config webpack.config.demo.js",
"test": "jest",
"test": "tsc -p tstestconfig.json --noEmit && jest",
"coverage": "npm run test -- --coverage",
"prepare": "npm run build",
"trypublish": "npm publish || true"
Expand Down
52 changes: 38 additions & 14 deletions wasm/tests/clvm-tools-interface/src/lib/tests/index.test.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import type { Program, IProgram, ITuple } from '../../../../../pkg/clvm_tools_wasm.d.ts';
import type { IProgram, ITuple } from '../../../../../pkg/clvm_tools_wasm.js';
import type { G1Element } from 'bls-signatures';

import * as fs from 'fs';
import { resolve } from 'path';
import * as assert from 'assert';
import * as bls_loader from 'bls-signatures';
const {h, t, Program} = require('../../../../../pkg/clvm_tools_wasm');
const {h, t, Program} = require('../../../../../pkg/clvm_tools_wasm.js');

it('Has BLS signatures support', async () => {
const bls = await bls_loader.default();
Expand All @@ -18,6 +19,28 @@ it('Has the "h" function', async () => {
assert.equal([0x21, 0x20, 0x30, 0x31].toString(), unhexed.toString());
});

it('Converts uint8arrays', async () => {
let ua = new Uint8Array(3);
ua[0] = 0x30;
ua[1] = 0x81;
ua[2] = 0xff;
let p = Program.to(ua);
assert.equal([0x30, 0x81, 0xff].toString(), ua.toString());
});

it('Converts uint8arrays from the "h" function', async () => {
let unhexed = h('8b5fd961cb1a826823c45a796b350d0d6ba2398829f249b1e535fd76f6d150b1');
let p = Program.to([unhexed]);
assert.equal("ffa08b5fd961cb1a826823c45a796b350d0d6ba2398829f249b1e535fd76f6d150b180", p.toString());
});

it('Converts a buffer', async () => {
let unhexed = h('8b5fd961cb1a826823c45a796b350d0d6ba2398829f249b1e535fd76f6d150b1');
let b = Buffer.from(unhexed);
let p = Program.to([b]);
assert.equal("ffa08b5fd961cb1a826823c45a796b350d0d6ba2398829f249b1e535fd76f6d150b180", p.toString());
});

it('Converts to string', async () => {
const converted_sexp = Program.to([1, 2, 3]);
assert.equal("ff01ff02ff0380", converted_sexp.toString());
Expand Down Expand Up @@ -64,7 +87,7 @@ it('Has as_int', async () => {
try {
/*const non_int_value =*/ Program.to([7,13]).as_int();
assert.fail('was an int but should not be');
} catch (e) {
} catch (e: any) {
assert.equal(e.toString(), "not a number");
}
});
Expand All @@ -75,7 +98,7 @@ it('Has as_bigint', async () => {
try {
/*const non_int_value =*/ Program.to([7,13]).as_bigint();
assert.fail('');
} catch (e) {
} catch (e: any) {
assert.equal(e.toString(), "not a number");
}
});
Expand All @@ -87,13 +110,13 @@ it('Has first and rest', async () => {
try {
Program.to([]).first();
assert.fail("empty list had first");
} catch (e) {
} catch (e: any) {
assert.equal(e.toString(), "not a cons");
}
try {
Program.to([]).rest();
assert.fail("empty list had rest");
} catch (e) {
} catch (e: any) {
assert.equal(e.toString(), "not a cons");
}
});
Expand All @@ -116,7 +139,7 @@ it('Has the t function', async () => {

it('Has as_bin', async () => {
const test_data = Program.to([7,8,9,10]);
const as_bin = test_data.as_bin();
const as_bin: Uint8Array = test_data.as_bin();
assert.equal([255,7,255,8,255,9,255,10,128].toString(), as_bin.toString());
});

Expand Down Expand Up @@ -168,8 +191,8 @@ export class ChiaExample {
constructor(MOD: IProgram) {
this.MOD = MOD;
}
public puzzle_for_synthetic_public_key(synthetic_public_key: G1Element): Program {
return this.MOD.curry(synthetic_public_key);
public puzzle_for_synthetic_public_key(synthetic_public_key: G1Element): IProgram {
return this.MOD.curry(Program.to(synthetic_public_key));
}
}

Expand All @@ -178,15 +201,16 @@ it('works as expected in context', async () => {
const program_text = fs.readFileSync(resolve(__dirname, '../../../content/p2_delegated_puzzle_or_hidden_puzzle.clvm.hex'),'utf-8');
const MOD: IProgram = Program.from_hex(program_text);
const ce = new ChiaExample(MOD);
const sk = bls.AugSchemeMPL.key_gen([
const sk = bls.AugSchemeMPL.key_gen(new Uint8Array([
0, 50, 6, 244, 24, 199, 1, 25, 52, 88, 192, 19, 18, 12, 89, 6, 220,
18, 102, 58, 209, 82, 12, 62, 89, 110, 182, 9, 44, 20, 254, 22
]);
]));
const pk = bls.AugSchemeMPL.sk_to_g1(sk);
// pk bytes 86243290bbcbfd9ae75bdece7981965350208eb5e99b04d5cd24e955ada961f8c0a162dee740be7bdc6c3c0613ba2eb1
// Expected puzzle hash = 30cdae3d54778db5eba21584c452cfb1a278136b2ec352ba44a52078efea7507
const target_puzzle = ce.puzzle_for_synthetic_public_key(pk);
assert.equal(target_puzzle.sha256tree().toString(), h('30cdae3d54778db5eba21584c452cfb1a278136b2ec352ba44a52078efea7507').toString());
const shatree_result: Uint8Array = target_puzzle.sha256tree();
assert.equal(shatree_result.toString(), h('30cdae3d54778db5eba21584c452cfb1a278136b2ec352ba44a52078efea7507').toString());
});

const cat2_puzzle = 'ff02ffff01ff02ff5effff04ff02ffff04ffff04ff05ffff04ffff0bff2cff0580ffff04ff0bff80808080ffff04ffff02ff17ff2f80ffff04ff5fffff04ffff02ff2effff04ff02ffff04ff17ff80808080ffff04ffff0bff82027fff82057fff820b7f80ffff04ff81bfffff04ff82017fffff04ff8202ffffff04ff8205ffffff04ff820bffff80808080808080808080808080ffff04ffff01ffffffff81ca3dff46ff0233ffff3c04ff01ff0181cbffffff02ff02ffff03ff05ffff01ff02ff32ffff04ff02ffff04ff0dffff04ffff0bff22ffff0bff2cff3480ffff0bff22ffff0bff22ffff0bff2cff5c80ff0980ffff0bff22ff0bffff0bff2cff8080808080ff8080808080ffff010b80ff0180ffff02ffff03ff0bffff01ff02ffff03ffff09ffff02ff2effff04ff02ffff04ff13ff80808080ff820b9f80ffff01ff02ff26ffff04ff02ffff04ffff02ff13ffff04ff5fffff04ff17ffff04ff2fffff04ff81bfffff04ff82017fffff04ff1bff8080808080808080ffff04ff82017fff8080808080ffff01ff088080ff0180ffff01ff02ffff03ff17ffff01ff02ffff03ffff20ff81bf80ffff0182017fffff01ff088080ff0180ffff01ff088080ff018080ff0180ffff04ffff04ff05ff2780ffff04ffff10ff0bff5780ff778080ff02ffff03ff05ffff01ff02ffff03ffff09ffff02ffff03ffff09ff11ff7880ffff0159ff8080ff0180ffff01818f80ffff01ff02ff7affff04ff02ffff04ff0dffff04ff0bffff04ffff04ff81b9ff82017980ff808080808080ffff01ff02ff5affff04ff02ffff04ffff02ffff03ffff09ff11ff7880ffff01ff04ff78ffff04ffff02ff36ffff04ff02ffff04ff13ffff04ff29ffff04ffff0bff2cff5b80ffff04ff2bff80808080808080ff398080ffff01ff02ffff03ffff09ff11ff2480ffff01ff04ff24ffff04ffff0bff20ff2980ff398080ffff010980ff018080ff0180ffff04ffff02ffff03ffff09ff11ff7880ffff0159ff8080ff0180ffff04ffff02ff7affff04ff02ffff04ff0dffff04ff0bffff04ff17ff808080808080ff80808080808080ff0180ffff01ff04ff80ffff04ff80ff17808080ff0180ffffff02ffff03ff05ffff01ff04ff09ffff02ff26ffff04ff02ffff04ff0dffff04ff0bff808080808080ffff010b80ff0180ff0bff22ffff0bff2cff5880ffff0bff22ffff0bff22ffff0bff2cff5c80ff0580ffff0bff22ffff02ff32ffff04ff02ffff04ff07ffff04ffff0bff2cff2c80ff8080808080ffff0bff2cff8080808080ffff02ffff03ffff07ff0580ffff01ff0bffff0102ffff02ff2effff04ff02ffff04ff09ff80808080ffff02ff2effff04ff02ffff04ff0dff8080808080ffff01ff0bff2cff058080ff0180ffff04ffff04ff28ffff04ff5fff808080ffff02ff7effff04ff02ffff04ffff04ffff04ff2fff0580ffff04ff5fff82017f8080ffff04ffff02ff7affff04ff02ffff04ff0bffff04ff05ffff01ff808080808080ffff04ff17ffff04ff81bfffff04ff82017fffff04ffff0bff8204ffffff02ff36ffff04ff02ffff04ff09ffff04ff820affffff04ffff0bff2cff2d80ffff04ff15ff80808080808080ff8216ff80ffff04ff8205ffffff04ff820bffff808080808080808080808080ff02ff2affff04ff02ffff04ff5fffff04ff3bffff04ffff02ffff03ff17ffff01ff09ff2dffff0bff27ffff02ff36ffff04ff02ffff04ff29ffff04ff57ffff04ffff0bff2cff81b980ffff04ff59ff80808080808080ff81b78080ff8080ff0180ffff04ff17ffff04ff05ffff04ff8202ffffff04ffff04ffff04ff24ffff04ffff0bff7cff2fff82017f80ff808080ffff04ffff04ff30ffff04ffff0bff81bfffff0bff7cff15ffff10ff82017fffff11ff8202dfff2b80ff8202ff808080ff808080ff138080ff80808080808080808080ff018080';
Expand All @@ -195,8 +219,8 @@ const cat2_curried_program = 'ff02ffff01ff02ffff01ff02ffff03ff0bffff01ff02ffff03

it('can uncurry an example program', async () => {
const to_uncurry_text = fs.readFileSync(resolve(__dirname, '../../../content/test_cat2_program.hex'),'utf-8');
const program: IProgram = Program.from_hex(to_uncurry_text);
const uncurried: Array<IProgram> = program.uncurry_error();
const program = Program.from_hex(to_uncurry_text);
const uncurried = program.uncurry_error();
assert.equal(uncurried.length, 2);
assert.equal(uncurried[1].length, 3);
assert.equal(uncurried[0].toString(), cat2_puzzle);
Expand Down
1 change: 1 addition & 0 deletions wasm/tests/clvm-tools-interface/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
"suppressImplicitAnyIndexErrors": true,
"lib": ["es2018", "dom"],
"moduleResolution": "node",
"target": "es2020"
},
"include": ["src/lib"],
"exclude": ["src/lib/**/tests"],
Expand Down
10 changes: 10 additions & 0 deletions wasm/tests/clvm-tools-interface/tstestconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"emitDeclarationOnly": false,
"noEmitOnError": true,
"strict": true,
},
"include": ["src/lib/**/tests"],
"exclude": []
}

0 comments on commit b37adad

Please sign in to comment.