Error in Solana Concurrent Merkle Tree: Invalid root recalculated from proof when updating metadata
As a cNFT developer on the Solana blockchain, updating metadata can be a straightforward process. However, many developers are frustrated when they encounter an error related to the computation of a concurrent merkle tree. In this article, we will delve into the issue and provide guidance on how to resolve it.
Error
The error occurs when attempting to update cNFT metadata on the Solana blockchain. The updateMetadata method is called in conjunction with another operation, resulting in an invalid root recalculated from the proof. This can lead to inconsistent state on the network and issues with cNFT functionality.
Here is the reference material for you:
- [Solana API Documentation](
- [cNFT Documentation for Solana](
Code Sample
For demonstration purposes, let’s assume we have a cNFT contract with the following code:
import { Program } from "solana-program";
import { updateMetadata } from "../lib/update-metadata";
async function main() {
// Initialize metadata
const metadata = await getMetadata();
try {
// Update metadata
await updateMetadata(metadata);
} catch (error) {
if (error instance of Error && error.message.includes("Invalid root")) {
// Fix the error by recalculating the root from the proof
const proof = await getProofForUpdate();
const root = await computeMerkleTree(proof);
try {
// Update the metadata using the new root
await updateMetadata(metadata, root);
} catch (error) {
// Handle any errors that occur during the metadata update
console error(error);
}
} else {
throw error;
}
}
}
async function getMetadata() {
// Provide some metadata examples
return [
"
"other metadata information",
];
}
// Helper functions generate proof and compute Merkle tree
function getProofForUpdate() {
// Generate a random proof for metadata update
return new Promise(resolve => setTimeout(() => solve(new Uint8Array(32))), 100);
}
async function computeMerkleTree(proof) {
// Compute Merkle tree from proof
return new Promise(resolve => setTimeout(() => solve(new Uint8Array(256)), 200));
}
main ();
Solution
To solve this problem, we need to recompute the root from the proof only when updating the metadata. This can be achieved by introducing a new variable that tracks whether an update is in progress:
“`sunflower
import { Program } from “solana-program”;
import { updateMetadata } from “../lib/update-metadata”;
class CNTF {
private updateInProgress = false;
private proofIndex = 0;
async getMetadata() {
if (this.updateInProgress) return null; // Update in progress. Do not continue
this.proofIndex++;
const metadata = await getMetadataFromProof();
return metadata;
}
async updateMetadata(metadata) {
if (this.updateInProgress) throw new Error (“Invalid root computed from proof”);
this.updateInProgress = true;
try {
// Update metadata using metadata
await updateMetadata(metadata);
} catch (error) {
if (error instance of Error && error.message.includes(“Invalid root”)) {
// Fix the error by recalculating the root from the proof
const proofIndex = this.proofIndex;
const proofData = await getProofFromIndex(proofIndex);
try {
this.updateInProgress = false; // Reset the update flag
this.
Leave a Reply