diff --git a/lib/blockstore/abstract.js b/lib/blockstore/abstract.js index 9c2a31b02..efde2ddf1 100644 --- a/lib/blockstore/abstract.js +++ b/lib/blockstore/abstract.js @@ -298,10 +298,9 @@ class AbstractBatch { } } -AbstractBlockStore.AbstractBatch = AbstractBatch; - /* * Expose */ +AbstractBlockStore.AbstractBatch = AbstractBatch; module.exports = AbstractBlockStore; diff --git a/lib/covenants/view.js b/lib/covenants/view.js index 7302f33e4..462c7a83b 100644 --- a/lib/covenants/view.js +++ b/lib/covenants/view.js @@ -5,11 +5,20 @@ const {BufferMap} = require('buffer-map'); const NameState = require('./namestate'); const NameUndo = require('./undo'); +/** @typedef {import('../types').Hash} Hash */ + class View { constructor() { + /** @type {BufferMap} */ this.names = new BufferMap(); } + /** + * @param {Object} db + * @param {Hash} nameHash + * @returns {NameState} + */ + getNameStateSync(db, nameHash) { assert(db && typeof db.getNameState === 'function'); assert(Buffer.isBuffer(nameHash)); @@ -19,6 +28,7 @@ class View { if (cache) return cache; + /** @type {NameState?} */ const ns = db.getNameState(nameHash); if (!ns) { @@ -33,6 +43,12 @@ class View { return ns; } + /** + * @param {Object} db + * @param {Hash} nameHash + * @returns {Promise} + */ + async getNameState(db, nameHash) { assert(db && typeof db.getNameState === 'function'); assert(Buffer.isBuffer(nameHash)); @@ -42,6 +58,7 @@ class View { if (cache) return cache; + /** @type {NameState?} */ const ns = await db.getNameState(nameHash); if (!ns) { diff --git a/lib/hd/common.js b/lib/hd/common.js index 256dd3259..d5b8482cd 100644 --- a/lib/hd/common.js +++ b/lib/hd/common.js @@ -39,7 +39,7 @@ common.MAX_ENTROPY = 512; /** * LRU cache to avoid deriving keys twice. - * @type {LRU} + * @type {LRU} */ common.cache = new LRU(500); diff --git a/lib/mempool/airdropentry.js b/lib/mempool/airdropentry.js index 2803d37cc..337416e67 100644 --- a/lib/mempool/airdropentry.js +++ b/lib/mempool/airdropentry.js @@ -12,6 +12,11 @@ const policy = require('../protocol/policy'); const util = require('../utils/util'); const Address = require('../primitives/address'); +/** @typedef {import('../types').Amount} AmountValue */ +/** @typedef {import('../types').Rate} Rate */ +/** @typedef {import('../types').BufioWriter} BufioWriter */ +/** @typedef {import('../primitives/airdropproof')} AirdropProof */ + /* * Constants */ @@ -73,7 +78,6 @@ class AirdropEntry extends bio.Struct { /** * Inject properties from airdrop. - * @private * @param {AirdropProof} proof * @param {Number} height */ @@ -99,7 +103,6 @@ class AirdropEntry extends bio.Struct { /** * Create a mempool entry from an airdrop proof. * @param {AirdropProof} proof - * @param {Object} data * @param {Number} height - Entry height. * @returns {AirdropEntry} */ @@ -110,7 +113,7 @@ class AirdropEntry extends bio.Struct { /** * Get fee. - * @returns {Amount} + * @returns {AmountValue} */ getFee() { @@ -160,7 +163,8 @@ class AirdropEntry extends bio.Struct { /** * Serialize entry to a buffer. - * @returns {Buffer} + * @param {BufioWriter} bw + * @returns {BufioWriter} */ write(bw) { @@ -180,9 +184,8 @@ class AirdropEntry extends bio.Struct { /** * Inject properties from serialized data. - * @private - * @param {Buffer} data - * @returns {AirdropEntry} + * @param {bio.BufferReader} br + * @returns {this} */ read(br) { diff --git a/lib/mempool/claimentry.js b/lib/mempool/claimentry.js index ac664191d..1da6d4ef9 100644 --- a/lib/mempool/claimentry.js +++ b/lib/mempool/claimentry.js @@ -13,6 +13,11 @@ const util = require('../utils/util'); const Address = require('../primitives/address'); const rules = require('../covenants/rules'); +/** @typedef {import('../primitives/claim')} Claim */ +/** @typedef {import('../types').Amount} AmountValue */ +/** @typedef {import('../types').Rate} Rate */ +/** @typedef {import('../types').BufioWriter} BufioWriter */ + /* * Constants */ @@ -58,7 +63,6 @@ class ClaimEntry extends bio.Struct { /** * Inject properties from options object. - * @private * @param {Object} options */ @@ -84,7 +88,6 @@ class ClaimEntry extends bio.Struct { /** * Inject properties from claim. - * @private * @param {Claim} claim * @param {Object} data * @param {Number} height @@ -128,7 +131,7 @@ class ClaimEntry extends bio.Struct { /** * Get fee. - * @returns {Amount} + * @returns {AmountValue} */ getFee() { @@ -178,7 +181,8 @@ class ClaimEntry extends bio.Struct { /** * Serialize entry to a buffer. - * @returns {Buffer} + * @param {BufioWriter} bw + * @returns {BufioWriter} */ write(bw) { @@ -204,9 +208,8 @@ class ClaimEntry extends bio.Struct { /** * Inject properties from serialized data. - * @private - * @param {Buffer} data - * @returns {ClaimEntry} + * @param {bio.BufferReader} br + * @returns {this} */ read(br) { diff --git a/lib/mempool/contractstate.js b/lib/mempool/contractstate.js index cf0fca700..cbc2948bc 100644 --- a/lib/mempool/contractstate.js +++ b/lib/mempool/contractstate.js @@ -14,6 +14,10 @@ const CoinView = require('../coins/coinview'); const {types} = rules; const {states} = NameState; +/** @typedef {import('../types').Hash} Hash */ +/** @typedef {import('../protocol/network')} Network */ +/** @typedef {import('../primitives/tx')} TX */ + /* * Constants */ @@ -25,6 +29,11 @@ const EMPTY = Buffer.alloc(0); */ class ContractState { + /** + * @constructor + * @param {Network} network + */ + constructor(network) { assert(network); @@ -35,18 +44,23 @@ class ContractState { this.unique = new BufferSet(); // Reference counter. + /** @type {BufferMap} */ this.refs = new BufferMap(); // Map of nameHash->set-of-txids. + /** @type {BufferMap} */ this.opens = new BufferMap(); // Map of nameHash->set-of-txids. + /** @type {BufferMap} */ this.bids = new BufferMap(); // Map of nameHash->set-of-txids. + /** @type {BufferMap} */ this.reveals = new BufferMap(); // Map of nameHash->set-of-txids. + /** @type {BufferMap} */ this.updates = new BufferMap(); // Current on-chain state @@ -65,24 +79,51 @@ class ContractState { return this; } + /** + * @param {Hash} nameHash + * @returns {Boolean} + */ + hasName(nameHash) { return this.unique.has(nameHash); } + /** + * @param {Hash} nameHash + * @returns {ContractState} + */ + addName(nameHash) { this.unique.add(nameHash); return this; } + /** + * @param {Hash} nameHash + * @returns {ContractState} + */ + removeName(nameHash) { this.unique.delete(nameHash); return this; } + /** + * @param {TX} tx + * @returns {Boolean} + */ + hasNames(tx) { return rules.hasNames(tx, this.unique); } + /** + * @param {BufferMap} map + * @param {Hash} nameHash + * @param {Hash} hash + * @returns {ContractState} + */ + addMap(map, nameHash, hash) { let set = map.get(nameHash); @@ -96,6 +137,13 @@ class ContractState { return this; } + /** + * @param {BufferMap} map + * @param {Hash} nameHash + * @param {Hash} hash + * @returns {ContractState} + */ + removeMap(map, nameHash, hash) { const set = map.get(nameHash); @@ -110,38 +158,91 @@ class ContractState { return this; } + /** + * @param {Hash} nameHash + * @param {Hash} hash + * @returns {ContractState} + */ + addOpen(nameHash, hash) { return this.addMap(this.opens, nameHash, hash); } + /** + * @param {Hash} nameHash + * @param {Hash} hash + * @returns {ContractState} + */ + removeOpen(nameHash, hash) { return this.removeMap(this.opens, nameHash, hash); } + /** + * @param {Hash} nameHash + * @param {Hash} hash + * @returns {ContractState} + */ + addBid(nameHash, hash) { return this.addMap(this.bids, nameHash, hash); } + /** + * @param {Hash} nameHash + * @param {Hash} hash + * @returns {ContractState} + */ + removeBid(nameHash, hash) { return this.removeMap(this.bids, nameHash, hash); } + /** + * @param {Hash} nameHash + * @param {Hash} hash + * @returns {ContractState} + */ + addReveal(nameHash, hash) { return this.addMap(this.reveals, nameHash, hash); } + /** + * @param {Hash} nameHash + * @param {Hash} hash + * @returns {ContractState} + */ + removeReveal(nameHash, hash) { return this.removeMap(this.reveals, nameHash, hash); } + /** + * @param {Hash} nameHash + * @param {Hash} hash + * @returns {ContractState} + */ + addUpdate(nameHash, hash) { return this.addMap(this.updates, nameHash, hash); } + /** + * @param {Hash} nameHash + * @param {Hash} hash + * @returns {ContractState} + */ + removeUpdate(nameHash, hash) { return this.removeMap(this.updates, nameHash, hash); } + /** + * @param {Hash} nameHash + * @returns {ContractState} + */ + reference(nameHash) { let count = this.refs.get(nameHash); @@ -155,6 +256,11 @@ class ContractState { return this; } + /** + * @param {Hash} nameHash + * @returns {ContractState} + */ + dereference(nameHash) { let count = this.refs.get(nameHash); @@ -176,6 +282,12 @@ class ContractState { return this; } + /** + * @param {TX} tx + * @param {CoinView} view + * @returns {ContractState} + */ + track(tx, view) { const hash = tx.hash(); @@ -233,6 +345,11 @@ class ContractState { return this; } + /** + * @param {TX} tx + * @returns {ContractState} + */ + untrack(tx) { const hash = tx.hash(); const names = new BufferSet(); @@ -270,6 +387,11 @@ class ContractState { return this; } + /** + * @param {CoinView} view + * @returns {ContractState} + */ + merge(view) { for (const [nameHash, ns] of view.names) { if (!this.refs.has(nameHash)) @@ -284,6 +406,13 @@ class ContractState { return this; } + /** + * @param {BufferMap} map + * @param {Hash} nameHash + * @param {BufferSet} items + * @returns {ContractState} + */ + toSet(map, nameHash, items) { const hashes = map.get(nameHash); @@ -296,24 +425,54 @@ class ContractState { return this; } + /** + * @param {Hash} nameHash + * @param {BufferSet} items + * @returns {ContractState} + */ + handleExpired(nameHash, items) { this.toSet(this.updates, nameHash, items); this.toSet(this.reveals, nameHash, items); return this; } + /** + * @param {Hash} nameHash + * @param {BufferSet} items + * @returns {ContractState} + */ + handleOpen(nameHash, items) { return this.toSet(this.updates, nameHash, items); } + /** + * @param {Hash} nameHash + * @param {BufferSet} items + * @returns {ContractState} + */ + handleBidding(nameHash, items) { return this.toSet(this.opens, nameHash, items); } + /** + * @param {Hash} nameHash + * @param {BufferSet} items + * @returns {ContractState} + */ + handleReveal(nameHash, items) { return this.toSet(this.bids, nameHash, items); } + /** + * @param {Hash} nameHash + * @param {BufferSet} items + * @returns {ContractState} + */ + handleClosed(nameHash, items) { return this.toSet(this.reveals, nameHash, items); } @@ -322,7 +481,7 @@ class ContractState { * Invalidate transactions in the mempool. * @param {Number} height * @param {Boolean} hardened - * @returns {BufferSet} - list of invalidated tx hashes. + * @returns {BufferSet} - list of invalidated tx hashes. */ invalidate(height, hardened) { diff --git a/lib/mempool/mempoolentry.js b/lib/mempool/mempoolentry.js index e6b102e8d..08043fc1c 100644 --- a/lib/mempool/mempoolentry.js +++ b/lib/mempool/mempoolentry.js @@ -11,6 +11,13 @@ const policy = require('../protocol/policy'); const util = require('../utils/util'); const TX = require('../primitives/tx'); +/** @typedef {import('../types').Hash} Hash */ +/** @typedef {import('../types').HexHash} HexHash */ +/** @typedef {import('../types').Amount} AmountValue */ +/** @typedef {import('../types').Rate} Rate */ +/** @typedef {import('../types').BufioWriter} BufioWriter */ +/** @typedef {import('../coins/coinview')} CoinView */ + /** * Mempool Entry * Represents a mempool entry. @@ -26,12 +33,12 @@ class MempoolEntry extends bio.Struct { /** * Create a mempool entry. * @constructor - * @param {Object} options + * @param {Object} [options] * @param {TX} options.tx - Transaction in mempool. * @param {Number} options.height - Entry height. * @param {Number} options.priority - Entry priority. * @param {Number} options.time - Entry time. - * @param {Amount} options.value - Value of on-chain coins. + * @param {AmountValue} options.value - Value of on-chain coins. */ constructor(options) { @@ -57,7 +64,6 @@ class MempoolEntry extends bio.Struct { /** * Inject properties from options object. - * @private * @param {Object} options */ @@ -80,8 +86,8 @@ class MempoolEntry extends bio.Struct { /** * Inject properties from transaction. - * @private * @param {TX} tx + * @param {CoinView} view * @param {Number} height */ @@ -123,6 +129,7 @@ class MempoolEntry extends bio.Struct { /** * Create a mempool entry from a TX. * @param {TX} tx + * @param {CoinView} view * @param {Number} height - Entry height. * @returns {MempoolEntry} */ @@ -171,7 +178,7 @@ class MempoolEntry extends bio.Struct { /** * Get fee. - * @returns {Amount} + * @returns {AmountValue} */ getFee() { @@ -180,7 +187,7 @@ class MempoolEntry extends bio.Struct { /** * Get delta fee. - * @returns {Amount} + * @returns {AmountValue} */ getDeltaFee() { @@ -284,7 +291,8 @@ class MempoolEntry extends bio.Struct { /** * Serialize entry to a buffer. - * @returns {Buffer} + * @param {BufioWriter} bw + * @returns {BufioWriter} */ write(bw) { @@ -303,9 +311,8 @@ class MempoolEntry extends bio.Struct { /** * Inject properties from serialized data. - * @private - * @param {Buffer} data - * @returns {MempoolEntry} + * @param {bio.BufferReader} br + * @returns {this} */ read(br) { diff --git a/lib/mining/common.js b/lib/mining/common.js index dcdc1bd28..27128563d 100644 --- a/lib/mining/common.js +++ b/lib/mining/common.js @@ -34,8 +34,8 @@ const B0 = 0x1; common.swap32 = function swap32(data) { for (let i = 0; i < data.length; i += 4) { - const field = data.readUInt32LE(i, true); - data.writeUInt32BE(field, i, true); + const field = data.readUInt32LE(i); + data.writeUInt32BE(field, i); } return data; @@ -53,20 +53,20 @@ common.double256 = function double256(target) { assert(target.length === 32); - hi = target.readUInt32BE(0, true); - lo = target.readUInt32BE(4, true); + hi = target.readUInt32BE(0); + lo = target.readUInt32BE(4); n += (hi * 0x100000000 + lo) * B192; - hi = target.readUInt32BE(8, true); - lo = target.readUInt32BE(12, true); + hi = target.readUInt32BE(8); + lo = target.readUInt32BE(12); n += (hi * 0x100000000 + lo) * B128; - hi = target.readUInt32BE(16, true); - lo = target.readUInt32BE(20, true); + hi = target.readUInt32BE(16); + lo = target.readUInt32BE(20); n += (hi * 0x100000000 + lo) * B64; - hi = target.readUInt32BE(24, true); - lo = target.readUInt32BE(28, true); + hi = target.readUInt32BE(24); + lo = target.readUInt32BE(28); n += (hi * 0x100000000 + lo) * B0; return n; @@ -113,7 +113,7 @@ common.getTarget = function getTarget(bits) { /** * Get bits from target. * @param {Buffer} data - * @returns {Buffer} + * @returns {Number} */ common.getBits = function getBits(data) { diff --git a/lib/mining/template.js b/lib/mining/template.js index 9540ee486..41dfa7d91 100644 --- a/lib/mining/template.js +++ b/lib/mining/template.js @@ -23,6 +23,14 @@ const CoinView = require('../coins/coinview'); const rules = require('../covenants/rules'); const common = require('./common'); +/** @typedef {import('../types').Amount} AmountValue */ +/** @typedef {import('../types').Hash} Hash */ +/** @typedef {import('../primitives/claim')} Claim */ +/** @typedef {import('../primitives/airdropproof')} AirdropProof */ +/** @typedef {import('../mempool/airdropentry')} AirdropEntry */ +/** @typedef {import('../mempool/claimentry')} ClaimEntry */ +/** @typedef {import('../mempool/mempoolentry')} MempoolEntry */ + /* * Constants */ @@ -38,7 +46,7 @@ class BlockTemplate { /** * Create a block template. * @constructor - * @param {Object} options + * @param {Object} [options] */ constructor(options) { @@ -63,7 +71,7 @@ class BlockTemplate { this.witnessRoot = consensus.ZERO_HASH; this.treeRoot = consensus.ZERO_HASH; this.reservedRoot = consensus.ZERO_HASH; - this.coinbase = DUMMY; + this.coinbase = new TX(); this.items = []; this.claims = []; this.airdrops = []; @@ -74,7 +82,6 @@ class BlockTemplate { /** * Inject properties from options. - * @private * @param {Object} options * @returns {BlockTemplate} */ @@ -233,7 +240,7 @@ class BlockTemplate { /** * Calculate the block reward. - * @returns {Amount} + * @returns {AmountValue} */ getReward() { @@ -364,9 +371,10 @@ class BlockTemplate { /** * Create raw block header with given parameters. - * @param {Buffer} extraNonce - * @param {Number} time * @param {Number} nonce + * @param {Number} time + * @param {Buffer} extraNonce + * @param {Buffer} mask * @returns {Buffer} */ @@ -390,10 +398,10 @@ class BlockTemplate { /** * Calculate proof with given parameters. - * @param {Number} nonce1 - * @param {Number} nonce2 + * @param {Number} nonce * @param {Number} time - * @param {Buffer} nonce + * @param {Buffer} extraNonce + * @param {Buffer} mask * @returns {BlockProof} */ @@ -486,6 +494,7 @@ class BlockTemplate { * Add a transaction to the template. * @param {TX} tx * @param {CoinView} view + * @returns {Boolean} */ addTX(tx, view) { @@ -533,7 +542,8 @@ class BlockTemplate { * Add a transaction to the template * (less verification than addTX). * @param {TX} tx - * @param {CoinView?} view + * @param {CoinView?} [view] + * @returns {Boolean} */ pushTX(tx, view) { @@ -566,6 +576,7 @@ class BlockTemplate { * Add a claim to the template. * @param {Claim} claim * @param {Object} data + * @returns {Boolean} */ addClaim(claim, data) { @@ -582,6 +593,7 @@ class BlockTemplate { /** * Add a claim to the template. * @param {AirdropProof} proof + * @returns {Boolean} */ addAirdrop(proof) { @@ -801,9 +813,9 @@ class BlockAirdrop { } /** - * Instantiate block entry from mempool entry. - * @param {ClaimEntry} entry - * @returns {BlockClaim} + * Instantiate block airdrop from mempool airdropentry. + * @param {AirdropEntry} entry + * @returns {BlockAirdrop} */ static fromEntry(entry) { @@ -837,15 +849,27 @@ class BlockProof { this.mask = consensus.ZERO_HASH; } + /** + * @returns {Hash} + */ + hash() { return this.powHash(); } + /** + * @returns {Hash} + */ + shareHash() { const hdr = Headers.fromMiner(this.hdr); return hdr.shareHash(); } + /** + * @returns {Hash} + */ + powHash() { const hash = this.shareHash(); @@ -855,10 +879,20 @@ class BlockProof { return hash; } - verify(target, network) { + /** + * @param {Buffer} target + * @returns {Boolean} + */ + + verify(target) { return this.powHash().compare(target) <= 0; } + /** + * Calculate the target difficulty. + * @returns {Number} + */ + getDifficulty() { return common.getDifficulty(this.powHash()); } diff --git a/lib/primitives/abstractblock.js b/lib/primitives/abstractblock.js index 0d6f8bbcc..fdba21184 100644 --- a/lib/primitives/abstractblock.js +++ b/lib/primitives/abstractblock.js @@ -344,7 +344,7 @@ class AbstractBlock extends bio.Struct { /** * Calculate share hash. - * @returns {Buffer} + * @returns {Hash} */ shareHash() { diff --git a/lib/primitives/claim.js b/lib/primitives/claim.js index 37dab00f5..6b4d4ed4a 100644 --- a/lib/primitives/claim.js +++ b/lib/primitives/claim.js @@ -20,6 +20,10 @@ const Output = require('./output'); const {OwnershipProof} = Ownership; /** @typedef {import('../types').Hash} Hash */ +/** @typedef {import('../types').Amount} AmountValue */ +/** @typedef {import('../types').Rate} Rate */ +/** @typedef {import('../types').BufioWriter} BufioWriter */ +/** @typedef {import('../protocol/network')} Network */ /* * Constants @@ -43,6 +47,10 @@ class Claim extends bio.Struct { this._data = null; } + /** + * @returns {this} + */ + refresh() { this._hash = null; this._data = null; @@ -60,10 +68,19 @@ class Claim extends bio.Struct { return this._hash; } + /** + * @returns {String} + */ + hashHex() { return this.hash().toString('hex'); } + /** + * @param {Network} network + * @returns {Object} + */ + getData(network) { if (!this._data) { const proof = this.getProof(); @@ -82,16 +99,30 @@ class Claim extends bio.Struct { return this._data; } + /** + * @returns {Number} + */ + getSize() { return 2 + this.blob.length; } + /** + * @param {BufioWriter} bw + * @returns {BufioWriter} + */ + write(bw) { bw.writeU16(this.blob.length); bw.writeBytes(this.blob); return bw; } + /** + * @param {Buffer} data + * @returns {this} + */ + decode(data) { const br = bio.read(data); @@ -106,6 +137,11 @@ class Claim extends bio.Struct { return this; } + /** + * @param {bio.BufferReader} br + * @returns {this} + */ + read(br) { const size = br.readU16(); @@ -117,19 +153,37 @@ class Claim extends bio.Struct { return this; } + /** + * @returns {InvItem} + */ + toInv() { return new InvItem(InvItem.types.CLAIM, this.hash()); } + /** + * @returns {Number} + */ + getWeight() { return this.getSize(); } + /** + * @returns {Number} + */ + getVirtualSize() { const scale = consensus.WITNESS_SCALE_FACTOR; return (this.getWeight() + scale - 1) / scale | 0; } + /** + * @param {Number} [size] + * @param {Number} [rate] + * @returns {AmountValue} + */ + getMinFee(size, rate) { if (size == null) size = this.getVirtualSize(); @@ -137,12 +191,23 @@ class Claim extends bio.Struct { return policy.getMinFee(size, rate); } + /** + * @param {Network} [network] + * @returns {AmountValue} + */ + getFee(network) { const data = this.getData(network); assert(data); return data.fee; } + /** + * @param {Number} [size] + * @param {Network} [network] + * @returns {Rate} + */ + getRate(size, network) { const fee = this.getFee(network); @@ -152,6 +217,12 @@ class Claim extends bio.Struct { return policy.getRate(size, fee); } + /** + * @param {Network} network + * @param {Number} height + * @returns {TX} + */ + toTX(network, height) { const data = this.getData(network); assert(data); @@ -193,6 +264,10 @@ class Claim extends bio.Struct { return tx; } + /** + * @returns {OwnershipProof} + */ + getProof() { try { return this.toProof(); @@ -201,35 +276,70 @@ class Claim extends bio.Struct { } } + /** + * @returns {OwnershipProof} + */ + toProof() { return OwnershipProof.decode(this.blob); } + /** + * @returns {Buffer} + */ + toBlob() { return this.blob; } + /** + * @returns {Object} + */ + getJSON() { const proof = this.getProof(); return proof.toJSON(); } + /** + * Inject properties from blob. + * @param {Buffer} blob + * @returns {this} + */ + fromBlob(blob) { assert(Buffer.isBuffer(blob)); this.blob = blob; return this; } + /** + * @param {OwnershipProof} proof + * @returns {this} + */ + fromProof(proof) { assert(proof instanceof OwnershipProof); this.blob = proof.encode(); return this; } + /** + * Instantiate claim from raw proof. + * @param {Buffer} blob + * @returns {Claim} + */ + static fromBlob(blob) { return new this().fromBlob(blob); } + /** + * Instantiate claim from proof. + * @param {OwnershipProof} proof + * @returns {Claim} + */ + static fromProof(proof) { return new this().fromProof(proof); }