2

I am following the soldev tutorial. In the tutorial about Cross Program Instruction is this piece of code:

 invoke_signed(        
  &system_instruction::create_account(
            initializer.key,  //if this is the account that pays for the transaction
            token_mint.key,   //then where is his key-pair given
            rent_lamports,
            82,          
            token_program.key,),
  &[initializer.clone(),token_mint.clone(),system_program.clone(),],
  &[&[b"token_mint", &[mint_bump]]],)?; 
   
  msg!("Created token mint account");

My question is, the initializer is the one who pays the transaction, but where is its private key? I initially thought in the accounts array, their metadata is given its private key for signing but the accountmeta struct doesn't have it.

The full code can be found here: https://soldev.app/course/cpi Section: Demo

2 Answers 2

3

Private keys are never exposed publicly, unless there's some sort of hack. In most cryptographic systems, private keys are used to generate signatures, and the signatures can be verified through some other algorithm.

On Solana, the private key is used to generate a signature for a transaction, and the runtime verifies that the signature is valid for the accompanying private key. If the signature is valid, and an instruction declares the account as a signer, the runtime will mark that account as a "signer" during processing, and this "signer" bit can be propagated down.

So in your example, initializer must sign the transaction to be marked as a signer. The system_instruction::create_account instruction requires initializer to be a signer, so when the runtime sees that the account is already marked as a signer, it allows the instruction to go forward.

1

The account provided to the instruction as the initializer would have be a signer, otherwise the transaction would fail. A program's instruction logic does not include private keys for accounts.

Here is the reference for how to build a transaction which includes that instruction (https://github.com/Unboxed-Software/solana-movie-token-client):

import { initializeKeypair } from "./initializeKeypair"
import * as web3 from "@solana/web3.js"
import * as splToken from "@solana/spl-token"

const PROGRAM_ID = new web3.PublicKey(
  "HYkps3qJ9Uqq2NNTwU3VhpG2EaJgg1L4qsyXVnAvtYNJ"
)

async function initializeProgramTokenMint(
  connection: web3.Connection,
  signer: web3.Keypair,
  programId: web3.PublicKey
): Promise<string> {
  const [tokenMint] = await web3.PublicKey.findProgramAddress(
    [Buffer.from("token_mint")],
    PROGRAM_ID
  )
  const [tokenAuth] = await web3.PublicKey.findProgramAddress(
    [Buffer.from("token_auth")],
    PROGRAM_ID
  )

  splToken.createInitializeMintInstruction
  const tx = new web3.Transaction()
  const ix = new web3.TransactionInstruction({
    keys: [
      {
        pubkey: signer.publicKey,
        isSigner: true,
        isWritable: false,
      },
      {
        pubkey: tokenMint,
        isSigner: false,
        isWritable: true,
      },
      {
        pubkey: tokenAuth,
        isSigner: false,
        isWritable: false,
      },
      {
        pubkey: web3.SystemProgram.programId,
        isSigner: false,
        isWritable: false,
      },
      {
        pubkey: splToken.TOKEN_PROGRAM_ID,
        isSigner: false,
        isWritable: false,
      },
      {
        pubkey: web3.SYSVAR_RENT_PUBKEY,
        isSigner: false,
        isWritable: false,
      },
    ],
    programId: PROGRAM_ID,
    data: Buffer.from([3]),
  })

  tx.add(ix)
  return await web3.sendAndConfirmTransaction(connection, tx, [signer])
}

async function main() {
  const connection = new web3.Connection("http://localhost:8899") //web3.clusterApiUrl("devnet"))
  const signer = await initializeKeypair(connection)

  const txid = await initializeProgramTokenMint(connection, signer, PROGRAM_ID)
  console.log(
    `Transaction submitted: https://explorer.solana.com/tx/${txid}?cluster=devnet`
  )
}

main()
  .then(() => {
    console.log("Finished successfully")
    process.exit(0)
  })
  .catch((error) => {
    console.log(error)
    process.exit(1)
  })

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.