File: README.md
Bitcore Monorepo
Infrastructure to build Bitcoin and blockchain-based applications for the next generation of financial technology.
Applications
- Bitcore Node - A standardized API to interact with multiple blockchain networks
- Bitcore Wallet Client - A client for Bitcore Wallet Service
- Bitcore Wallet Service - A coordination service for multisig wallets
- Bitcore CLI - A command line interface for using BWS and BWC
- Insight - A blockchain explorer web user interface
Libraries
- Bitcore Lib - A powerful JavaScript library for Bitcoin
- Bitcore Lib Cash - A powerful JavaScript library for Bitcoin Cash
- Bitcore Lib Doge - A powerful JavaScript library for Dogecoin
- Bitcore Lib Litecoin - A powerful JavaScript library for Litecoin
- Bitcore Mnemonic - Implements mnemonic code for generating deterministic keys
- Bitcore P2P - The peer-to-peer networking protocol for Bitcoin
- Bitcore P2P Cash - The peer-to-peer networking protocol for Bitcoin Cash
- Bitcore P2P Doge DEPRECATED[^1] - The peer-to-peer networking protocol for Dogecoin
- Crypto Wallet Core - A coin-agnostic wallet library for creating transactions, signing, and address derivation
- Crypto RPC - A library for connecting to blockchains' RPC interfaces
Extras
- Bitcore Build - A helper to add tasks to gulp
- Bitcore Client - A helper to create a wallet using the bitcore-node infrastructure
- Bitpay/Bitpay App - An easy-to-use, multiplatform, multisignature, secure wallet for bitcoin, ethereum, and more
Versioning
This repo follows the even-odd versioning convention. Major versions that are even (e.g. v8.x.x) are stable releases, odd are beta releases (e.g. v9.x.x). Beta versions may contain breaking changes or major feature additions that are still in testing.
Contributing
See CONTRIBUTING.md on the main bitcore repo for information about how to contribute.
License
Code released under the MIT license.
Copyright 2013-2025 BitPay, Inc. Bitcore is a trademark maintained by BitPay, Inc.
[^1]: The Bitcore P2P Doge library is no longer maintained as all the core functionality is contained in Bitcore P2P
File: packages/bitcore-wallet-service/README.md
Bitcore Wallet Service
A Multisig HD Bitcore Wallet Service.
Description
Bitcore Wallet Service facilitates multisig HD wallets creation and operation through a (hopefully) simple and intuitive REST API.
BWS can usually be installed within minutes and accommodates all the needed infrastructure for peers in a multisig wallet to communicate and operate โ with minimum server trust.
See bitcore-wallet-client for the official client library that communicates to BWS and verifies its response. Also check bitcore-cli for a simple CLI wallet implementation that relies on BWS.
BWS is been used in production enviroments for Copay Wallet, Bitpay App wallet and others.
More about BWS at https://blog.bitpay.com/announcing-the-bitcore-wallet-suite/
Getting Started
git clone https://github.com/bitpay/bitcore.git
cd bitcore
npm install
npm run bwsThis will launch the BWS service (with default settings) at http://localhost:3232/bws/api.
BWS needs mongoDB. You can configure the connection inside the "bitcoreWalletService" section of your bitcore.config.json. See the Configuration section of Installation.md.
BWS uses by default a Request Rate Limitation to CreateWallet endpoint. If you need to modify it, check defaults.js' Defaults.RateLimit
Security Considerations
- Private keys are never sent to BWS. Copayers store them locally.
- Extended public keys are stored on BWS. This allows BWS to easily check wallet balance, send offline notifications to copayers, etc.
- During wallet creation, the initial copayer creates a wallet secret that contains a private key. All copayers need to prove they have the secret by signing their information with this private key when joining the wallet. The secret should be shared using secured channels.
- A copayer could join the wallet more than once, and there is no mechanism to prevent this. See wallet's confirm command, for a method for confirming copayers.
- All BWS responses are verified:
- Addresses and change addresses are derived independently and locally by the copayers from their local data.
- TX Proposals templates are signed by copayers and verified by others, so the BWS cannot create or tamper with them.
Using SSL
You can add your certificates at the bws.config.js using:
https: true,
privateKeyFile: 'private.pem',
certificateFile: 'cert.pem',
////// The following is only for certs which are not
////// trusted by nodejs 'https' by default
////// CAs like Verisign do not require this
// CAinter1: '', // ex. 'COMODORSADomainValidationSecureServerCA.crt'
// CAinter2: '', // ex. 'COMODORSAAddTrustCA.crt'
// CAroot: '', // ex. 'AddTrustExternalCARoot.crt'@dabura667 made a report about how to use letsencrypt with BWS: https://github.com/bitpay/bitcore-wallet-service/issues/423
TX proposal life cycle
Tx proposal need to be:
- First created via /v?/txproposal
-> This will create a 'temporary' TX proposal, returning the object, but not locking the inputs - Then published via /v?/txproposal/:id/publish
-> This publish the tx proposal to all copayers, looking the inputs. The TX proposal can bedeletedalso, after been published. - Then signed via /v?/txproposal/:id/signature for each copayer
- Then broadcasted to the p2p network via /v?/txproposal/:id/broadcast
There are plenty examples of creating and sending proposals in the /test/integration code.
Enabling Regtest Mode for BWS and Copay
Requirements
- bitcore-node running on http://localhost:3000
- bws running locally on http://localhost:3232/bws/api
- mongod running
- copay running on port: 8100
- bitcoin-core running on regtest mode (blue icon logo)
mongo topology crashes sometimes due to notifications being incompatible in a web browser
bitcore-wallet-service/lib/notificationbroadcaster.js
Note: If testing on a PC browser, comment out notificationbroadcaster.js to disable notifications.
Steps:
bitcore.config.json
- Add a regtest configuration to the bitcoreNode section of your
bitcore.config.json.
Example:
// bitcore.config.json
{
"bitcoreNode": {
"chains": {
"BTC": {
// add me:
"regtest": {
"chainSource": "p2p",
"trustedPeers": [
{
"host": "127.0.0.1",
"port": 20020
}
],
"rpc": {
"host": "127.0.0.1",
"port": 20021,
"username": "bitpaytest",
"password": "local321"
}
}
}
}
}
}- Point regtest to http://localhost:3000 in the bitcoreWalletService.blockchainExplorerOpts section and set allowRegtest to true.
// bitcore.config.json
{
"bitcoreWalletService": {
"allowRegtest": true,
"blockchainExplorerOpts": {
"btc": {
"livenet": {
"url": "https://api.bitcore.io"
},
"regtest": {
"url": "http://localhost:3000",
}
},
...Copay changes
copay/app-template/index-template.html
- Comment out content security meta tag in the
<head>
// <meta http-equiv="Content-Security-Policy" content="default-src 'self' ... >Creating a wallet on regtest network
Steps:
- Set the wallet service URL to
http://localhost:3232/bws/api- Select Testnet by pressing the slider button.
Testing on mobile
Requirements:
- Mobile phone and PC must be connected to the same internet
- PC desktop ip address for localhost
To find ip address for PC run:
// 127.0.0.1 is equal to localhost
ifconfig | grep "inet " | grep -v 127.0.0.1- Inside copay project root directory run:
npm run apply:copay- Enter PC ip address followed by port in the mobile phone browser:
10.10.11.73:8100- Set wallet service url to PC ip address /bws/api when creating a new wallet
http://10.10.11.73:3232/bws/apiREST API
Note: all currency amounts are in units of satoshis (1/100,000,000 of a bitcoin).
Authentication
In order to access a wallet, clients are required to send the headers:
x-identity
x-signatureIdentity is the Peer-ID, this will identify the peer and its wallet. Signature is the current request signature, using requestSigningKey, the m/1/1 derivative of the Extended Private Key.
See Bitcore Wallet Client for implementation details.
GET Endpoints
`/v1/wallets/`: Get wallet information
Returns:
- Wallet object. (see fields on the source code).
`/v1/txhistory/`: Get Wallet's transaction history
Optional Arguments:
- skip: Records to skip from the result (defaults to 0)
- limit: Total number of records to return (return all available records if not specified).
- reverse: Return oldest transactions first.
Returns:
- History of incoming and outgoing transactions of the wallet. The list is paginated using the
skip&limitparams. Each item has the following fields: - action ('sent', 'received', 'moved')
- amount
- fees
- time
- addressTo
- confirmations
- proposalId
- creatorName
- message
- actions array ['createdOn', 'type', 'copayerId', 'copayerName', 'comment']
`/v2/txproposals/`: Get Wallet's pending transaction proposals and their status
Returns:
List of pending TX Proposals. (see fields on the source code)
Uses cashaddr without prefix for BCH
`/v4/addresses/`: Get Wallet's main addresses (does not include change addresses)
Optional Arguments:
- ignoreMaxGap: [false] Ignore checking less that 20 unused addresses (BIP44 GAP)
Returns:
- List of Addresses object: (https://github.com/bitpay/bitcore/blob/master/packages/bitcore-wallet-service/src/lib/model/address.ts). This call is mainly provided so the client check this addresses for incoming transactions (using a service like Insight
- Returns cashaddr without prefix for BCH
`/v1/balance/`: Get Wallet's balance
Returns:
- totalAmount: Wallet's total balance
- lockedAmount: Current balance of outstanding transaction proposals, that cannot be used on new transactions.
- availableAmount: Funds available for new proposals.
- totalConfirmedAmount: Same as totalAmount for confirmed UTXOs only.
- lockedConfirmedAmount: Same as lockedAmount for confirmed UTXOs only.
- availableConfirmedAmount: Same as availableAmount for confirmed UTXOs only.
- byAddress array ['address', 'path', 'amount']: A list of addresses holding funds.
- totalKbToSendMax: An estimation of the number of KiB required to include all available UTXOs in a tx (including unconfirmed).
`/v1/txnotes/:txid`: Get user notes associated to the specified transaction
Returns:
- The note associated to the
txidas a string.
`/v1/fiatrates/:code`: Get the fiat rate for the specified ISO 4217 code
Optional Arguments:
- provider: An identifier representing the source of the rates.
- ts: The timestamp for the fiat rate (defaults to now).
Returns:
- The fiat exchange rate.
POST Endpoints
`/v1/wallets/`: Create a new Wallet
Required Arguments:
- name: Name of the wallet
- m: Number of required peers to sign transactions
- n: Number of total peers on the wallet
- pubKey: Wallet Creation Public key to check joining copayer's signatures (the private key is unknown by BWS and must be communicated
by the creator peer to other peers).
Returns:
- walletId: Id of the new created wallet
`/v1/wallets/:id/copayers/`: Join a Wallet in creation
Required Arguments:
- walletId: Id of the wallet to join
- name: Copayer Name
- xPubKey - Extended Public Key for this copayer.
- requestPubKey - Public Key used to check requests from this copayer.
- copayerSignature - Signature used by other copayers to verify that the copayer joining knows the wallet secret.
Returns:
- copayerId: Assigned ID of the copayer (to be used on x-identity header)
- wallet: Object with wallet's information
`/v3/txproposals/`: Add a new temporary transaction proposal
Required Arguments:
- toAddress: RCPT Bitcoin address.
- amount: amount (in satoshis) of the mount proposed to be transfered
- proposalsSignature: Signature of the proposal by the creator peer, using proposalSigningKey.
- (opt) message: Encrypted private message to peers.
- (opt) payProUrl: Paypro URL for peers to verify TX
- (opt) feePerKb: Use an alternative fee per KB for this TX.
- (opt) excludeUnconfirmedUtxos: Do not use UTXOs of unconfirmed transactions as inputs for this TX.
- BCH addresses need to be cashaddr without prefix.
Returns:
- TX Proposal object. (see [fields on the source code]https://github.com/bitpay/bitcore/blob/master/packages/bitcore-wallet-service/src/lib/model/txproposal.ts)).
.idis probably needed in this case.
`/v2/txproposals/:id/publish`: Publish the previously created `temporary` tx proposal
Returns:
- TX Proposal object. (see fields on the source code).
`/v3/addresses/`: Request a new main address from wallet . (creates an address on normal conditions)
Returns:
- Address object: (https://github.com/bitpay/bitcore/blob/master/packages/bitcore-wallet-service/src/lib/model/address.ts). Note that
pathis returned so client can derive the address independently and check server's response.
`/v1/txproposals/:id/signatures/`: Sign a transaction proposal
Required Arguments:
- signatures: All Transaction's input signatures, in order of appearance.
Returns:
- TX Proposal object. (see fields on the source code).
.statusis probably needed in this case.
`/v1/txproposals/:id/broadcast/`: Broadcast a transaction proposal
Returns:
- TX Proposal object. (see fields on the source code).
.statusis probably needed in this case.
`/v1/txproposals/:id/rejections`: Reject a transaction proposal
Returns:
- TX Proposal object. (see fields on the source code).
.statusis probably needed in this case.
`/v1/addresses/scan`: Start an address scan process looking for activity.
Optional Arguments:
- includeCopayerBranches: Scan all copayer branches following BIP45 recommendation (defaults to false).
`/v1/txconfirmations/`: Subscribe to receive push notifications when the specified transaction gets confirmed
Required Arguments:
- txid: The transaction to subscribe to.
PUT Endpoints
`/v1/txnotes/:txid/`: Modify a note for a tx
DELETE Endpoints
`/v1/txproposals/:id/`: Deletes a transaction proposal. Only the creator can delete a TX Proposal, and only if it has no other signatures or rejections
Returns:
- TX Proposal object. (see fields on the source code).
.idis probably needed in this case.
`/v1/txconfirmations/:txid`: Unsubscribe from transaction `txid` and no longer listen to its confirmation
Push Notifications
Recomended to complete config.js file:
POST Endpoints
`/v1/pushnotifications/subscriptions/`: Adds subscriptions for push notifications service at database
DELETE Endpoints
`/v2/pushnotifications/subscriptions/`: Remove subscriptions for push notifications service from database
Contributing
See CONTRIBUTING.md on the main bitcore repo for information about how to contribute.
License
Code released under the MIT license.
Copyright 2013-2019 BitPay, Inc. Bitcore is a trademark maintained by BitPay, Inc.
File: packages/bitcore-wallet-client/README.header.md
bitcore-wallet-client
The official client library for bitcore-wallet-service.
Description
This package communicates with BWS Bitcore wallet service using the REST API. All REST endpoints are wrapped as simple async methods. All relevant responses from BWS are checked independently by the peers, thus the importance of using this library when talking to a third party BWS instance.
See [Bitcore-CLI] (https://github.com/bitpay/bitcore/tree/master/packages/bitcore-cli) for a simple CLI wallet implementation that relies on BWS and uses bitcore-wallet-client.
Get Started
You can start using bitcore-wallet-client via NPM: by running npm install @bitpay-labs/bitcore-wallet-client from your console.
Example
Start your own local Bitcore wallet service instance. In this example we assume you have bitcore-wallet-service running on your localhost:3232.
Then create two files irene.js and tomas.js with the content below:
**irene.js**
var Client = require('@bitpay-labs/bitcore-wallet-client');
var fs = require('fs');
var BWS_INSTANCE_URL = 'https://bws.bitpay.com/bws/api'
var client = new Client({
baseUrl: BWS_INSTANCE_URL,
verbose: false,
});
client.createWallet("My Wallet", "Irene", 2, 2, {network: 'testnet'}, function(err, secret) {
if (err) {
console.log('error: ',err);
return
};
// Handle err
console.log('Wallet Created. Share this secret with your copayers: ' + secret);
fs.writeFileSync('irene.dat', client.export());
});**tomas.js**
var Client = require('@bitpay-labs/bitcore-wallet-client');
var fs = require('fs');
var BWS_INSTANCE_URL = 'https://bws.bitpay.com/bws/api'
var secret = process.argv[2];
if (!secret) {
console.log('./tomas.js <Secret>')
process.exit(0);
}
var client = new Client({
baseUrl: BWS_INSTANCE_URL,
verbose: false,
});
client.joinWallet(secret, "Tomas", {}, function(err, wallet) {
if (err) {
console.log('error: ', err);
return
};
console.log('Joined ' + wallet.name + '!');
fs.writeFileSync('tomas.dat', client.export());
client.openWallet(function(err, ret) {
if (err) {
console.log('error: ', err);
return
};
// Example output for demonstration / debugging purposes
console.log('\n\n** Wallet Info', ret);
console.log('\n\nCreating first address:', ret);
if (ret.wallet.status == 'complete') {
client.createAddress({}, function(err,addr){
if (err) {
console.log('error: ', err);
return;
};
console.log('\nReturn:', addr)
});
}
});
});Install bitcore-wallet-client before start:
npm i @bitpay-labs/bitcore-wallet-clientCreate a new wallet with the first script:
$ node irene.js
info Generating new keys
Wallet Created. Share this secret with your copayers: JbTDjtUkvWS4c3mgAtJf4zKyRGzdQzZacfx2S7gRqPLcbeAWaSDEnazFJF6mKbzBvY1ZRwZCbvTJoin to this wallet with generated secret:
$ node tomas.js JbTDjtUkvWS4c3mgAtJf4zKyRGzdQzZacfx2S7gRqPLcbeAWaSDEnazFJF6mKbzBvY1ZRwZCbvT
Joined My Wallet!
Wallet Info: [...]
Creating first address:
Return: [...]Note that the scripts created two files named irene.dat and tomas.dat. With these files you can get status, generate addresses, create proposals, sign transactions, etc.
File: packages/bitcore-wallet-client/README.md
bitcore-wallet-client
The official client library for bitcore-wallet-service.
Description
This package communicates with BWS Bitcore wallet service using the REST API. All REST endpoints are wrapped as simple async methods. All relevant responses from BWS are checked independently by the peers, thus the importance of using this library when talking to a third party BWS instance.
See [Bitcore-CLI] (https://github.com/bitpay/bitcore/tree/master/packages/bitcore-cli) for a simple CLI wallet implementation that relies on BWS and uses bitcore-wallet-client.
Get Started
You can start using bitcore-wallet-client via NPM: by running npm install @bitpay-labs/bitcore-wallet-client from your console.
Example
Start your own local Bitcore wallet service instance. In this example we assume you have bitcore-wallet-service running on your localhost:3232.
Then create two files irene.js and tomas.js with the content below:
**irene.js**
var Client = require('@bitpay-labs/bitcore-wallet-client');
var fs = require('fs');
var BWS_INSTANCE_URL = 'https://bws.bitpay.com/bws/api'
var client = new Client({
baseUrl: BWS_INSTANCE_URL,
verbose: false,
});
client.createWallet("My Wallet", "Irene", 2, 2, {network: 'testnet'}, function(err, secret) {
if (err) {
console.log('error: ',err);
return
};
// Handle err
console.log('Wallet Created. Share this secret with your copayers: ' + secret);
fs.writeFileSync('irene.dat', client.export());
});**tomas.js**
var Client = require('@bitpay-labs/bitcore-wallet-client');
var fs = require('fs');
var BWS_INSTANCE_URL = 'https://bws.bitpay.com/bws/api'
var secret = process.argv[2];
if (!secret) {
console.log('./tomas.js <Secret>')
process.exit(0);
}
var client = new Client({
baseUrl: BWS_INSTANCE_URL,
verbose: false,
});
client.joinWallet(secret, "Tomas", {}, function(err, wallet) {
if (err) {
console.log('error: ', err);
return
};
console.log('Joined ' + wallet.name + '!');
fs.writeFileSync('tomas.dat', client.export());
client.openWallet(function(err, ret) {
if (err) {
console.log('error: ', err);
return
};
console.log('\n\n** Wallet Info', ret); //TODO
console.log('\n\nCreating first address:', ret); //TODO
if (ret.wallet.status == 'complete') {
client.createAddress({}, function(err,addr){
if (err) {
console.log('error: ', err);
return;
};
console.log('\nReturn:', addr)
});
}
});
});Install bitcore-wallet-client before start:
npm i @bitpay-labs/bitcore-wallet-clientCreate a new wallet with the first script:
$ node irene.js
info Generating new keys
Wallet Created. Share this secret with your copayers: JbTDjtUkvWS4c3mgAtJf4zKyRGzdQzZacfx2S7gRqPLcbeAWaSDEnazFJF6mKbzBvY1ZRwZCbvTJoin to this wallet with generated secret:
$ node tomas.js JbTDjtUkvWS4c3mgAtJf4zKyRGzdQzZacfx2S7gRqPLcbeAWaSDEnazFJF6mKbzBvY1ZRwZCbvT
Joined My Wallet!
Wallet Info: [...]
Creating first address:
Return: [...]Note that the scripts created two files named irene.dat and tomas.dat. With these files you can get status, generate addresses, create proposals, sign transactions, etc.The MIT License
Copyright (c) 2015-2021 BitPay
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
File: packages/bitcore-tss/README.md
Bitcore Threshold Signature Scheme
A powerful JavaScript library for distributed threshold ECDSA key and signature generation
Principles
A threshold signature scheme allows a group of participants to sign a message in a distributed manner. The signature is valid only if a certain number of participants (the threshold) have signed the message.
This libary is designed to be flexible in that it supports distributed key generation (DKG) which means that the private key is never constructed in any one location, thus ensuring than no single party ever has the full private key in their possession.
The TSS protocols (DKG & DSG) depend on a secure communication channel between the participants.
For example, a central coordination server that all parties connect to over HTTPS
Get Started
To add Bitcore-TSS to your project, run:
npm install @bitpay-labs/bitcore-tssDocumentation
Distributed Key Generation
The DKG protocol is used to generate a shared private key that is distributed among a group of participants. The private key is never constructed in any one location, thus ensuring than no single party ever has the full private key in their possession.
Example
First, you need to instantiate a KeyGen instance.
const keygen = new bitcoreTss.KeyGen({
m: 2, // participant threshold needed to generate a signature
n: 3, // number of participants
partyId: 0, // which participant of the 3 are you (0-based...the initiator is always 0)?
authKey: privateKey, // a private key used for encrypting and signing messages
seed: seedKey, // Optional - could be the derivation of a 12-word phrase
});Then, you need to generate the broadcast message to the other participants that you're joining the group.
const broadcastMessage = await keygen.initJoin();
// securely send broadcastMessage to the other participantsOnce you receive the broadcast messages from the other participants, you need to proceed to the next round of messages.
const otherParticipantsMessages = // receive messages from the other participants
const myNextRoundMessage = keygen.nextRound(otherParticipantsMessages);
// securely send myNextRoundMessage to the other participantsContinue through the rounds until the keychain is ready
while (!keygen.isKeyChainReady()) {
const otherParticipantsMessages = // receive messages from the other participants
const myNextRoundMessage = keygen.nextRound(otherParticipantsMessages);
// securely send myNextRoundMessage to the other participants
}
const keychain = keygen.getKeyChain();Congrats! You now have a key share that you can use to sign messages.
Distributed Signature Generation
Once you have your key share, you can use it to sign messages. The process is similar to the DKG protocol - generating a signature requires multiple rounds of message passing.
In this example, we'll use an Ethereum transaction as our use case.
const rawTxHex = '0x...'; // your raw hex transaction
const hashBuffer = Buffer.from(Web3.utils.keccak256(rawTxHex).substring(2), 'hex');
const signer = new bitcoreTss.Sign({
keychain,
m: 2, // participant threshold needed to generate a signature
n: 3, // total number of participants
partyId: 0, // your party id
messageHash: hashBuffer, // a 32-byte hash of message to sign
authKey: privateKey, // a private key used for encrypting and signing messages
derivationPath: 'm' // optional - useful for UTXO chains like Bitcoin that derive lots of addresses
});Initiate the first round of the signature generation protocol and create a broadcast message to send to the other participants that you wish to sign a message
const broadcastMessage = await signer.initJoin();
// securely send broadcastMessage to the other participantsContinue through the rounds until the signature is ready
while (!signer.isSignatureReady()) {
const otherParticipantsMessages = // receive messages from the other participants
const myNextRoundMessage = signer.nextRound(otherParticipantsMessages);
// securely send myNextRoundMessage to the other participants
}Once the signature is ready, you can get it and apply it to your use case. For this example, we're applying the signature to our Ethereum transaction.
const CWC = require('@bitpay-labs/crypto-wallet-core');
const sig = signer.getSignature();
const signedTxHex = CWC.Transactions.applySignature({ chain: 'ETH', tx: rawTxHex, signature: sig });File: packages/bitcore-p2p-doge/docs/index.md
Peer-to-Peer
The bitcore-p2p-doge module provides peer-to-peer networking capabilities for Bitcore, and includes Peer and Pool classes. A Message class is also exposed, in addition to several types of messages. Pool will maintain connection to several peers, Peers represents a node in the bitcoin network, and Message represents data sent to and from a Peer. For detailed technical information about the bitcoin protocol, please visit the Protocol Specification on the Bitcoin Wiki.
Installation
Peer-to-peer is implemented as a separate module.
To add to your project, run:
npm install @bitpay-labs/bitcore-p2p-dogeQuick Start
var Peer = require('@bitpay-labs/bitcore-p2p-doge').Peer;
var peer = new Peer({host: '5.9.85.34'});
// handle events
peer.on('inv', function(message) {
// message.inventory[]
});
peer.connect();File: packages/bitcore-p2p-doge/docs/messages.md
Messages
The bitcoin protocol specifies a set of messages that can be sent from peer to peer. bitcore-p2p-doge provides support for some of these messages.
To create a message, you can use any of the message constructors, here is a simple example:
var messages = new Messages();
var message = messages.Ping();There are also several convenient helpers for inventory based messages:
message = messages.GetData.forTransaction(txHash);
message = messages.GetData.forBlock(blockHash);
message = messages.Inventory.forTransaction(txHash);As well as sending "tx" and "block" messages with Bitcore instances:
message = messages.Block(block);
message = messages.Transaction(transaction);Note: A list of further messages is available below.
For advanced usage, you can also customize which constructor is used for Block and Transaction messages by passing it as an argument to Messages, for example:
var messages = new Messages({Block: MyBlock, Transaction: MyTransaction});And additionally a custom network:
var messages = new Messages({network: Networks.testnet});List of Messages
Version
The version message (ver) is used on connection creation, to advertise the type of node. The remote node will respond with its version, and no communication is possible until both peers have exchanged their versions. By default, bitcore advertises itself as named bitcore with the current version of the bitcore-p2p-doge package.
VerAck
Finishes the connection handshake started by the ver message.
Inventory
From the bitcoin protocol spec: "Allows a node to advertise its knowledge of one or more objects. It can be received unsolicited, or in reply to getblocks.".
GetData
From the bitcoin protocol spec: getdata is used in response to inv, to retrieve the content of a specific object, and is usually sent after receiving an inv packet, after filtering known elements. It can be used to retrieve transactions, but only if they are in the memory pool or relay set - arbitrary access to transactions in the chain is not allowed to avoid having clients start to depend on nodes having full transaction indexes (which modern nodes do not).
GetData inherits from Inventory, as they both have the same structure.
NotFound
notfound is a response to a getdata, sent if any requested data items could not be relayed, for example, because the requested transaction was not in the memory pool or relay set. Contains inventory information specifying which items were not found.
Ping
Sent to another peer mainly to check the connection is still alive.
Pong
Sent in response to a ping message.
Address and GetAddresses
Provides information on known nodes of the network. GetAddresses is used to query another peer for known addresses.
GetHeaders and Headers
getheaders allows a peer to query another about blockheaders. headers is sent in response to a getheaders message, containing information about block headers.
GetBlocks and Block
Same as getheaders and headers, but the response comes one block at the time.
Transaction
Message that contains a transaction.
Custom Messages
It is possible to extend the default peer to peer messages and add custom ones. First you will need to create a message which resembles the default messages in lib/messages/commands.
Then to add the custom message:
messages.add('custom', 'Custom', CustomMessage);
var customMessage = messages.Custom('argument');File: packages/bitcore-p2p-doge/docs/peer.md
Peer
Represents a node from the p2p bitcoin network. The Peer class supports connecting directly to other nodes or through a socks5 proxy like Tor.
Creating a peer
The code to create a new peer looks like this:
var Peer = require('@bitpay-labs/bitcore-p2p-doge').Peer;
// default port
var livenetPeer = new Peer({host: '5.9.85.34'});
var testnetPeer = new Peer({host: '5.9.85.34', network: Networks.testnet});
// custom port
var livenetPeer = new Peer({host: '5.9.85.34', port: 8334});
var testnetPeer = new Peer({host: '5.9.85.34', port: 18334, network: Networks.testnet});
// use sock5 proxy (Tor)
var peer = new Peer({host: '5.9.85.34'}).setProxy('localhost', 9050);States
A peer instance is always in one of the following states:
disconnected: No connection with the remote node.connecting: While establishing the connection.connected: Exchanging version packages.ready: Connection ready for sending and receiving messages.
You can subscribe to the change of those states as follows:
var Peer = require('@bitpay-labs/bitcore-p2p-doge').Peer;
var peer = new Peer({host: '5.9.85.34'});
peer.on('ready', function() {
// peer info
console.log(peer.version, peer.subversion, peer.bestHeight);
});
peer.on('disconnect', function() {
console.log('connection closed');
});
peer.connect();Handle messages
Once connected, a peer instance can send and receive messages. Every time a message arrives it's emitted as a new event. Let's see an example of this:
var Peer = require('@bitpay-labs/bitcore-p2p-doge').Peer;
var peer = new Peer({host: '5.9.85.34'});
// handle events
peer.on('inv', function(message) {
// message.inventory[]
});
peer.on('tx', function(message) {
// message.transaction
});
peer.on('addr', function(message) {
// message.addresses[]
});
peer.connect();Sending messages
In order to send messages the Peer class offers the sendMessage(message) method, which receives an instance of a message. All supported messages can be found in the Messages module. For more information about messages refer to the protocol specification.
An example for requesting other connected nodes to a peers looks like this:
var p2p = require('@bitpay-labs/bitcore-p2p-doge')
var Peer = p2p.Peer;
var Messages = p2p.Messages;
var peer = new Peer({host: '5.9.85.34'});
peer.on('ready', function() {
var message = new Messages.GetAddresses();
peer.sendMessage(message);
});
peer.on('addr', function(message) {
message.addresses.forEach(function(address) {
// do something
});
});
peer.connect();File: packages/bitcore-p2p-doge/docs/pool.md
Pool
A pool maintains a connection of Peers. A pool will discover peers via DNS seeds, as well as when peer addresses are announced through the network.
The quickest way to get connected is to run the following:
var Pool = require('@bitpay-labs/bitcore-p2p-doge').Pool;
var Networks = require('@bitpay-labs/bitcore-lib-doge').Networks;
var pool = new Pool({network: Networks.livenet});
// connect to the network
pool.connect();
// attach peer events
pool.on('peerinv', function(peer, message) {
// a new peer message has arrived
});
// will disconnect all peers
pool.disconnect()For more information about Peer events please read the Peer documentation. Peer events are relayed to the pool, a peer event inv in the pool would be peerinv. When a peer is disconnected the pool will try to connect to the list of known addresses to maintain connection.
Trusted Peers
By default, peers will be added via DNS discovery and as peers are announced in the network. Configuration options can be included to connect only to specific trusted peers:
var pool = new Pool({
network: Networks.livenet, // the network object
dnsSeed: false, // prevent seeding with DNS discovered known peers upon connecting
listenAddr: false, // prevent new peers being added from addr messages
addrs: [ // initial peers to connect to
{
ip: {
v4: '127.0.0.1'
}
}
]
});
pool.connect();Listening for Peers
It's also possible to listen to incoming socket connections to add peers to the pool. To enable this capability, you can do the following:
var pool = new Pool({network: Networks.livenet});
pool.listen();When there are incoming connections the peer will be added to the pool.