• Home
  • ビットコインのマルチシグアドレスをNode.jsで作成して送信

ビットコインのマルチシグアドレスをNode.jsで作成して送信

Bitcoin マルチシグアドレスの作成から署名、送信までをまとめる。

確認環境:BitcoinCore(0.18.0)、npm(6.9.0)、nvm(v8.12.0)

マルチシグアドレスの作成

1. プライベートキーの作成(PrivateKey)

bitcore-lib を用いてランダムにプライベートキーを作成する。(2つ以上必要数作成する。)

var bitcore = require('bitcore-lib');
var network = 'livenet';
var privateKey = new bitcore.PrivateKey();
console.log(privateKey.toString());

64文字のプライベートキーがランダムに生成される。

2. パブリックキーの作成(privateKey.toPublicKey)

bitcore-lib を用いてプライベートキーをパブリックキーに変換する。

var bitcore = require('bitcore-lib');
var privkey = process.argv[2];
var privateKey = new bitcore.PrivateKey(privkey);
var publicKey = privateKey.toPublicKey();
console.log(publicKey.toString());

66文字のパブリックキーが生成される。

3. マルチシグアドレスの作成(createmultisig)

JSON-RPC を用いてマルチシグアドレスを作成する。

createmultisig required/*必要署名数*/ ["public key",...]
$ curl --user root --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "createmultisig" , "params": [2, '[\"03a8795069c5f6233838c9996a00f9e974056a6661bdb29cd6c9e62a47d239cff4\",\"033d9b042212eeab0dc4ffbf4e4c3a525a0cf61a5b4266d5f0721fdbb815b72644\"]'] }'  -H 'content-type: text/plain;' http://127.0.0.1:8332/

トランザクションへの署名

bitcore-lib を用いてトランザクションに署名する。

require('dotenv').config();

const BN = require('bignumber.js');
BN.set({ ROUNDING_MODE: BN.ROUND_DOWN, DECIMAL_PLACES: 8});

const bitcore = require('bitcore-lib');
const explorers = require('bitcore-explorers');
const insight = new explorers.Insight();
const Client = require('bitcoin-core');

const client = new Client({
host: process.env.BITCOIN_NODE_HOST,
network: process.env.BITCOIN_NODE_NETWORK,
username: process.env.BITCOIN_NODE_USER,
password: process.env.BITCOIN_NODE_PASS,
port: process.env.BITCOIN_NODE_PORT
});

const from_address = "3KxY1Uqjw7oLTcd9xFRsHjtoksESSAae8e";
const to_address = "37Aq5Huw6kXEYV4LpT1b3grS3cULt2nBnd";
let amount = 0.0001;
let fee = 0.00002;
let threshold = 2;

const private_keys = [
new bitcore.PrivateKey('cd6a11ee315416c830d18dd31a497cd0f7f218bfe7629a65dc198d9bd2f8a458'),
new bitcore.PrivateKey('7d2373****************************************************613fc7')
];
const public_keys = private_keys.map(bitcore.PublicKey);

amount = new BN(amount).multipliedBy(1e8).toNumber();
fee = new BN(fee).multipliedBy(1e8).toNumber();

Promise.resolve(1).then(rows => {
return getUtxos(from_address);
}).then(rows => {
let unspent_utxos = rows;
const utxos = unspent_utxos.map((unspent_utxo) => {return bitcore.Transaction.UnspentOutput(unspent_utxo)});

const transaction = new bitcore.Transaction(); <em>// make transaction & signature </em>
transaction.from(utxos, public_keys, threshold);
transaction.to(to_address, amount);
transaction.change(from_address);
transaction.fee(fee);
transaction.sign(private_keys);

const signature = transaction.serialize();
console.log(signature);

});

if (private_keys == null) {
throw Error('no provate key registered.');
}

function getUtxos(from_address) {
return new Promise((resolve, reject) => {
insight.getUnspentUtxos(from_address, function (err, utxos) { <em>// insightを用いたutxoの取得</em>

if (err) {
reject(err);
}

try {

const object = utxos.map((utxo) => {
return utxo.toObject();
});

resolve(object);

} catch (e) {
reject(e);
}

});
});
};

署名されたトランザクションが作成される。

送信処理

node.js を用いて署名されたトランザクションを送信する。

require('dotenv').config();

const bitcore = require('bitcore-lib');
const explorers = require('bitcore-explorers');
const Client = require('bitcoin-core');

const client = new Client({
host: process.env.BITCOIN_NODE_HOST,
network: process.env.BITCOIN_NODE_NETWORK,
username: process.env.BITCOIN_NODE_USER,
password: process.env.BITCOIN_NODE_PASS,
port: process.env.BITCOIN_NODE_PORT
});

const signature = process.argv[2];

client.sendRawTransaction(signature).then(tx_hash => {
console.log(tx_hash);
});

送信が完了し64文字のトランザクションIDが返される。

その他(bitcore-cliを用いた署名手順)

1. トランザクション生成情報確認

送信に使用するVOUTを確認する

1.1 hexstring の確認(getrawtransaction)
bitcoin-cli getrawtransaction <em>トランザクションID</em>

トランザクションのhexstringが表示される。

1.2 トランザクションの詳細確認(decoderawtransaction)
bitcoin-cli decoderawtransaction [:hexstring]

トランザクションの詳細な情報が表示される。

{
"txid": "52a98*****************************************************74930",
"hash": "52a98*****************************************************74930",
"version": 1,
"size": 224,
"vsize": 224,
"weight": 896,
"locktime": 0,
"vin": [
{
"txid": "20e0c*****************************************************89339d",
"vout": 1,
"scriptSig": {
"asm": "3045022100d317****************************************ad9ac93914e9de1e577502204ba1265aa379c2c7****************************************c7de36c8[ALL] 03bc87****************************************2dc36cd836370d7c1ec0",
"hex": "483045022100d3****************************************57ad9ac93914e9de1e577502204ba1265aa379c2****************************************13c7de36c8012103bc87****************************************2dc36cd836370d7c1ec0"
},
"sequence": 42******95
}
],
"vout": [
{
"value": 0.00010000,
"n": 0,
"scriptPubKey": {
"asm": "OP_HASH160 d51******************************ee0856a OP_EQUAL",
"hex": "a914******************************827ee0856a87",
"reqSigs": 1,
"type": "scripthash",
"addresses": [
"3KxY1Uqjw7oLTcd9xFRsHjtoksESSAae8e"
]
}
},
{
"value": 0.01006657,
"n": 1,
"scriptPubKey": {
"asm": "OP_DUP OP_HASH160 2969c0******************************894e OP_EQUALVERIFY OP_CHECKSIG",
"hex": "76a9******************************ac634bdb894e88ac",
"reqSigs": 1,
"type": "pubkeyhash",
"addresses": [
"3Kxjw9xFRsH7oY1UqtoLTcdjksEe8SSAae"
]
}
}
]
}

2. 未署名トランザクションの生成(createrawtransaction)

署名が行われる前のトランザクションを生成する。

bitcoin-cli createrawtransaction [{"txid":"txid","vout":n,"scriptPubKey":"scriptPubKey hex","redeemScript":"redeemScript"] [{"address":amount}

未署名のトランザクションが生成される。

3. トランザクションへの署名(signrawtransactionwithkey)

未署名トランザクションに対し署名を行う。

bitcoin-cli signrawtransactionwithkey "hexstring" ["privatekey",...] [{"txid":"hex","vout":n,"scriptPubKey":"hex","redeemScript":"hex","amount":amount}]

※ここではBase58Checkエンコーディングが使用される。以下のnode.jsを用いてプライベートキーをWIF(Wallet imoprt format)形式に変換する。

ご相談・お見積もり

03-5207-2689