-
-
Notifications
You must be signed in to change notification settings - Fork 141
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
c33f2cb
commit 86e34d3
Showing
3 changed files
with
45 additions
and
43 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,6 @@ | ||
// Haskell implementation: https://github.com/input-output-hk/hydra-poc/blob/master/plutus-merkle-tree/src/Plutus/MerkleTree.hs | ||
import { concat, equals } from "https://deno.land/[email protected]/bytes/mod.ts"; | ||
import { Sha256 } from "https://deno.land/[email protected]/hash/sha256.ts"; | ||
// TODO: get rid of async sha256 | ||
import { concat, equals } from "jsr:@std/bytes"; | ||
import { toHex } from "./utils.ts"; | ||
|
||
type MerkleNode = { | ||
|
@@ -20,18 +20,24 @@ export class MerkleTree { | |
root!: MerkleNode | null; | ||
|
||
/** Construct Merkle tree from data, which get hashed with sha256 */ | ||
constructor(data: Array<Uint8Array>) { | ||
this.root = MerkleTree.buildRecursively(data.map((d) => sha256(d))); | ||
static async new(data: Array<Uint8Array>): Promise<MerkleTree> { | ||
const tree = new this(); | ||
tree.root = await MerkleTree.buildRecursively( | ||
await Promise.all(data.map((d) => sha256(d))), | ||
); | ||
return tree; | ||
} | ||
|
||
/** Construct Merkle tree from sha256 hashes */ | ||
static fromHashes(hashes: Array<Hash>): MerkleTree { | ||
return new this(hashes); | ||
static async fromHashes(hashes: Array<Hash>): Promise<MerkleTree> { | ||
const tree = new this(); | ||
tree.root = await MerkleTree.buildRecursively(hashes); | ||
return tree; | ||
} | ||
|
||
private static buildRecursively( | ||
private static async buildRecursively( | ||
hashes: Array<Hash>, | ||
): MerkleNode | null { | ||
): Promise<MerkleNode | null> { | ||
if (hashes.length <= 0) return null; | ||
if (hashes.length === 1) { | ||
return { | ||
|
@@ -43,11 +49,11 @@ export class MerkleTree { | |
|
||
const cutoff = Math.floor(hashes.length / 2); | ||
const [left, right] = [hashes.slice(0, cutoff), hashes.slice(cutoff)]; | ||
const lnode = this.buildRecursively(left); | ||
const rnode = this.buildRecursively(right); | ||
const lnode = await this.buildRecursively(left); | ||
const rnode = await this.buildRecursively(right); | ||
if (lnode === null || rnode === null) return null; | ||
return { | ||
node: combineHash(lnode.node, rnode.node), | ||
node: await combineHash(lnode.node, rnode.node), | ||
left: lnode, | ||
right: rnode, | ||
}; | ||
|
@@ -58,8 +64,8 @@ export class MerkleTree { | |
return this.root.node; | ||
} | ||
|
||
getProof(data: Uint8Array): MerkleTreeProof { | ||
const hash = sha256(data); | ||
async getProof(data: Uint8Array): Promise<MerkleTreeProof> { | ||
const hash = await sha256(data); | ||
const proof: MerkleTreeProof = []; | ||
const searchRecursively = (tree: MerkleNode | null) => { | ||
if (tree && equals(tree.node, hash)) return true; | ||
|
@@ -90,23 +96,23 @@ export class MerkleTree { | |
return searchRecursively(this.root); | ||
} | ||
|
||
static verify( | ||
static async verify( | ||
data: Uint8Array, | ||
rootHash: Hash, | ||
proof: MerkleTreeProof, | ||
): boolean { | ||
const hash = sha256(data); | ||
const searchRecursively = ( | ||
): Promise<boolean> { | ||
const hash = await sha256(data); | ||
const searchRecursively = async ( | ||
rootHash2: Hash, | ||
proof: MerkleTreeProof, | ||
): boolean => { | ||
): Promise<boolean> => { | ||
if (proof.length <= 0) return equals(rootHash, rootHash2); | ||
const [h, t] = [proof[0], proof.slice(1)]; | ||
if (h.left) { | ||
return searchRecursively(combineHash(h.left, rootHash2), t); | ||
return searchRecursively(await combineHash(h.left, rootHash2), t); | ||
} | ||
if (h.right) { | ||
return searchRecursively(combineHash(rootHash2, h.right), t); | ||
return searchRecursively(await combineHash(rootHash2, h.right), t); | ||
} | ||
return false; | ||
}; | ||
|
@@ -129,10 +135,10 @@ export class MerkleTree { | |
|
||
export { concat, equals }; | ||
|
||
export function sha256(data: Uint8Array): Hash { | ||
return new Uint8Array(new Sha256().update(data).arrayBuffer()); | ||
export async function sha256(data: Uint8Array): Promise<Hash> { | ||
return new Uint8Array(await crypto.subtle.digest("SHA-256", data)); | ||
} | ||
|
||
export function combineHash(hash1: Hash, hash2: Hash): Hash { | ||
return sha256(concat(hash1, hash2)); | ||
export function combineHash(hash1: Hash, hash2: Hash): Promise<Hash> { | ||
return sha256(concat([hash1, hash2])); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,4 @@ | ||
import { | ||
decode, | ||
decodeString, | ||
encodeToString, | ||
} from "https://deno.land/[email protected]/encoding/hex.ts"; | ||
import { decodeHex, encodeHex } from "jsr:@std/encoding/hex"; | ||
import { | ||
Addresses, | ||
type Assets, | ||
|
@@ -15,16 +11,16 @@ import { | |
import { crc8 } from "../misc/crc8.ts"; | ||
|
||
export function fromHex(hex: string): Uint8Array { | ||
return decodeString(hex); | ||
return decodeHex(hex); | ||
} | ||
|
||
export function toHex(bytes: Uint8Array): string { | ||
return encodeToString(bytes); | ||
return encodeHex(bytes); | ||
} | ||
|
||
/** Convert a Hex encoded string to a Utf-8 encoded string. */ | ||
export function toText(hex: string): string { | ||
return new TextDecoder().decode(decode(new TextEncoder().encode(hex))); | ||
return new TextDecoder().decode(fromHex(hex)); | ||
} | ||
|
||
/** Convert a Utf-8 encoded string to a Hex encoded string. */ | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters