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

news2025/3/1 3:24:13

目录

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 };
}

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;
}

3.1.3 账户的签名

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

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

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

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

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

然后,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)
    )

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

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

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

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';
    }
}

链上截图:

可以看到这里创建并初始化了一个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);
    }
}

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

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

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2040210.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

第八节AWK报告生成器(1)

第八节AWK报告生成器 一,AWK简介 其名称得自于它的创始人阿尔佛雷德•艾侯(Alfred Aho)、彼得•温伯格(Peter Weinberger) 和布莱恩柯林(Brian Kernighan)姓氏的首个字母 AWK是一个文本处理工具&#xff0c;Linux及Unix环境中现有的功能最强大的数据处理引擎之一 现在默认li…

「C++系列」输入/输出

文章目录 一、输入/输出1. 包含iostream库2. 使用std命名空间3. 输出到控制台4. 从控制台读取输入5. 注意事项 二、库头文件三、标准输出流&#xff08;cout&#xff09;1. 基本用法2. 格式化输出3. 缓冲4. 错误处理5. 注意事项 四、标准输入流&#xff08;cin&#xff09;1. 基…

X-Recon:一款针对Web安全的XSS安全扫描检测工具

关于X-Recon X-Recon是一款功能强大的Web安全扫描与检测工具&#xff0c;该工具能够帮助广大研究人员识别网页端输入数据&#xff0c;并执行XSS扫描任务。 功能介绍 1、子域名发现&#xff1a;检索目标网站的相关子域名并将其整合到白名单中。这些子域名可在抓取过程中使用&am…

重启人生计划-积蓄星火

&#x1f973;&#x1f973;&#x1f973; 茫茫人海千千万万&#xff0c;感谢这一刻你看到了我的文章&#xff0c;感谢观赏&#xff0c;大家好呀&#xff0c;我是最爱吃鱼罐头&#xff0c;大家可以叫鱼罐头呦~&#x1f973;&#x1f973;&#x1f973; 如果你觉得这个【重启人生…

MySQL数据分析进阶(十二)设计数据库——PART4

&#xff1b;※食用指南&#xff1a;文章内容为‘CodeWithMosh’SQL进阶教程系列学习笔记&#xff0c;笔记整理比较粗糙&#xff0c;主要目的自存为主&#xff0c;记录完整的学习过程。&#xff08;图片超级多&#xff0c;慎看&#xff01;&#xff09; 【中字】SQL进阶教程 |…

基于SpringBoot+VUE的员工绩效考核管理系统(源码+文档+部署)

主要内容&#xff1a;Java项目、Python项目、前端项目、PHP、ASP.NET、人工智能与大数据、单片机开发、物联网设计与开发设计、简历模板、学习资料、面试题库、技术互助、就业指导等 业务范围&#xff1a;免费功能设计、开题报告、任务书、中期检查PPT、系统功能实现、代码编写…

二级分发域名-子比比

二级分发域名全开源链接 二级分发域名

大数据技术——实战项目:广告数仓(第四部分)

目录 第7章 数据仓库环境准备 7.1 数据仓库运行环境 7.1.1 Hive环境搭建 7.1.2 Yarn环境配置 7.2 数据仓库开发环境 第8章 广告数仓ODS层 8.1 广告信息表 8.2 推广平台表 8.3 产品表 8.4 广告投放表 8.5 日志服务器列表 8.6 广告监测日志表 8.7 数据装载脚本 第7章…

C语言【自定义类型——枚举与联合】详细!!

目录 1、枚举 1.0、什么是枚举 1.1、枚举类型的优点 2、联合体&#xff08;共用体&#xff09; 2.0、什么是联合体 2.1、联合体的特点 2.2、联合体大小的计算 2.2.0、联合体节省空间例子 2.3、联合小练习 1、枚举 1.0、什么是枚举 枚举&#xff0c;顾名思义&#…

打造编程学习的“知识宝库”:高效笔记记录与整理指南

如何高效记录并整理编程学习笔记&#xff1f; 在编程学习的海洋中&#xff0c;高效的笔记记录和整理方法就像一张珍贵的航海图&#xff0c;能够帮助我们在浩瀚的知识中找到方向。如何建立一个既能快速记录又易于回顾的笔记系统&#xff1f;如何在繁忙的学习中保持笔记的条理性…

MySQL的字符集配置

MySQL的字符集配置 创建database创建表插入数据查看字符集配置查看字符集的比较规则关于字符集的配置修改字符集总结 创建database create database dbtest1; show databases;use dbtest1;创建表 create table employees(id int,name varchar(15));插入数据 insert into empl…

二分查找专题——基础二分查找

一、题目解析 二、算法分析 找到数组的中心值与target比较&#xff0c;如果中心值大于target则证明target有可能在数组的左边&#xff08;还有一种情况是不存在&#xff09;&#xff0c;反之在数组的右边。重新设置左右边界&#xff0c;折半数组的长度&#xff0c;如此反复&am…

50kg双电多旋翼大载重无人机技术详解

随着无人机技术的飞速发展&#xff0c;大载重无人机因其在物流运输、应急救援、农业植保、环境监测等领域的广泛应用而备受关注。本文将深入解析一款设计承载量达到50kg级别的双电多旋翼大载重无人机&#xff0c;从机体结构设计、动力系统、飞行控制系统、载重挂载系统、能源管…

docker 部署 遇到的一些问题

1. nacos 部署问题 1.1 问题 springboot 服务器启动失败 AnnotationNacosPropertySourceBuilder - There is no content for NacosPropertySource from dataId[rsa.yaml] , groupId[DEFAULT_GROUP] , properties[{accessKey${nacos.access-key:}, clusterName${nacos.cluster…

宝塔面板如何修改域名和网站名

目录 前言修改域名修改网站名 前言 BT宝塔面板是一款安全高效的服务器运维平台&#xff0c;windows和Linux系统都可以使用&#xff0c;安装也简单&#xff0c;相信很多开发者都在用它。 但当我们创建的网站需要更换新的域名&#xff0c;面板中的网站名官方却没有给修改的地方&…

sql语句优化(mysql select语句)-索引方式

1、上图是mysql user表的一小部分数据,一共有: 100万条数据 2、假如现在需要查询name列的某一条数据&#xff08;name‘user3’&#xff09; 3、下图是查询优化器评估的最佳方案&#xff0c;索引我删除了还走索引&#xff0c;还他呀的在&#xff0c;奇怪&#xff0c;就先不研究…

89. UE5 RPG 实现伤害 冷却 消耗技能描述

在上一篇文章里&#xff0c;我们能够通过富文本显示多种格式的文字&#xff0c;并显示技能描述。在这一篇文章里&#xff0c;我们继续优化技能描述&#xff0c;将技能说需要显示的内容显示出来。 实现火球术的基础描述 首先&#xff0c;我们现实现火球术的基础描述&#xff0…

kettle将Excel数据导入oracle

Excel数据导入Oracle示例 Kettle将Excel数据导入Oracle过程记录如下&#xff1a; 3、编辑转换 &#xff08;1&#xff09;Excel输入控件 双击Excel输入&#xff0c;重命名控件名称get_data&#xff0c;在文件选项卡浏览选择Excel文件&#xff08;若不能识别Excel文件&#…

关系,条件和逻辑操作符详解

1关系操作符 C 语言用于比较的表达式&#xff0c;称为 “关系表达式”&#xff08;relational expression&#xff09;&#xff0c;里面使用的运算符就称 为“关系运算符”&#xff08;relational operator&#xff09;&#xff0c;主要有下面6个。 • > 大于运算符 • &…

C++之模版初阶

目录 前言 1.泛型编程 2.函数模版 2.1函数模版概念 2.2函数模版格式 2.3函数模版的原理 2.4函数模版的实例化 2.5模版参数的匹配原则 3.类模版 3.1类模版的定义格式 3.2类模版的实例化 结束语 前言 前面我们学习了C的类与对象和内存管理&#xff0c;接下来我们继续学习…