js-sdk icon indicating copy to clipboard operation
js-sdk copied to clipboard

litContracts.addPermittedAction fails for certain IPFS IDs

Open ranile opened this issue 1 year ago • 2 comments

Is there an existing issue for this?

  • [X] I have searched the existing issues

SDK version

@lit-protocol/[email protected] @lit-protocol/[email protected]

Lit Network

datil-test

Description of the bug/issue

When addPermittedAction is called with some IPFS CIDs, it fails with the following error:

/Users/me/code/lit-custom-auth/node_modules/@ethersproject/basex/src.ts/index.ts:112
                throw new Error("Non-base" + this.base + " character");
                      ^
Error: Non-base58 character
    at BaseX.decode (/Users/me/code/lit-custom-auth/node_modules/@ethersproject/basex/src.ts/index.ts:112:23)
    at Object.getBytesFromMultihash (/Users/me/code/lit-custom-auth/packages/contracts-sdk/src/lib/contracts-sdk.ts:1710:43)
    at LitContracts.addPermittedAction (/Users/me/code/lit-custom-auth/packages/contracts-sdk/src/lib/contracts-sdk.ts:1495:36)
    at main (file:///Users/me/code/lit-custom-auth/apps/backend/src/main.ts:137:56)
    at processTicksAndRejections (node:internal/process/task_queues:95:5)
    at file:///Users/me/code/lit-custom-auth/apps/backend/src/main.ts:145:1

Severity of the bug

N/A

Steps To Reproduce

The following code will result in the error:

export const litActionCode = `(async () => {
  const tokenId = await Lit.Actions.pubkeyToTokenId({ publicKey: pkpPublicKey });
  const permittedAuthMethods = await Lit.Actions.getPermittedAuthMethods({ tokenId });
  const isPermitted = permittedAuthMethods.some((permittedAuthMethod) => {
    if (permittedAuthMethod["auth_method_type"] === "0x15f85" &&
        permittedAuthMethod["id"] === customAuthMethod.authMethodId) {
      return true;
    }
    return false;
  });
  LitActions.setResponse({ response: isPermitted ? "true" : "false" });
})();`;
const SELECTED_LIT_NETWORK = LIT_NETWORK.DatilTest

const litNodeClient = new LitNodeClientNodeJs({
  alertWhenUnauthorized: false,
  litNetwork: SELECTED_LIT_NETWORK,
  debug: true
});
await litNodeClient.connect()

const ethersWallet = new ethers.Wallet(
  ETHEREUM_PRIVATE_KEY,
  new ethers.providers.JsonRpcProvider(LIT_RPC.CHRONICLE_YELLOWSTONE)
);

const litContracts = new LitContracts({
  signer: ethersWallet,
  network: SELECTED_LIT_NETWORK,
  debug: false
});
await litContracts.connect();

const stringToCidV0 = async (input: string) => {
  const bytes = new TextEncoder().encode(input)

  const fs = unixfs({ blockstore: new BlackHoleBlockstore() })
  const cid = await fs.addBytes(bytes, { cidVersion: 0 })
  console.log('!!cid', cid); // !!cid CID(bafkreih5onejzpifwy7j3gna37z7i4hi35x4svml4dbilsucaeifi4o5ba)
  return cid
}

async function main() {
  const { pkp } = await litContracts.pkpNftContractUtils.write.mint();

  const authMethodAddReciept = await litContracts.addPermittedAuthMethod({
    pkpTokenId: pkp.tokenId,
    authMethodType: customAuthMethod.authMethodType,
    authMethodId: customAuthMethod.authMethodId,
    authMethodScopes: [AUTH_METHOD_SCOPE.SignAnything],
  });

  const ipfsCid = await stringToCidV0(litActionCode);
  const permittedActionAddReciept = await litContracts.addPermittedAction({
    ipfsId: ipfsCid.toString(),
    pkpTokenId: pkp.tokenId,
    authMethodScopes: [AUTH_METHOD_SCOPE.SignAnything],
  });
  console.log('done????');
}

await main()

Link to code

No response

Anything else?

This is workaroundable (at least for aforementioned lit actions code) by using an ancient library that's used in the examples as well (ipfs-only-hash). The lit actions code is taken from the custom-auth example

ranile avatar Jan 13 '25 14:01 ranile

addPermittedAction tries to decode CID as base58:

https://github.com/LIT-Protocol/js-sdk/blob/412264bb37ec586785d389fc9a9416f422b91c7f/packages/contracts-sdk/src/lib/contracts-sdk.ts#L1495

https://github.com/LIT-Protocol/js-sdk/blob/412264bb37ec586785d389fc9a9416f422b91c7f/packages/contracts-sdk/src/lib/contracts-sdk.ts#L1709-L1713

This is wrong: Only v0 CIDs are guaranteed base58 (which explains why the ipfs-only-hash library works). V1 CIDs may be base58 but as shown in this issue, this would cause problems:

// this snippet errors

// litActionCode is same as one from "steps to reproduce"
const ipfsCid = await stringToCidV0(litActionCode);
ethers.utils.base58.decode(ipfsCid.toString())

However, this is sucessful:

const code = `(async () => { return LitActions.setResponse({ response: "true" }) })()`;
const ipfsCid = await stringToCidV0(code); // !!cid CID(bafkreifo6c37kt36n7xx27nvpt7mkiqb5ocdxvn62abcdfcnvwdfad3pfe)
const base58 = ethers.utils.base58.decode(ipfsCid.toString());
console.log('!!base58', base58.length); // !!base58 44

ranile avatar Jan 13 '25 14:01 ranile

multiformats library can be used to properly implement getBytesFromMultihash function. CID class from this library provides a way to get the CID as bytes

ranile avatar Jan 13 '25 14:01 ranile