Skip to content

Commit

Permalink
Project canopy (solana-labs#118)
Browse files Browse the repository at this point in the history
* Initial implementation of project canopy (lots of magic numbers, no comments, no tests) WIP

* Finalized canopy changes and fixed a number of bugs in concurrent merkle tree lib

* revert indexer to main

* Don't worry guys, I added some comments

* Support up to 2^30 tree size
  • Loading branch information
jarry-xiao authored Jun 22, 2022
1 parent 0e3a1e8 commit 7ceaddd
Show file tree
Hide file tree
Showing 7 changed files with 600 additions and 237 deletions.
4 changes: 2 additions & 2 deletions contracts/programs/bubblegum/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ use {
gummyroll::{program::Gummyroll, Node},
crate::error::BubblegumError,
crate::utils::{append_leaf,
insert_or_append_leaf,
replace_leaf,
get_asset_id,
cmp_bytes,
Expand Down Expand Up @@ -570,14 +569,15 @@ pub mod bubblegum {
}?;
let merkle_slab = ctx.accounts.merkle_slab.to_account_info();
emit!(voucher.leaf_schema.to_event());
insert_or_append_leaf(
replace_leaf(
&merkle_slab.key(),
*ctx.bumps.get("authority").unwrap(),
&ctx.accounts.gummyroll_program.to_account_info(),
&ctx.accounts.authority.to_account_info(),
&ctx.accounts.merkle_slab.to_account_info(),
ctx.remaining_accounts,
root,
[0; 32],
voucher.leaf_schema.to_node(),
voucher.index,
)
Expand Down
25 changes: 0 additions & 25 deletions contracts/programs/bubblegum/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,31 +58,6 @@ pub fn append_leaf<'info>(
gummyroll::cpi::append(cpi_ctx, leaf_node)
}

pub fn insert_or_append_leaf<'info>(
seed: &Pubkey,
bump: u8,
gummyroll_program: &AccountInfo<'info>,
authority: &AccountInfo<'info>,
merkle_roll: &AccountInfo<'info>,
remaining_accounts: &[AccountInfo<'info>],
root_node: Node,
leaf: Node,
index: u32,
) -> Result<()> {
let seeds = &[seed.as_ref(), &[bump]];
let authority_pda_signer = &[&seeds[..]];
let cpi_ctx = CpiContext::new_with_signer(
gummyroll_program.clone(),
gummyroll::cpi::accounts::Modify {
authority: authority.clone(),
merkle_roll: merkle_roll.clone(),
},
authority_pda_signer,
)
.with_remaining_accounts(remaining_accounts.to_vec());
gummyroll::cpi::insert_or_append(cpi_ctx, root_node, leaf, index)
}

pub fn cmp_pubkeys(a: &Pubkey, b: &Pubkey) -> bool {
sol_memcmp(a.as_ref(), b.as_ref(), PUBKEY_BYTES) == 0
}
Expand Down
4 changes: 2 additions & 2 deletions contracts/programs/gummyroll/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ pub enum GummyrollError {
ZeroCopyError,
#[msg("An unsupported max depth or max buffer size constant was provided")]
MerkleRollConstantsError,
#[msg("Expected a different byte length for the merkle roll")]
MerkleRollByteLengthMismatch,
#[msg("Expected a different byte length for the merkle roll canopy")]
CanopyLengthMismatch,
}

impl From<&CMTError> for GummyrollError {
Expand Down
303 changes: 225 additions & 78 deletions contracts/programs/gummyroll/src/lib.rs

Large diffs are not rendered by default.

9 changes: 7 additions & 2 deletions contracts/sdk/gummyroll/accounts/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -143,13 +143,18 @@ export function decodeMerkleRoll(buffer: Buffer): OnChainMerkleRoll {

export function getMerkleRollAccountSize(
maxDepth: number,
maxBufferSize: number
maxBufferSize: number,
canopyDepth?: number
): number {
let headerSize = 8 + 32 + 32;
let changeLogSize = (maxDepth * 32 + 32 + 4 + 4) * maxBufferSize;
let rightMostPathSize = maxDepth * 32 + 32 + 4 + 4;
let merkleRollSize = 8 + 8 + 16 + changeLogSize + rightMostPathSize;
return merkleRollSize + headerSize;
let canopySize = 0;
if (canopyDepth) {
canopySize = ((1 << canopyDepth + 1) - 2) * 32
}
return merkleRollSize + headerSize + canopySize;
}

export async function assertOnChainMerkleRollProperties(
Expand Down
34 changes: 23 additions & 11 deletions contracts/sdk/indexer/smokeTest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ async function main() {
await BubblegumCtx.provider.connection.confirmTransaction(
await BubblegumCtx.provider.connection.requestAirdrop(
payer.publicKey,
1e10
2e10
),
"confirmed"
);
Expand Down Expand Up @@ -76,10 +76,16 @@ async function main() {
);
}

let maxDepth = 20;
let maxSize = 1024;
let maxDepth = 30;
let maxSize = 512;
let canopyDepth = 14;
const merkleRollKeypair = Keypair.generate();
const requiredSpace = getMerkleRollAccountSize(maxDepth, maxSize);
console.log(merkleRollKeypair.publicKey.toBase58());
const requiredSpace = getMerkleRollAccountSize(
maxDepth,
maxSize,
canopyDepth
);
const allocAccountIx = SystemProgram.createAccount({
fromPubkey: payer.publicKey,
newAccountPubkey: merkleRollKeypair.publicKey,
Expand All @@ -95,6 +101,7 @@ async function main() {
[merkleRollKeypair.publicKey.toBuffer()],
BubblegumCtx.programId
);
console.log(authority.toBase58());
let createTreeIx = createCreateTreeInstruction(
{
treeCreator: payer.publicKey,
Expand Down Expand Up @@ -167,6 +174,7 @@ async function main() {
);
const assets = await response.json();
if (assets.length === 0) {
console.log("No assets found");
continue;
}
let k = Math.floor(Math.random() * assets.length);
Expand All @@ -179,17 +187,21 @@ async function main() {
console.log(proof);
continue;
}
const proofNodes: Array<AccountMeta> = proof.proofNodes.map((key) => {
return {
pubkey: new PublicKey(key),
isWritable: false,
isSigner: false,
};
});
const proofNodes: Array<AccountMeta> = proof.proofNodes
.map((key) => {
return {
pubkey: new PublicKey(key),
isWritable: false,
isSigner: false,
};
})
.slice(0, maxDepth - canopyDepth);
let [merkleAuthority] = await PublicKey.findProgramAddress(
[bs58.decode(assets[k].treeId)],
BubblegumCtx.programId
);
console.log(assets[k].treeId);
console.log(merkleAuthority.toBase58());
let replaceIx = createTransferInstruction(
{
owner: wallets[i].publicKey,
Expand Down
Loading

0 comments on commit 7ceaddd

Please sign in to comment.