小试牛刀-区块链Solana多签账户

本文涉及的产品
应用实时监控服务-应用监控,每月50GB免费额度
任务调度 XXL-JOB 版免费试用,400 元额度,开发版规格
Serverless 应用引擎免费试用套餐包,4320000 CU,有效期3个月
简介: 在 Solana 区块链中,多签账户(Multisig Account)是一种智能合约账户,允许多个签名者共同管理和控制账户上的资产或操作。这种机制增强了账户的安全性和灵活性,特别适用于需要多个权限共同批准的操作场景,如资产管理、资金转移、或项目治理。

目录

1.什么是多签账户

2.多签账户的特点

2.1 多个签名者

2.2 最小签名要求

2.3 常见应用场景

3.多签账户实现

3.1 账户的创建

3.1.1 创建新账户

3.1.2 获取创建和初始账户事务

3.1.3 账户的签名

3.2 代币转移操作


Welcome to Code Block's blog

本篇文章主要介绍了

[小试牛刀-Solana多签账户]

❤博主广交技术好友,喜欢文章的可以关注一下❤

1.什么是多签账户

       在 Solana 区块链中,多签账户(Multisig Account)是一种智能合约账户,允许多个签名者共同管理和控制账户上的资产或操作。这种机制增强了账户的安全性和灵活性,特别适用于需要多个权限共同批准的操作场景,如资产管理、资金转移、或项目治理。                              

2.多签账户的特点

2.1 多个签名者

       多签账户通常指定多个签名者(即一组公钥),这些签名者可以是个人账户、智能合约账户或其他实体。

       每个签名者都有权批准账户的操作,但只有在达到预定义的签名数量时,操作才会生效。

2.2 最小签名要求

       多签账户设置了最小签名数(M)的要求,即在 N 个签名者中,至少需要 M 个签名才能执行账户的任何操作。

       这种机制通常被称为 M-of-N 签名方案,例如 2-of-3 签名意味着需要三个人中的两个人签署才能批准操作。

2.3 常见应用场景

       项目治理:在去中心化自治组织(DAO)中,使用多签账户来管理资金或项目决策。

       资产托管:增加资金管理的安全性,避免单一账户被攻击或失控。

       合作项目:需要多个合作方共同控制账户,确保所有操作都有多个利益相关方的同意。

3.多签账户实现

3.1 账户的创建

3.1.1 创建新账户

       首先创建一个新的账户,作为要创建多签账户,同时需要其公钥和私钥参与签名,实现代码如下:

function generateSolanaWalletNacl(): { publicKey: string, privateKey: string } {
    const keyPair = nacl.sign.keyPair();
    const publicKeyBase58 = bs58.encode(Buffer.from(keyPair.publicKey)).toString();
    const privateKeyBase58 = bs58.encode(Buffer.from(keyPair.secretKey)).toString();
    return { publicKey: publicKeyBase58, privateKey: privateKeyBase58 };
}

image.gif

3.1.2 获取创建和初始账户事务

       这里multisigPubKey为上面创建的新账户的公钥,payer我们使用另一个账户(已有或创建)的公钥,保证payer中存在可以创建账户的费用,然后获取创建和初始化事务,代码如下:

export async function createMultisigAccount(payer:string,multisigPubKey:PublicKey): Promise<Transaction> {
    const fromPubkey =new PublicKey(payer);
    //签名者列表
    const signers = [fromPubkey,multisigPubKey];
    // 获取多签账户所需的最小余额以免租金
    const lamports = await getMinimumBalanceForRentExemptMultisig(connection);
    // 创建多签账户的指令
    const createAccountInstruction = SystemProgram.createAccount({
        //这个账户的拥有者
        fromPubkey: fromPubkey,
        //多签账户公钥
        newAccountPubkey: multisigPubKey,
        //免租金最小金额
        lamports,
        space: 355, // 多签账户的空间大小
        //属于的程序地址,这里使用SPL程序
        programId: TOKEN_PROGRAM_ID,
    });
    // 初始化多签账户的指令
    const initializeMultisigInstruction = createInitializeMultisigInstruction(
        //多签账户
        multisigPubKey,
        //签名者列表
        signers,
        //最小签名数量,这里是2
        requiredSigners,
        //属于的程序地址,这里使用SPL程序
        TOKEN_PROGRAM_ID
    );
    //创建transaction并添加创建和初始化指令
    const transaction = new Transaction()
        .add(createAccountInstruction,initializeMultisigInstruction);
    //最近的区块hash
    transaction.recentBlockhash = (await connection.getLatestBlockhash()).blockhash;
    //付费者为拥有者
    transaction.feePayer=fromPubkey;
    console.log("签名者:"+signers)
    console.log("multisigPubKey:"+multisigPubKey)
    return transaction;
}

image.gif

3.1.3 账户的签名

       账户创建时需要签名者列表中的用户分别对transaction进行签名,(是对同一transaction进行签名),如果是拥有者公私钥在本地,可以将公私钥生成Keypair,可使用以下方式签名:

const signer1=Keypair.generate()
const signer2=Keypair.generate()
//签名者1和签名者2 的keypair
transaction.sign(signer1,signer2)

image.gif

       但若是外部签名,如walletconnect连接的钱包用户作为签名者,则需要使用以下方式进行签名(重点):

首先,获取本地公私钥的签名,注意这里并没有对transaction进行签名,只是获取签名:

export async function getLocalSign(transaction:Transaction,signer:Keypair){
    const signature = nacl.sign.detached(transaction.serializeMessage(), signer.secretKey);
    return signature;
}

image.gif

然后,walletconnet用户连接钱包对创建和初始化账户事务签名后,会获取到一个signature,将这个signature和本地公私钥获取的signature添加到transaction中,代码如下:

//钱包签名
    const result =await sendWcTransaction(signClient,session,transaction);
    //本地签名
    const signature = nacl.sign.detached(transaction.serializeMessage(), bs58.decode(privateKey));
    transaction.addSignature(
        transaction.feePayer,
        //这里返回的是字符串,所以需要转换
        Buffer.from(bs58.decode(result.signature))
    )
    //<>!
    transaction.addSignature(
        multisigPubKey,
        //本地获取的是uint8array,无需转换
        Buffer.from(signature)
    )

image.gif

为保证签名的有效性,需要先验证签名,验证方式如下:

//验证签名
    const valid = transaction.verifySignatures();
    if (!valid){
        //验证未通过则不进行操作,或打印
        return ;
    }

image.gif

验证通过后,就可以通过以下代码将要进行的创建事务提交到链上:

export async function sendTransaction(transaction:Transaction){
    try{
        const txId =await connection.sendRawTransaction(transaction.serialize())
        return txId;
    }catch(error){
        console.error('Exception occurred:', error);
        return 'error';
    }
}

image.gif

链上截图:

image.gif 编辑可以看到这里创建并初始化了一个Multisig账户,即多签账户,并且Signers有两个地址,这样就完成了多签账户的创建.              

3.2 代币转移操作

       多签账户操作的转移和创建类似,同样需要两个或多个账户对transaction进行签名,获取transaction返回的[transaction,senderKeypair]分别是事务和本地的keyPair,方便后续签名使用,代码如下:

export async function getMultisigTransferTransaction(
    ownerPublicKey:string,
    senderPublicKey: string,
    privateKey: string,
    drawPublicKey: string,
    tokenAmount: number,
    drawData: string
): Promise<[Transaction,Keypair]> {
    const ownerPubKey = new PublicKey(ownerPublicKey);
    const senderPubkey = new PublicKey(senderPublicKey);
    const drawPubkey = new PublicKey(drawPublicKey);
    const tokenMintAddress = BOGGY_TOKEN_MINT;
    
    const senderKeypair = Keypair.fromSecretKey(Uint8Array.from(bs58.decode(privateKey)));
    try {
        const sourceTokenAccount = await getAssociatedTokenAddress(tokenMintAddress,senderPubkey);
        const destTokenAccount = await getAssociatedTokenAddress(tokenMintAddress,drawPubkey);
        const transferInstruction = createTransferInstruction(
            sourceTokenAccount,
            destTokenAccount,
            senderPubkey,
            tokenAmount * 1e9,
            [senderPubkey,ownerPubKey],
            TOKEN_PROGRAM_ID
        );
        // 构造 Memo 指令
        const memoInstruction = new TransactionInstruction({
            keys: [
            { pubkey: ownerPubKey,  isSigner: true , isWritable:false },
            { pubkey: senderPubkey, isSigner: true, isWritable: false }
            ],
            programId: MEMO_PROGRAM_ID,
            data: Buffer.from(drawData,'utf-8')
        });
        // 创建 compute unit price 指令,提高交易速度
        const computeUnitPriceInstruction = ComputeBudgetProgram.setComputeUnitPrice({
            microLamports: 7500,
        });
        const computeUnitLimitInstruction=ComputeBudgetProgram.setComputeUnitLimit({
            units:200000
        })
        const transaction = new Transaction().add(computeUnitPriceInstruction,computeUnitLimitInstruction,transferInstruction,memoInstruction);
        transaction.recentBlockhash = (await connection.getLatestBlockhash()).blockhash;
        transaction.feePayer = ownerPubKey;
        return [transaction,senderKeypair];
    } catch (error) {
        console.error('Exception occurred:', error);
    }
}

image.gif

签名和发送的步骤和创建时签名是一样的,这里就不重复写了.

区块链内容感兴趣可以查看我的专栏:小试牛刀-区块链

感谢您的关注和收藏!!!!!!

image.gif 编辑

目录
相关文章
|
2月前
|
Python
小试牛刀-Python生成solana Wallet公私钥
在使用Python开发solana应用过程中,需要生成solana Wallet公私钥,以实现后续应用操作.这里将Python生成方法进行整理,方便日后的查阅,也能帮助到实现相关功能的朋友。
61 5
|
2月前
|
JSON 前端开发 JavaScript
小试牛刀-区块链代币锁仓(Web页面)
本篇文章是的后续,记录前端页面的开发过程,分享前端页面代码,加深对前端页面理解,同时希望能帮到需要实现相关功能的朋友。
31 1
|
存储 NoSQL Java
Spring Boot统计一个Bean中方法的调用次数
Spring Boot统计一个Bean中方法的调用次数
274 1
|
2月前
|
存储 Java API
小试牛刀-SpringBoot集成SOL链
java工程师:如何在java/springboot中使用solana区块链呢?不用担心,现在solanaj来了!
63 1
后端返回base64格式数据转excel格式文件并下载
后端返回base64格式数据转excel格式文件并下载
475 0
|
2月前
|
机器学习/深度学习 算法 Java
Java实现林火蔓延路径算法
记录正在进行的森林防火项目中林火蔓延功能,本篇文章可以较好的实现森林防火蔓延,但还存在很多不足,如:很多参数只能使用默认值,所以蔓延范围仅供参考。(如果底层设备获取的数据充足,那当我没说)。注:因林火蔓延涉及因素太多,如静可燃物载量、矿质阻尼系数等存在估值,所以得出的结果仅供参考。
36 4
|
2月前
|
存储 JavaScript 区块链
小试牛刀-walletconnect二维码及交互
最近在使用walletconnect协议和typescript语言实现相关交互功能,在此对从walletconnet协议二维码生成、连接后发送交易事务、签名事务、签名任意信息的处理进行记录,加深对walletconnect的理解,熟悉对其组件的使用,同时希望帮助到有实现相关功能的朋友。
79 1
|
2月前
|
存储 Rust IDE
小试牛刀-Solana合约账户详解
开发语言上,Solana合约使用Rust为主要开发语言,其次是Solana合约并不像其它链那样将数据直接存到合约里,而是使用了更加独立的账户来代币转移和存储数据。按功能可以分为以下账户
77 0
|
2月前
|
存储 前端开发 测试技术
小试牛刀-区块链代币锁仓合约实战
记录一下自己在开发代币合约中的过程,加深自己对合约功能的理解,在后续的学习过程中可以进行资料查阅,以及帮助有这方面开发要求或想学习的朋友进行更方便的入门。
61 1
|
2月前
|
API 区块链
小试牛刀-SOL链swap程序
本篇文章是为了记录自己通过jupiter swap Api接口实现简单的自动化的swap交换程序的过程,记录相关步骤方便查阅,同时希望可以帮助到有实现相关功能的朋友.
47 1

热门文章

最新文章