Skip to content

Commit

Permalink
photon 0.45.0, add: getValidityProofV0 for custom tree support (#1202)
Browse files Browse the repository at this point in the history
Co-authored-by: swen <swen-code@swens-MacBook-Air-2.local>
  • Loading branch information
SwenSchaeferjohann and swen authored Sep 11, 2024
1 parent 38e4c46 commit 47c1cd7
Show file tree
Hide file tree
Showing 8 changed files with 108 additions and 27 deletions.
2 changes: 1 addition & 1 deletion cli/src/utils/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export const LIGHT_PROVER_PROCESS_NAME = "light-prover";
export const INDEXER_PROCESS_NAME = "photon";
export const FORESTER_PROCESS_NAME = "forester";

export const PHOTON_VERSION = "0.44.0";
export const PHOTON_VERSION = "0.45.0";

export const LIGHT_PROTOCOL_PROGRAMS_DIR_ENV = "LIGHT_PROTOCOL_PROGRAMS_DIR";
export const BASE_PATH = "../../bin/";
5 changes: 2 additions & 3 deletions js/stateless.js/src/actions/create-account.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,8 @@ export async function createAccount(
/// TODO: enforce program-derived
const address = await deriveAddress(seed, addressTree);

/// TODO: pass trees
const proof = await rpc.getValidityProof(undefined, [
bn(address.toBytes()),
const proof = await rpc.getValidityProofV0(undefined, [
{ address: bn(address.toBytes()), tree: addressTree, queue: addressQueue },
]);

const params: NewAddressParams = {
Expand Down
21 changes: 19 additions & 2 deletions js/stateless.js/src/rpc-interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,18 @@ export interface SignatureWithMetadata {
slot: number;
}

export interface HashWithTree {
hash: BN254;
tree: PublicKey;
queue: PublicKey;
}

export interface AddressWithTree {
address: BN254;
tree: PublicKey;
queue: PublicKey;
}

export interface CompressedTransaction {
compressionInfo: {
closedAccounts: {
Expand Down Expand Up @@ -497,9 +509,14 @@ export interface CompressionApiInterface {
newAddresses: BN254[],
): Promise<CompressedProofWithContext>;

getValidityProofV0(
hashes: HashWithTree[],
newAddresses: AddressWithTree[],
): Promise<CompressedProofWithContext>;

getValidityProofAndRpcContext(
hashes: BN254[],
newAddresses: BN254[],
hashes: HashWithTree[],
newAddresses: AddressWithTree[],
): Promise<WithContext<CompressedProofWithContext>>;

getCompressedAccountsByOwner(
Expand Down
73 changes: 58 additions & 15 deletions js/stateless.js/src/rpc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ import {
WithContext,
GetCompressedAccountsByOwnerConfig,
WithCursor,
AddressWithTree,
HashWithTree,
} from './rpc-interface';
import {
MerkleContextWithMerkleProof,
Expand Down Expand Up @@ -1367,15 +1369,52 @@ export class Rpc extends Connection implements CompressionApiInterface {
*/
async getValidityProof(
hashes: BN254[] = [],
newAddresses: BN254[] = [],
newAddresses: BN254[] = []
): Promise<CompressedProofWithContext> {
const { value } = await this.getValidityProofAndRpcContext(
hashes,
newAddresses,
);
const defaultAddressTreePublicKey = defaultTestStateTreeAccounts().addressTree;
const defaultAddressQueuePublicKey = defaultTestStateTreeAccounts().addressQueue;
const defaultStateTreePublicKey = defaultTestStateTreeAccounts().merkleTree;
const defaultStateQueuePublicKey = defaultTestStateTreeAccounts().nullifierQueue;
const formattedHashes = hashes.map(item => {
if (item instanceof BN) {
return { hash: item, tree: defaultStateTreePublicKey, queue: defaultStateQueuePublicKey };
}
return item;
});

const formattedNewAddresses = newAddresses.map(item => {
if (item instanceof BN) {
return { address: item, tree: defaultAddressTreePublicKey, queue: defaultAddressQueuePublicKey };
}
return item;
});

return this.getValidityProofV0(formattedHashes, formattedNewAddresses);
}

/**
* Fetch the latest validity proof for (1) compressed accounts specified by
* an array of account hashes. (2) new unique addresses specified by an
* array of addresses.
*
* Validity proofs prove the presence of compressed accounts in state trees
* and the non-existence of addresses in address trees, respectively. They
* enable verification without recomputing the merkle proof path, thus
* lowering verification and data costs.
*
* @param hashes Array of { hash: BN254, tree: PublicKey, queue: PublicKey }.
* @param newAddresses Array of { address: BN254, tree: PublicKey, queue: PublicKey }.
* @returns validity proof with context
*/
async getValidityProofV0(
hashes: HashWithTree[] = [],
newAddresses: AddressWithTree[] = []
): Promise<CompressedProofWithContext> {
const { value } = await this.getValidityProofAndRpcContext(hashes, newAddresses);
return value;
}
/**

/**
* Fetch the latest validity proof for (1) compressed accounts specified by
* an array of account hashes. (2) new unique addresses specified by an
* array of addresses. Returns with context slot.
Expand All @@ -1386,21 +1425,25 @@ export class Rpc extends Connection implements CompressionApiInterface {
* lowering verification and data costs.
*
* @param hashes Array of BN254 hashes.
* @param newAddresses Array of BN254 new addresses.
* @param newAddresses Array of BN254 new addresses. Optionally specify the
* tree and queue for each address. Default to public
* state tree/queue.
* @returns validity proof with context
*/
async getValidityProofAndRpcContext(
hashes: BN254[] = [],
newAddresses: BN254[] = [],
hashes: HashWithTree[] = [],
newAddresses: AddressWithTree[] = []
): Promise<WithContext<CompressedProofWithContext>> {

const unsafeRes = await rpcRequest(
this.compressionApiEndpoint,
'getValidityProof',
{
hashes: hashes.map(hash => encodeBN254toBase58(hash)),
newAddresses: newAddresses.map(address =>
encodeBN254toBase58(address),
),
hashes: hashes.map(({ hash }) => encodeBN254toBase58(hash)),
newAddressesWithTrees: newAddresses.map(({ address, tree }) => ({
address: encodeBN254toBase58(address),
tree: tree.toBase58(),
})),
},
);

Expand Down Expand Up @@ -1428,8 +1471,8 @@ export class Rpc extends Connection implements CompressionApiInterface {
merkleTrees: result.merkleTrees,
leafIndices: result.leafIndices,
nullifierQueues: [
...hashes.map(() => mockNullifierQueue),
...newAddresses.map(() => mockAddressQueue),
...hashes.map(({ queue }) => queue),
...newAddresses.map(({ queue }) => queue),
],
rootIndices: result.rootIndices,
roots: result.roots,
Expand Down
26 changes: 23 additions & 3 deletions js/stateless.js/src/test-helpers/test-rpc/test-rpc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,10 @@ import { MerkleTree } from '../merkle-tree/merkle-tree';
import { getParsedEvents } from './get-parsed-events';
import { defaultTestStateTreeAccounts } from '../../constants';
import {
AddressWithTree,
CompressedTransaction,
GetCompressedAccountsByOwnerConfig,
HashWithTree,
LatestNonVotingSignatures,
LatestNonVotingSignaturesPaginated,
SignatureWithMetadata,
Expand Down Expand Up @@ -589,11 +591,14 @@ export class TestRpc extends Connection implements CompressionApiInterface {
* {@link getValidityProof} instead.
*/
async getValidityProofAndRpcContext(
hashes: BN254[] = [],
newAddresses: BN254[] = [],
hashes: HashWithTree[] = [],
newAddresses: AddressWithTree[] = [],
): Promise<WithContext<CompressedProofWithContext>> {
if (newAddresses.some(address => !(address instanceof BN))) {
throw new Error('AddressWithTree is not supported in test-rpc');
}
return {
value: await this.getValidityProof(hashes, newAddresses),
value: await this.getValidityProofV0(hashes, newAddresses),
context: { slot: 1 },
};
}
Expand All @@ -615,6 +620,10 @@ export class TestRpc extends Connection implements CompressionApiInterface {
hashes: BN254[] = [],
newAddresses: BN254[] = [],
): Promise<CompressedProofWithContext> {

if (newAddresses.some(address => !(address instanceof BN))) {
throw new Error('AddressWithTree is not supported in test-rpc');
}
let validityProof: CompressedProofWithContext;

if (hashes.length === 0 && newAddresses.length === 0) {
Expand Down Expand Up @@ -737,4 +746,15 @@ export class TestRpc extends Connection implements CompressionApiInterface {

return validityProof;
}

async getValidityProofV0(
hashes: HashWithTree[] = [],
newAddresses: AddressWithTree[] = [],
): Promise<CompressedProofWithContext> {
/// TODO(swen): add support for custom trees
return this.getValidityProof(
hashes.map(hash => hash.hash),
newAddresses.map(address => address.address),
);
}
}
3 changes: 2 additions & 1 deletion js/stateless.js/tests/e2e/compress.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ function txFees(

return totalFee.toNumber();
}

/// TODO: add test case for payer != address
describe('compress', () => {
const { merkleTree } = defaultTestStateTreeAccounts();
Expand All @@ -73,7 +74,7 @@ describe('compress', () => {

it('should create account with address', async () => {
const preCreateAccountsBalance = await rpc.getBalance(payer.publicKey);

await createAccount(
rpc as TestRpc,
payer,
Expand Down
3 changes: 2 additions & 1 deletion js/stateless.js/tests/e2e/rpc-interop.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -641,9 +641,10 @@ describe('rpc-interop', () => {
it('getCompressedAccount with address param should work ', async () => {
const seed = new Uint8Array(randomBytes(32));
const addressTree = defaultTestStateTreeAccounts().addressTree;
const addressQueue = defaultTestStateTreeAccounts().addressQueue;
const address = await deriveAddress(seed, addressTree);

await createAccount(rpc, payer, seed, LightSystemProgram.programId);
await createAccount(rpc, payer, seed, LightSystemProgram.programId, addressTree, addressQueue);

// fetch the owners latest account
const accounts = await rpc.getCompressedAccountsByOwner(
Expand Down
2 changes: 1 addition & 1 deletion scripts/install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ VERSIONS=(
"solana:1.18.22"
"anchor:anchor-v0.29.0"
"jq:jq-1.7.1"
"photon:0.44.0"
"photon:0.45.0"
)

# Architecture-specific suffixes
Expand Down

0 comments on commit 47c1cd7

Please sign in to comment.