Skip to content

Commit

Permalink
Merge pull request #20 from sCrypt-Inc/blockchain-lib
Browse files Browse the repository at this point in the history
Finish blockchain lib
  • Loading branch information
msinkec authored Mar 29, 2024
2 parents aac8fe3 + 833d5ac commit 2dd2980
Show file tree
Hide file tree
Showing 4 changed files with 427 additions and 409 deletions.
94 changes: 42 additions & 52 deletions src/blockchain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,74 +41,64 @@ export class Blockchain extends SmartContractLib {
)
}

// Is txid the last transaction in a block
// Check if tx is the last within block using its merkle path.
@method()
static lastTxInBlock(
static isLastTxInBlock(merkleProof: MerkleProof, depth: number): boolean {
let last = true

for (let i = 0; i < depth; i++) {
const node = merkleProof[i]

if (node.pos != MerklePath.INVALID_NODE) {
if (node.pos != MerklePath.LEFT_NODE) {
last = false
}
}
}

return last
}

// Calculate a tx's index in a block from its merkle path.
@method()
static txIndex(
txid: Sha256,
bh: BlockHeader,
merkleProof: MerkleProof,
depth: number
): boolean {
let last = true
): bigint {
let root = txid
let sum = 0n

for (let i = 0; i < depth; i++) {
const node = merkleProof[i]

if (node.pos != MerklePath.INVALID_NODE) {
// IF LAST ELEMENT:
// - A non-duplicate node cannot ever be on the right.
const isDuplicate = node.hash == root
if (!isDuplicate && node.pos == MerklePath.RIGHT_NODE) {
last = false
if (node.pos == MerklePath.LEFT_NODE) {
// Check if duplicate.
if (root != node.hash) {
sum += lshift(1n, BigInt(i))
}
root = Sha256(hash256(node.hash + root))
} else {
root = Sha256(hash256(root + node.hash))
}

root = Sha256(
node.pos == MerklePath.LEFT_NODE
? hash256(node.hash + root)
: hash256(root + node.hash)
)
}
}

return last && root == bh.merkleRoot
return sum
}

// TODO:
// The function below assumes there cannot be any duplicate nodes on the left-hand side,
// which is false.
//// Calculate a tx's index in a block from its merkle path.
//// Goes from top to bottom, the path basically encodes the index in binary form.
//// left/L means 1, and right/R 0: e.g., (L, R, L) denotes 101 in binary, and 5 in decimal
//@method()
//static txIndex(merkleProof: MerkleProof): bigint {
// let sum = 0n

// // traverse the path from top to bottom
// for (let i = 0; i < MerklePath.DEPTH; i++) {
// const node = merkleProof[Number(MerklePath.DEPTH) - i - 1]

// if (node.pos != MerklePath.INVALID_NODE) {
// sum *= 2n
// if (node.pos == MerklePath.LEFT_NODE) {
// sum++
// }
// }
// }
// return sum
//}

//// Get number of transactions in a block.
//@method()
//static blockTxCount(
// bh: BlockHeader,
// lastTxid: Sha256,
// merkleProof: MerkleProof
//): bigint {
// // Ensure this tx is indeed the last one.
// assert(Blockchain.lastTxInBlock(lastTxid, bh, merkleProof))
// return Blockchain.txIndex(merkleProof) + 1n
//}
// Get number of transactions in a block based using its last tx merkle path.
@method()
static blockTxCount(
lastTxid: Sha256,
merkleProof: MerkleProof,
depth: number
): bigint {
// Ensure this tx is indeed the last one.
assert(Blockchain.isLastTxInBlock(merkleProof, depth))
return Blockchain.txIndex(lastTxid, merkleProof, depth) + 1n
}

// Is block header valid with difficulty meeting target.
@method()
Expand Down
37 changes: 14 additions & 23 deletions tests/contracts/blockchainTest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,8 @@ export class BlockchainTest extends SmartContract {
}

@method()
public testLastTxInBlock(
txid: Sha256,
bh: BlockHeader,
merkleProof: MerkleProof,
res: boolean
) {
assert(Blockchain.lastTxInBlock(txid, bh, merkleProof, 32) == res)
public testLastTxInBlock(merkleProof: MerkleProof, res: boolean) {
assert(Blockchain.isLastTxInBlock(merkleProof, 32) == res)
}

@method()
Expand All @@ -51,21 +46,17 @@ export class BlockchainTest extends SmartContract {
assert(Blockchain.blockHeight(bh, coinbaseTx, merkleProof, 32) == res)
}

//@method()
//public testTxIndex(
// merkleProof: MerkleProof,
// res: bigint
//) {
// assert(Blockchain.txIndex(merkleProof) == res)
//}
@method()
public testTxIndex(txid: Sha256, merkleProof: MerkleProof, res: bigint) {
assert(Blockchain.txIndex(txid, merkleProof, 32) == res)
}

//@method()
//public testBlockTxCount(
// bh: BlockHeader,
// lastTxId: Sha256,
// merkleProof: MerkleProof,
// res: bigint
//) {
// assert(Blockchain.blockTxCount(bh, lastTxId, merkleProof) == res)
//}
@method()
public testBlockTxCount(
lastTxId: Sha256,
merkleProof: MerkleProof,
res: bigint
) {
assert(Blockchain.blockTxCount(lastTxId, merkleProof, 32) == res)
}
}
Loading

0 comments on commit 2dd2980

Please sign in to comment.