Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

enhancement: Initial stateproofs support #629

Merged
merged 12 commits into from
Aug 29, 2022
38 changes: 36 additions & 2 deletions src/client/v2/algod/algod.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,25 +6,27 @@ import AccountApplicationInformation from './accountApplicationInformation';
import Block from './block';
import Compile from './compile';
import Dryrun from './dryrun';
import Genesis from './genesis';
import GetAssetByID from './getAssetByID';
import GetApplicationByID from './getApplicationByID';
import HealthCheck from './healthCheck';
import PendingTransactionInformation from './pendingTransactionInformation';
import PendingTransactions from './pendingTransactions';
import PendingTransactionsByAddress from './pendingTransactionsByAddress';
import Proof from './proof';
import SendRawTransaction from './sendRawTransaction';
import Status from './status';
import StatusAfterBlock from './statusAfterBlock';
import SuggestedParams from './suggestedParams';
import Supply from './supply';
import Versions from './versions';
import Genesis from './genesis';
import Proof from './proof';
import { BaseHTTPClient } from '../../baseHTTPClient';
import {
AlgodTokenHeader,
CustomTokenHeader,
} from '../../urlTokenBaseHTTPClient';
import LightBlockHeaderProof from './lightBlockHeaderProof';
import StateProof from './stateproof';

/**
* Algod client connects an application to the Algorand blockchain. The algod client requires a valid algod REST endpoint IP address and algod token from an Algorand node that is connected to the network you plan to interact with.
Expand Down Expand Up @@ -462,4 +464,36 @@ export default class AlgodClient extends ServiceClient {
getProof(round: number, txID: string) {
return new Proof(this.c, this.intDecoding, round, txID);
}

/**
* Returns a light block header proof for a given block.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

*
* #### Example
* ```typescript
* const round = 11111111;
* const lightBlockHeaderProof = await algodClient.getLightBlockHeaderProof(round).do();
* ```
*
* [Response data schema details](https://developer.algorand.org/docs/rest-apis/algod/v2#get-v2blocksroundlightheaderproof)
* @param round
*/
getLightBlockHeaderProof(round: number) {
return new LightBlockHeaderProof(this.c, this.intDecoding, round);
}

/**
* Returns a state proof for a given block.
*
* #### Example
* ```typescript
* const round = 11111111;
* const stateProof = await algodClient.getStateProof(round).do();
* ```
*
* [Response data schema details](https://developer.algorand.org/docs/rest-apis/algod/v2#get-v2stateproofsround)
* @param round
*/
getStateProof(round: number) {
return new StateProof(this.c, this.intDecoding, round);
}
}
15 changes: 15 additions & 0 deletions src/client/v2/algod/lightBlockHeaderProof.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import JSONRequest from '../jsonrequest';
import HTTPClient from '../../client';
import IntDecoding from '../../../types/intDecoding';

export default class LightBlockHeaderProof extends JSONRequest {
constructor(c: HTTPClient, intDecoding: IntDecoding, private round: number) {
super(c, intDecoding);

this.round = round;
}

path() {
return `/v2/blocks/${this.round}/lightheader/proof`;
}
}
259 changes: 209 additions & 50 deletions src/client/v2/algod/models/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1631,6 +1631,54 @@ export class EvalDeltaKeyValue extends BaseModel {
}
}

/**
* Proof of membership and position of a light block header.
*/
export class LightBlockHeaderProof extends BaseModel {
/**
* The index of the light block header in the vector commitment tree
*/
public index: number | bigint;

/**
* The encoded proof.
*/
public proof: Uint8Array;

/**
* Represents the depth of the tree that is being proven, i.e. the number of edges
* from a leaf to the root.
*/
public treedepth: number | bigint;

/**
* Creates a new `LightBlockHeaderProof` object.
* @param index - The index of the light block header in the vector commitment tree
* @param proof - The encoded proof.
* @param treedepth - Represents the depth of the tree that is being proven, i.e. the number of edges
* from a leaf to the root.
*/
constructor(
index: number | bigint,
proof: string | Uint8Array,
treedepth: number | bigint
) {
super();
this.index = index;
this.proof =
typeof proof === 'string'
? new Uint8Array(Buffer.from(proof, 'base64'))
: proof;
this.treedepth = treedepth;

this.attribute_map = {
index: 'index',
proof: 'proof',
treedepth: 'treedepth',
};
}
}

/**
*
*/
Expand Down Expand Up @@ -2038,80 +2086,112 @@ export class PostTransactionsResponse extends BaseModel {
}

/**
* Proof of transaction in a block.
* Represents a state proof and its corresponding message
*/
export class ProofResponse extends BaseModel {
export class StateProof extends BaseModel {
/**
* Index of the transaction in the block's payset.
* Represents the message that the state proofs are attesting to.
*/
public idx: number | bigint;
public message: StateProofMessage;

/**
* Merkle proof of transaction membership.
* The encoded StateProof for the message.
*/
public proof: Uint8Array;
public stateproof: Uint8Array;

/**
* Hash of SignedTxnInBlock for verifying proof.
* Creates a new `StateProof` object.
* @param message - Represents the message that the state proofs are attesting to.
* @param stateproof - The encoded StateProof for the message.
*/
public stibhash: Uint8Array;
constructor(message: StateProofMessage, stateproof: string | Uint8Array) {
super();
this.message = message;
this.stateproof =
typeof stateproof === 'string'
? new Uint8Array(Buffer.from(stateproof, 'base64'))
: stateproof;

this.attribute_map = {
message: 'Message',
stateproof: 'StateProof',
};
}
}

/**
* Represents the message that the state proofs are attesting to.
*/
export class StateProofMessage extends BaseModel {
/**
* Represents the depth of the tree that is being proven, i.e. the number of edges
* from a leaf to the root.
* The vector commitment root on all light block headers within a state proof
* interval.
*/
public treedepth: number | bigint;
public blockheaderscommitment: Uint8Array;

/**
* The type of hash function used to create the proof, must be one of:
* * sha512_256
* * sha256
* The first round the message attests to.
*/
public hashtype?: string;
public firstattestedround: number | bigint;

/**
* Creates a new `ProofResponse` object.
* @param idx - Index of the transaction in the block's payset.
* @param proof - Merkle proof of transaction membership.
* @param stibhash - Hash of SignedTxnInBlock for verifying proof.
* @param treedepth - Represents the depth of the tree that is being proven, i.e. the number of edges
* from a leaf to the root.
* @param hashtype - The type of hash function used to create the proof, must be one of:
* * sha512_256
* * sha256
* The last round the message attests to.
*/
public lastattestedround: number | bigint;

/**
* An integer value representing the natural log of the proven weight with 16 bits
* of precision. This value would be used to verify the next state proof.
*/
public lnprovenweight: number | bigint;

/**
* The vector commitment root of the top N accounts to sign the next StateProof.
*/
public voterscommitment: Uint8Array;

/**
* Creates a new `StateProofMessage` object.
* @param blockheaderscommitment - The vector commitment root on all light block headers within a state proof
* interval.
* @param firstattestedround - The first round the message attests to.
* @param lastattestedround - The last round the message attests to.
* @param lnprovenweight - An integer value representing the natural log of the proven weight with 16 bits
* of precision. This value would be used to verify the next state proof.
* @param voterscommitment - The vector commitment root of the top N accounts to sign the next StateProof.
*/
constructor({
idx,
proof,
stibhash,
treedepth,
hashtype,
blockheaderscommitment,
firstattestedround,
lastattestedround,
lnprovenweight,
voterscommitment,
}: {
idx: number | bigint;
proof: string | Uint8Array;
stibhash: string | Uint8Array;
treedepth: number | bigint;
hashtype?: string;
blockheaderscommitment: string | Uint8Array;
firstattestedround: number | bigint;
lastattestedround: number | bigint;
lnprovenweight: number | bigint;
voterscommitment: string | Uint8Array;
}) {
super();
this.idx = idx;
this.proof =
typeof proof === 'string'
? new Uint8Array(Buffer.from(proof, 'base64'))
: proof;
this.stibhash =
typeof stibhash === 'string'
? new Uint8Array(Buffer.from(stibhash, 'base64'))
: stibhash;
this.treedepth = treedepth;
this.hashtype = hashtype;
this.blockheaderscommitment =
typeof blockheaderscommitment === 'string'
? new Uint8Array(Buffer.from(blockheaderscommitment, 'base64'))
: blockheaderscommitment;
this.firstattestedround = firstattestedround;
this.lastattestedround = lastattestedround;
this.lnprovenweight = lnprovenweight;
this.voterscommitment =
typeof voterscommitment === 'string'
? new Uint8Array(Buffer.from(voterscommitment, 'base64'))
: voterscommitment;

this.attribute_map = {
idx: 'idx',
proof: 'proof',
stibhash: 'stibhash',
treedepth: 'treedepth',
hashtype: 'hashtype',
blockheaderscommitment: 'BlockHeadersCommitment',
firstattestedround: 'FirstAttestedRound',
lastattestedround: 'LastAttestedRound',
lnprovenweight: 'LnProvenWeight',
voterscommitment: 'VotersCommitment',
};
}
}
Expand Down Expand Up @@ -2317,6 +2397,85 @@ export class TransactionParametersResponse extends BaseModel {
}
}

/**
* Proof of transaction in a block.
*/
export class TransactionProofResponse extends BaseModel {
/**
* Index of the transaction in the block's payset.
*/
public idx: number | bigint;

/**
* Proof of transaction membership.
*/
public proof: Uint8Array;

/**
* Hash of SignedTxnInBlock for verifying proof.
*/
public stibhash: Uint8Array;

/**
* Represents the depth of the tree that is being proven, i.e. the number of edges
* from a leaf to the root.
*/
public treedepth: number | bigint;

/**
* The type of hash function used to create the proof, must be one of:
* * sha512_256
* * sha256
*/
public hashtype?: string;

/**
* Creates a new `TransactionProofResponse` object.
* @param idx - Index of the transaction in the block's payset.
* @param proof - Proof of transaction membership.
* @param stibhash - Hash of SignedTxnInBlock for verifying proof.
* @param treedepth - Represents the depth of the tree that is being proven, i.e. the number of edges
* from a leaf to the root.
* @param hashtype - The type of hash function used to create the proof, must be one of:
* * sha512_256
* * sha256
*/
constructor({
idx,
proof,
stibhash,
treedepth,
hashtype,
}: {
idx: number | bigint;
proof: string | Uint8Array;
stibhash: string | Uint8Array;
treedepth: number | bigint;
hashtype?: string;
}) {
super();
this.idx = idx;
this.proof =
typeof proof === 'string'
? new Uint8Array(Buffer.from(proof, 'base64'))
: proof;
this.stibhash =
typeof stibhash === 'string'
? new Uint8Array(Buffer.from(stibhash, 'base64'))
: stibhash;
this.treedepth = treedepth;
this.hashtype = hashtype;

this.attribute_map = {
idx: 'idx',
proof: 'proof',
stibhash: 'stibhash',
treedepth: 'treedepth',
hashtype: 'hashtype',
};
}
}

/**
* algod version information.
*/
Expand Down
Loading