Cross-program invocation in C

Hi all,

I got stuck calling another program. Here are what I do:
Front-end:

const program1AccountPubKey = PublicKey.createWithSeed(myPubKey, program1Id, seed1);
const createProgram1AccountTx = ...;
sendAndConfirmTransaction(...);

const program2AccountPubKey = PublicKey.createWithSeed(myPubKey, program2Id, seed2);
const createProgram2AccountTx = ...;
sendAndConfirmTransaction(...);

// So far so good here
const program1Instruction = new TransactionInstruction({
  keys: [
    {pubKey: myPubKey, isSigner: true, isWritable: true},
    {pubKey: program1AccountPubKey, isSigner: false, isWritable: true},
    {pubKey: program2AccountPubKey, isSigner: false, isWritable: true},
 ],
 programId: program1Id,
 data
);

// Reports error: Error processing Instruction 0: An account required by the instruction is missing 
sendAndConfirmTransaction(...); 

Program 1:

extern uint64_t entrypoint(const uint8_t *input) {
    SolAccountInfo accounts[3];
    SolParameters params = (SolParameters) {.ka = accounts};

    if (!sol_deserialize(input, &params, SOL_ARRAY_SIZE(accounts))) {
        return ERROR_INVALID_ARGUMENT;
    }

    return process_instruction(&params);
}

uint64_t process_instruction(SolParameters *params) {

    if (params->ka_num < 3) {
        return ERROR_NOT_ENOUGH_ACCOUNT_KEYS;
    }

    if (params->data_len < 1) {
        sol_log_params(params);
        return ERROR_INVALID_ARGUMENT;
    }

    SolAccountInfo *state = &params->ka[1];
    if (!SolPubkey_same(state ->owner, params->program_id)) {
        sol_log("Account does not have the correct program id");
        return ERROR_INCORRECT_PROGRAM_ID;
    }

    SolAccountInfo *payer = &params->ka[0];
    SolAccountInfo *program2State = &params->ka[2];
    
    SolPubkey program2PubKey = {.x = PROGRAM2_PUBKEY};
    if (!SolPubkey_same(&program2PubKey , program2State ->owner)) {
        return ERROR_INCORRECT_PROGRAM_ID;
    }
    sol_log("Calling program2."); // last program log seen.
    SolAccountMeta accounts[] = {{program2State->key, true, false} };
    uint8_t data[1];
    data[0] = 1;
    const SolInstruction instruction = {
            .program_id = program2State->owner,
            .accounts = accounts,
            .account_len = SOL_ARRAY_SIZE(accounts),
            .data = data,
            .data_len = SOL_ARRAY_SIZE(data)
    };
    if (SUCCESS != sol_invoke(&instruction, program2State, 1)) {
         sol_log("Calling program2 failed."); // not seem 
    }
    return SUCCESS:
}

Program 2:

extern uint64_t entrypoint(const uint8_t *input) {
    sol_log("Program 2 entrypoint"); // not seem

    SolAccountInfo accounts[1];
    SolParameters params = (SolParameters) {.ka = accounts};

    if (!sol_deserialize(input, &params, SOL_ARRAY_SIZE(accounts))) {
        return ERROR_INVALID_ARGUMENT;
    }

    return process_instruction(&params);
}
// other codes ommited

Does anyone has idea? Program2 only modify the account data.
I’ve read the example cross-program-invocation.c but I can’t doesn’t know what are other signer seeds used for and for is sol_create_program_address for.

Program resolved by adding public key of the program B and pass it as an keyed account while invoking program B.

1 Like