Ripple 多重签名账户
多重签名账户允许多个签名者共同控制一个账户,提供更高的安全性和灵活性。
🚀 快速开始
环境准备
npm install ripple-lib
基本设置
const RippleAPI = require('ripple-lib').RippleAPI;
// 创建 API 实例
const api = new RippleAPI({
server: 'wss://s.altnet.rippletest.net/', // 测试网
// server: 'wss://s1.ripple.com/', // 主网
});
📝 多重签名账户流程
1. 连接网络
async function connectToNetwork() {
try {
await api.connect();
console.log('Connected to Ripple network');
} catch (error) {
console.error('Connection failed:', error);
}
}
2. 查询账户信息
async function getAccountInfo(address) {
try {
const account = await api.getAccountInfo(address);
console.log('Account info:', account);
return account;
} catch (error) {
console.error('Failed to get account info:', error);
}
}
3. 创建多重签名列表
async function createSignerList(accountAddress, signerEntries, quorum) {
try {
const preparedTx = await api.prepareTransaction(
{
Flags: 0,
TransactionType: 'SignerListSet',
Account: accountAddress,
Fee: '10000',
SignerQuorum: quorum,
SignerEntries: signerEntries,
}
);
console.log('Signer list transaction prepared:', preparedTx);
return preparedTx;
} catch (error) {
console.error('Failed to prepare signer list transaction:', error);
}
}
4. 签名和提交
async function signAndSubmit(preparedTx, secret) {
try {
// 签名交易
const signed = api.sign(preparedTx.txJSON, secret);
console.log('Transaction signed');
console.log('Transaction ID:', signed.id);
// 提交交易
const result = await api.submit(signed.signedTransaction);
console.log('Transaction submitted');
console.log('Result code:', result.resultCode);
console.log('Result message:', result.resultMessage);
return result;
} catch (error) {
console.error('Signing and submission failed:', error);
}
}
🔄 完整多重签名账户示例
基本多重签名设置
const from_address = 'rfXgErjK96k59evDnC22zX7vRo2hYaSiqc';
const secret = 'ssHAaRfvdDsF62da3dpDHgxHSnw4d';
async function setupMultisigAccount() {
try {
// 1. 连接网络
await api.connect();
// 2. 查询账户信息
const account = await getAccountInfo(from_address);
console.log('Account balance:', account.xrpBalance, 'XRP');
// 3. 定义签名者列表
const signerEntries = [
{
SignerEntry: {
Account: 'r3Q3D8nsyu2nJKFsagHfYdMp8H1VEHd3ps',
SignerWeight: 2, // 权重为 2
},
},
{
SignerEntry: {
Account: 'rhiWpgj8ai3QxegWAe3ZpHk6iionnbtAz1',
SignerWeight: 1, // 权重为 1
},
},
{
SignerEntry: {
Account: 'r3DtjVnBbAf63zryETCjx8NG2j3ewNcJ9g',
SignerWeight: 1, // 权重为 1
},
},
];
// 4. 创建多重签名列表
const preparedTx = await createSignerList(
from_address,
signerEntries,
3 // 需要总权重 3 才能执行交易
);
// 5. 签名和提交
const result = await signAndSubmit(preparedTx, secret);
// 6. 断开连接
await api.disconnect();
return result;
} catch (error) {
console.error('Multisig setup failed:', error);
await api.disconnect();
}
}
⚙️ 高级多重签名配置
动态签名者管理
class MultisigManager {
constructor(accountAddress, api) {
this.accountAddress = accountAddress;
this.api = api;
this.signers = new Map();
}
// 添加签名者
addSigner(signerAddress, weight) {
this.signers.set(signerAddress, {
address: signerAddress,
weight: weight,
addedAt: new Date(),
});
}
// 移除签名者
removeSigner(signerAddress) {
this.signers.delete(signerAddress);
}
// 更新签名者权重
updateSignerWeight(signerAddress, newWeight) {
if (this.signers.has(signerAddress)) {
this.signers.get(signerAddress).weight = newWeight;
}
}
// 生成签名者列表
generateSignerEntries() {
return Array.from(this.signers.values()).map(signer => ({
SignerEntry: {
Account: signer.address,
SignerWeight: signer.weight,
},
}));
}
// 计算所需权重
calculateRequiredQuorum() {
let totalWeight = 0;
for (const signer of this.signers.values()) {
totalWeight += signer.weight;
}
return Math.ceil(totalWeight * 0.6); // 需要 60% 的权重
}
}
多重签名策略配置
function configureMultisigStrategy(strategy) {
const strategies = {
// 2-of-3 策略
'2-of-3': {
signerEntries: [
{ SignerEntry: { Account: 'signer1', SignerWeight: 1 } },
{ SignerEntry: { Account: 'signer2', SignerWeight: 1 } },
{ SignerEntry: { Account: 'signer3', SignerWeight: 1 } },
],
quorum: 2,
},
// 3-of-5 策略
'3-of-5': {
signerEntries: [
{ SignerEntry: { Account: 'signer1', SignerWeight: 1 } },
{ SignerEntry: { Account: 'signer2', SignerWeight: 1 } },
{ SignerEntry: { Account: 'signer3', SignerWeight: 1 } },
{ SignerEntry: { Account: 'signer4', SignerWeight: 1 } },
{ SignerEntry: { Account: 'signer5', SignerWeight: 1 } },
],
quorum: 3,
},
// 加权策略
'weighted': {
signerEntries: [
{ SignerEntry: { Account: 'admin', SignerWeight: 3 } },
{ SignerEntry: { Account: 'manager', SignerWeight: 2 } },
{ SignerEntry: { Account: 'user', SignerWeight: 1 } },
],
quorum: 4, // 需要 admin + manager 或 admin + user + user
},
};
return strategies[strategy] || strategies['2-of-3'];
}
🔍 多重签名账户查询
查询签名者列表
async function getSignerList(accountAddress) {
try {
const account = await api.getAccountInfo(accountAddress);
if (account.signers) {
console.log('Signer list found:', account.signers);
return account.signers;
} else {
console.log('No signer list configured');
return null;
}
} catch (error) {
console.error('Failed to get signer list:', error);
}
}
查询多重签名状态
async function getMultisigStatus(accountAddress) {
try {
const account = await api.getAccountInfo(accountAddress);
const status = {
hasSignerList: !!account.signers,
signerCount: account.signers ? account.signers.length : 0,
quorum: account.signers ? account.signers.SignerQuorum : 0,
totalWeight: 0,
isMultisigEnabled: false,
};
if (account.signers) {
for (const signer of account.signers.SignerEntries) {
status.totalWeight += signer.SignerEntry.SignerWeight;
}
status.isMultisigEnabled = status.totalWeight >= status.quorum;
}
console.log('Multisig status:', status);
return status;
} catch (error) {
console.error('Failed to get multisig status:', error);
}
}
🚨 错误处理
多重签名特定错误
function handleMultisigError(error) {
if (error.data && error.data.error_code) {
switch (error.data.error_code) {
case 'temBAD_QUORUM':
console.error('Invalid quorum value');
break;
case 'temBAD_SIGNATURE':
console.error('Invalid signature');
break;
case 'temINSUFFICIENT_WEIGHT':
console.error('Insufficient signer weight');
break;
case 'temMALFORMED':
console.error('Malformed transaction');
break;
default:
console.error('Unknown multisig error:', error.data.error_code);
}
} else {
console.error('Network error:', error.message);
}
}
验证多重签名配置
function validateMultisigConfig(signerEntries, quorum) {
try {
// 1. 验证签名者数量
if (signerEntries.length < 1 || signerEntries.length > 8) {
throw new Error('Signer count must be between 1 and 8');
}
// 2. 验证权重值
let totalWeight = 0;
for (const entry of signerEntries) {
const weight = entry.SignerEntry.SignerWeight;
if (weight < 1 || weight > 65535) {
throw new Error('Signer weight must be between 1 and 65535');
}
totalWeight += weight;
}
// 3. 验证权重阈值
if (quorum < 1 || quorum > totalWeight) {
throw new Error('Quorum must be between 1 and total weight');
}
// 4. 验证地址格式
for (const entry of signerEntries) {
const address = entry.SignerEntry.Account;
if (!/^r[1-9A-HJ-NP-Za-km-z]{25,34}$/.test(address)) {
throw new Error(`Invalid address format: ${address}`);
}
}
console.log('Multisig configuration validated');
return true;
} catch (error) {
console.error('Validation failed:', error.message);
return false;
}
}
📊 多重签名分析
权重分析工具
class MultisigAnalyzer {
constructor(signerEntries, quorum) {
this.signers = signerEntries;
this.quorum = quorum;
}
// 计算总权重
getTotalWeight() {
return this.signers.reduce((total, entry) => {
return total + entry.SignerEntry.SignerWeight;
}, 0);
}
// 计算权重分布
getWeightDistribution() {
const distribution = {};
for (const entry of this.signers) {
const weight = entry.SignerEntry.SignerWeight;
distribution[weight] = (distribution[weight] || 0) + 1;
}
return distribution;
}
// 分析可能的签名组合
getPossibleCombinations() {
const combinations = [];
const totalWeight = this.getTotalWeight();
// 生成所有可能的签名者组合
for (let i = 1; i <= this.signers.length; i++) {
const combs = this.getCombinations(this.signers, i);
for (const comb of combs) {
const weight = comb.reduce((sum, entry) => {
return sum + entry.SignerEntry.SignerWeight;
}, 0);
if (weight >= this.quorum) {
combinations.push({
signers: comb,
weight: weight,
efficiency: weight / this.quorum,
});
}
}
}
return combinations.sort((a, b) => a.efficiency - b.efficiency);
}
// 辅助函数:生成组合
getCombinations(arr, size) {
if (size === 1) return arr.map(item => [item]);
const combinations = [];
for (let i = 0; i <= arr.length - size; i++) {
const head = arr[i];
const tailCombinations = this.getCombinations(arr.slice(i + 1), size - 1);
for (const tailComb of tailCombinations) {
combinations.push([head, ...tailComb]);
}
}
return combinations;
}
}
🔐 安全最佳实践
多重签名安全配置
function configureSecureMultisig() {
return {
// 1. 使用多个不同的签名者
minSigners: 3,
maxSigners: 5,
// 2. 合理的权重分配
weightStrategy: 'balanced', // balanced, hierarchical, democratic
// 3. 定期轮换签名者
rotationPeriod: 90, // 天
// 4. 备份和恢复策略
backupSigners: 2,
// 5. 紧急访问控制
emergencyAccess: {
enabled: true,
timeout: 24 * 60 * 60 * 1000, // 24小时
},
};
}
私钥管理
class SecureKeyManager {
constructor() {
this.keys = new Map();
this.encryptionKey = null;
}
// 加密存储私钥
storeEncryptedKey(address, encryptedKey) {
this.keys.set(address, {
encrypted: encryptedKey,
storedAt: new Date(),
});
}
// 获取加密的私钥
getEncryptedKey(address) {
return this.keys.get(address)?.encrypted;
}
// 清除私钥
clearKey(address) {
this.keys.delete(address);
}
// 设置加密密钥
setEncryptionKey(key) {
this.encryptionKey = key;
}
}
📱 移动端支持
移动端多重签名
class MobileMultisigClient {
constructor() {
this.api = null;
this.offlineMode = false;
}
// 配置移动端 API
configureMobileAPI() {
return {
timeout: 15000,
retries: 2,
compression: true,
mobileOptimized: true,
};
}
// 离线多重签名
async createOfflineMultisig(accountAddress, signerEntries, quorum) {
try {
// 创建离线交易
const preparedTx = await this.prepareOfflineSignerList(
accountAddress,
signerEntries,
quorum
);
return {
preparedTx,
offline: true,
timestamp: new Date().toISOString(),
};
} catch (error) {
console.error('Offline multisig creation failed:', error);
}
}
}
📚 最佳实践
- 签名者选择: 选择可信的签名者,避免单点故障
- 权重分配: 合理分配权重,确保安全性和可用性
- 阈值设置: 设置合适的权重阈值,平衡安全性和便利性
- 定期审查: 定期审查和更新多重签名配置
- 备份策略: 实现多重签名账户的备份和恢复策略
- 安全存储: 安全存储所有签名者的私钥