You're Invited:Meet the Socket Team at BlackHat and DEF CON in Las Vegas, Aug 7-8.RSVP
Socket
Socket
Sign inDemoInstall

io.github.scalahub:btc_2.12

Package Overview
Dependencies
Maintainers
1
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

io.github.scalahub:btc_2.12

Cryptocurrency node for bitcoin


Version published
Maintainers
1

Readme

Source

CryptoNode

Build Status Open Source Love svg1 MIT license

deprecated

CryptoNode is a bitcoin library written in Scala. It can be used for implementing nodes and wallets. It supports SPV mode out of the box and can be converted to a full node by implementing the core consensus rules and the execution engine. Note that this library is experimental so use it in TestNet only.

Supported features

  • Signing transactions and address generation:
    • SegWit legacy (P2SH-P2WPKH)
    • SegWit Bech32 (P2WPKH)
    • P2SH-P2PK
    • P2PKH
  • Node connectivity:
    • Listen for blocks and transactions
    • Broadcast transaction
  • SPV Mode:
    • Merkle Blocks
    • Bloom filters
  • Local Bitcoind connectivity:
    • RPC
    • Blockchain database parser (to reuse bitcoind chain)

Usage

Please refer to the tests for example usage: https://github.com/scalahub/CryptoNode/tree/master/btc/src/test/scala/org/sh/cryptonode

Connecting to the Network

From the TestBitcoinPeer example:

val useMainNet = false // set to true for main net (default)
val node = new org.sh.cryptonode.btc.BitcoinNode(useMainNet)
Listening for Transactions and Blocks

Once a node is created, here is how we can add handlers for listening to transactions and blocks.

node.addOnTxHandler("myTxHandler", tx => println(s"new transaction with id $tx"))
node.addOnBlkHandler("myBlkHandler", blk => println(s"new block with id $blk"))
Creating Transactions

The following code (based on the TestTx example) shows how how to create a transaction having both SegWit and non-SegWit inputs:

val useMainNet = false // mainnet is false

// generate a big integer to use as secret 
val int = new ECCPrvKey("BB2AC60BC518C0E239D5AF9D8D051A6BDFD0D931268DCA70C59E5992", true)   // random key
// three different types of private keys (can be generated from different ints but we use the same below)
val p2wpkh_key = new PrvKey_P2SH_P2WPKH(int.bigInt, useMainNet) 
val p2sh_key = new PrvKey_P2SH_P2PK(int, useMainNet)
val p2pkh_key = new PrvKey_P2PKH(int, useMainNet)

assert(p2wpkh_key.pubKey.address == "2N6nA4btbY23GTQ4RJi3mMGTonzXN7dbphE") // (segwit)
assert(p2sh_key.pubKey.address == "2MwprvB9tUMtX4vK8zJK8K329fNu79CJgR7") // (p2sh)
assert(p2pkh_key.pubKey.address == "muLwLjVipwixXcECVMcEwgsrtfGRTB4zB1") // (p2pkh)
  
// We will create a transaction whose inputs are a mix of segwit, p2sh and p2pkh types. The inputs are below
val in0 = TxIn("0224c8875a43c482c81a508fafc10bd0f084b27b5543c228e48431985f321547", 0) // p2pkh
val in1 = TxIn("63bec90405a0c173ae928860a1e1d403e507ec225e2cdd07717c8408820d418b", 0) // segwit // 2031250 satoshis
val in2 = TxIn("db5a23f0da2502b8ef82d93453aa3be0b6e9a3ecfbfbc00818dc32b3c712d2d0", 0) // p2pkh
val in3 = TxIn("6d73e3c8f66869859dc5c1ba73f252b8db51950ebc1fc4a59dca3552a0085f9a", 0) // p2sh
val in4 = TxIn("6ce466eb0920f84cc2cfde1d359176c0baab7dc442e4e5763bf67e8fa96ee6a4", 0) // p2sh
val in5 = TxIn("b49f3d6d15f2bdd9217ba3caaf1bb1f2d9875c9657e6b0ac7a0ef841d486ad1d", 2) // p2pkh
val in6 = TxIn("b75dfb27477834b3060c8e956273bef81c62689a8b9ebb7cd4a8119508c2c798", 0) // segwit // 1015625 satoshis

// The transaction creates one output to 2N8hwP1WmJrFF5QWABn38y63uYLhnJYJYTF, which is a faucet address and may 
// be either P2PKH or P2SH (without seeing a spend, it is impossible to distinguish them)

// The following output was created
val out1 = TxOut(Some("2N8hwP1WmJrFF5QWABn38y63uYLhnJYJYTF"), 32206092) // total amount is slightly more than 32206092

// Below are the steps to create the fully signed transaction

// Step 1: create an unsigned transaction
val tx0 = createTxRaw(Seq(in0,in1,in2,in3,in4,in5,in6), Seq(out1)) // unsigned tx

// Step 2: sign all the p2pkh inputs
val tx1 = p2pkh_key.signTx_P2PKH (tx0, Seq(0, 2, 5)) // inputs 0, 2, 5 are P2PKH 

// Step 3: sign all the p2wpkh inputs. Note that SegWit signatures need the value in satoshis
val tx2 = p2wpkh_key.signTx(tx1, Seq((1, 2031250), (6, 1015625)))  // inputs 1, 6 are segwit. 
  
// Step 4: sign all p2sh_p2pk inputs
val signed = p2sh_key.signTx_P2SH_P2PK(tx2, Seq(3, 4)) // inputs 3, 4 are P2SH_P2PK 

// above is a byte array encoding the fully signed raw Tx
val tx = new TxParser(signed).getTx // creates a Tx object
Broadcasting transactions

Once the transaction is created, we can broadcast it using the node created earlier:

node.pushTx(tx)

Acknowledgements

Thanks to Arubi from #bitcoin-dev (Freenode) for providing several test vectors.

FAQs

Package last updated on 09 Apr 2023

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc