feat: use wasm-isomorphic crypto lib

This commit is contained in:
Michał Konopka
2023-02-23 15:16:35 +01:00
committed by just_ppe
parent 610cff9141
commit fb32b0d33b
6 changed files with 6942 additions and 29 deletions

View File

@@ -11,7 +11,7 @@
}, },
"sideEffects": false, "sideEffects": false,
"engines": { "engines": {
"node": ">=16.5" "node": ">=16.8"
}, },
"scripts": { "scripts": {
"build:cjs": "tsc -b tsconfig.json", "build:cjs": "tsc -b tsconfig.json",
@@ -78,7 +78,7 @@
"stream-buffers": "^3.0.2", "stream-buffers": "^3.0.2",
"unzipit": "^1.4.0", "unzipit": "^1.4.0",
"vm2": "3.9.13", "vm2": "3.9.13",
"warp-isomorphic": "1.0.0", "warp-isomorphic": "1.0.4",
"warp-wasm-metering": "1.0.1" "warp-wasm-metering": "1.0.1"
}, },
"devDependencies": { "devDependencies": {

View File

@@ -203,7 +203,7 @@ export interface Contract<State = unknown> {
/** /**
* calculates state hash using stable stringify * calculates state hash using stable stringify
*/ */
stateHash(state: State): string; stateHash(state: State): Promise<string>;
/** /**
* this method allows to sync the state of the local SDK state with the state provided by an external endpoint; * this method allows to sync the state of the local SDK state with the state provided by an external endpoint;

View File

@@ -30,6 +30,7 @@ import { EvaluationOptionsEvaluator } from './EvaluationOptionsEvaluator';
import { WarpFetchWrapper } from '../core/WarpFetchWrapper'; import { WarpFetchWrapper } from '../core/WarpFetchWrapper';
import { Mutex } from 'async-mutex'; import { Mutex } from 'async-mutex';
import { TransactionStatusResponse } from '../utils/types/arweave-types'; import { TransactionStatusResponse } from '../utils/types/arweave-types';
import { Crypto } from 'warp-isomorphic';
/** /**
* An implementation of {@link Contract} that is backwards compatible with current style * An implementation of {@link Contract} that is backwards compatible with current style
@@ -505,11 +506,11 @@ export class HandlerBasedContract<State> implements Contract<State> {
sortedInteractions = interactions sortedInteractions = interactions
? interactions ? interactions
: await interactionsLoader.load( : await interactionsLoader.load(
contractTxId, contractTxId,
cachedState?.sortKey, cachedState?.sortKey,
this.getToSortKey(upToSortKey), this.getToSortKey(upToSortKey),
contractEvaluationOptions contractEvaluationOptions
); );
// (2) ...but we still need to return only interactions up to original "upToSortKey" // (2) ...but we still need to return only interactions up to original "upToSortKey"
if (cachedState?.sortKey) { if (cachedState?.sortKey) {
@@ -792,16 +793,12 @@ export class HandlerBasedContract<State> implements Contract<State> {
return this._benchmarkStats; return this._benchmarkStats;
} }
stateHash(state: State): string { async stateHash(state: State): Promise<string> {
const jsonState = stringify(state); const jsonState = stringify(state);
// note: cannot reuse: const hash = await Crypto.subtle.digest('SHA-256', Buffer.from(jsonState, 'utf-8'));
// "The Hash object can not be used again after hash.digest() method has been called.
// Multiple calls will cause an error to be thrown."
const hash = crypto.createHash('sha256');
hash.update(jsonState);
return hash.digest('hex'); return Buffer.from(hash).toString('hex');
} }
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- params can be anything // eslint-disable-next-line @typescript-eslint/no-explicit-any -- params can be anything

View File

@@ -1,13 +1,13 @@
import { InteractionData } from './modules/impl/HandlerExecutorFactory'; import { InteractionData } from './modules/impl/HandlerExecutorFactory';
import { InnerCallType } from '../contract/Contract'; import { InnerCallType } from '../contract/Contract';
import { isomorphicRandomUUID } from '../utils/utils'; import { Crypto } from 'warp-isomorphic';
export class ContractCallRecord { export class ContractCallRecord {
readonly interactions: { [key: string]: InteractionCall } = {}; readonly interactions: { [key: string]: InteractionCall } = {};
readonly id: string; readonly id: string;
constructor(readonly contractTxId: string, readonly depth: number, readonly innerCallType: InnerCallType = null) { constructor(readonly contractTxId: string, readonly depth: number, readonly innerCallType: InnerCallType = null) {
this.id = isomorphicRandomUUID(); this.id = Crypto.randomUUID();
} }
// eslint-disable-next-line @typescript-eslint/no-explicit-any // eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -45,7 +45,7 @@ export class ContractCallRecord {
export class InteractionCall { export class InteractionCall {
interactionOutput: InteractionOutput; interactionOutput: InteractionOutput;
private constructor(readonly interactionInput: InteractionInput) {} private constructor(readonly interactionInput: InteractionInput) { }
static create(interactionInput: InteractionInput): InteractionCall { static create(interactionInput: InteractionInput): InteractionCall {
return new InteractionCall(interactionInput); return new InteractionCall(interactionInput);
@@ -67,7 +67,7 @@ export class InteractionInput {
public readonly functionArguments: [], public readonly functionArguments: [],
public readonly dryWrite: boolean, public readonly dryWrite: boolean,
public readonly foreignContractCalls: { [key: string]: ContractCallRecord } = {} public readonly foreignContractCalls: { [key: string]: ContractCallRecord } = {}
) {} ) { }
} }
export class InteractionOutput { export class InteractionOutput {
@@ -79,5 +79,5 @@ export class InteractionOutput {
public readonly valid: boolean, public readonly valid: boolean,
public readonly errorMessage: string = '', public readonly errorMessage: string = '',
public readonly gasUsed: number public readonly gasUsed: number
) {} ) { }
} }

View File

@@ -1,7 +1,6 @@
/* eslint-disable */ /* eslint-disable */
import copy from 'fast-copy'; import copy from 'fast-copy';
import { Buffer } from 'warp-isomorphic'; import { Buffer } from 'warp-isomorphic';
import { randomUUID } from 'crypto';
export const sleep = (ms: number): Promise<void> => { export const sleep = (ms: number): Promise<void> => {
return new Promise((resolve) => setTimeout(resolve, ms)); return new Promise((resolve) => setTimeout(resolve, ms));
@@ -76,12 +75,4 @@ export function bufToBn(buf: Buffer) {
return BigInt('0x' + hex.join('')); return BigInt('0x' + hex.join(''));
} }
export function isomorphicRandomUUID() {
if (isBrowser() && self.crypto) {
return self.crypto.randomUUID();
} else {
return randomUUID();
}
}
export const isBrowser = new Function('try {return this===window;}catch(e){ return false;}'); export const isBrowser = new Function('try {return this===window;}catch(e){ return false;}');

6925
yarn.lock Normal file

File diff suppressed because it is too large Load Diff