Giter VIP home page Giter VIP logo

bitcoinrb's People

Contributors

azuchi avatar fryota142 avatar kannapoix avatar mike-ct avatar pool2win avatar quanon avatar rantan avatar takeshi-y avatar yamaguchi avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

bitcoinrb's Issues

Bitcoin::Secp256k1::Ruby.verify_sig always returns false

Currently on Ruby 3.0.2, I tried Ruby 3.0.1

Also tried switching from creating a signed message with a segwit bech32 address to a legacy address and no matter what the signature returns as false.. Can this issue be verified?

Thanks!

PSBT::Tx - p2sh-p2wsh - another signer create signature

More of a question than an issue report.

My situation: I would like to spent BTC from P2WSH-P2SH 2-of-2 multisig address 2MzNSwkkgi75psa1GP5RJynM8sgCt5oeqgG.

1 private key from Client and 1 key from sever. When client sign a raw transaction by bitcoinjs-lib then i send that payload to server to let's server sign remaining sig and broadcast it

payload = '70736274ff010053020000000113a74a3fb29ebc282d3cbf0a8bee086188d7e533d71e976419c955215ff50d530000000000ffffffff01a8c8fa020000000017a914ffd0dbb44402d5f8f12d9ba5b484a2c1bb47da4287000000000001012030dcfa020000000017a9144e269b90bfdc52dbd46b13eaaefaa55dcffda15787220203c1917544fd6f2c832618d41eace312600d75da50005a467cc82b4ef81555097b47304402202eda814690158067e4822e963454a503814bbb5ae7450b0bdc7fa6b22d95945902204f1741cc533134a0a0137ad86ba8251ea4cd3aac9f3d500f74085284e8a7b2640101042200200fc49349c98ac78e320d9a0249af566fea3d22d801abc52884da5fddaf736f8d010547522103c1917544fd6f2c832618d41eace312600d75da50005a467cc82b4ef81555097b210397923a255b75bd469886fd1564de7372a54dc8fd348499c25ca88d8383edc26352ae0000'

psbt = Bitcoin::PSBT::Tx.parse_from_payload(payload.htb)

Followed this spec:

sighash3 = signer_psbt2.tx.sighash_for_input(1, signer_psbt2.signature_script(1), sig_version: :witness_v0, amount: signer_psbt2.inputs[1].witness_utxo.value)

I tried:

server_prkey =  Bitcoin::Key.from_wif('cQ158uqooksh6QkA3PzoctGSc4uu6Wc3y4bXkVsCkESEJJjnEPrW')
sighash = psbt.tx.sighash_for_input(0, psbt.signature_script(0), sig_version: :witness_v0, amount: psbt.inputs[0].witness_utxo.value)
sig = server_prkey.sign(sighash, false) + [Bitcoin::SIGHASH_TYPE[:all]].pack('C')
psbt.inputs[0].add_sig(server_prkey.pubkey, sig)
# ArgumentError: The sighash in signature is invalid.
# from /Users/tobi/.rbenv/versions/2.3.3/lib/ruby/gems/2.3.0/gems/bitcoinrb-0.2.9/lib/bitcoin/psbt/input.rb:159:in `add_sig'

Should i create new server psbt tx without signature from client then merge with client psbt tx. Is there anyway without using merge method. Many thanks

Expect result after signing from server # i got it by bitcoinjs-lib

70736274ff010053020000000113a74a3fb29ebc282d3cbf0a8bee086188d7e533d71e976419c955215ff50d530000000000ffffffff01a8c8fa020000000017a914ffd0dbb44402d5f8f12d9ba5b484a2c1bb47da4287000000000001012030dcfa020000000017a9144e269b90bfdc52dbd46b13eaaefaa55dcffda1578722020397923a255b75bd469886fd1564de7372a54dc8fd348499c25ca88d8383edc263483045022100c99d7abdbceb677006c10d1364b807485b591a34065fabb1db53582c7193a1ae022018fac19b51012575323aa350ff460bdc662a9989e77398625218d6d6dfd151d601220203c1917544fd6f2c832618d41eace312600d75da50005a467cc82b4ef81555097b47304402202eda814690158067e4822e963454a503814bbb5ae7450b0bdc7fa6b22d95945902204f1741cc533134a0a0137ad86ba8251ea4cd3aac9f3d500f74085284e8a7b2640101042200200fc49349c98ac78e320d9a0249af566fea3d22d801abc52884da5fddaf736f8d010547522103c1917544fd6f2c832618d41eace312600d75da50005a467cc82b4ef81555097b210397923a255b75bd469886fd1564de7372a54dc8fd348499c25ca88d8383edc26352ae0000

undefined method `partial?' for nil:NilClass

Error occured in regtest mode.

I, [2019-05-31T16:29:19.824022 #158 #47033197926660]  INFO -- : [172.28.3.1:18444] process command inv.
I, [2019-05-31T16:29:19.824139 #158 #47033197926660]  INFO -- : receive inv message.
I, [2019-05-31T16:29:19.824174 #158 #47033197926660]  INFO -- : receive block= 1, txs: 0
I, [2019-05-31T16:29:19.824213 #158 #47033197926660]  INFO -- : send message getdata
I, [2019-05-31T16:29:19.828192 #158 #47033197923780]  INFO -- : [172.28.3.4:18444] process command headers.
I, [2019-05-31T16:29:19.828324 #158 #47033197923780]  INFO -- : receive headers message.
I, [2019-05-31T16:29:19.828442 #158 #47033197923780]  INFO -- : append header 3a140cfb1851c1e56d3d0db34bd5da00b1469e71494ec58a92594548356d9d5c
I, [2019-05-31T16:29:19.829012 #158 #47033197923780]  INFO -- : [172.28.3.4:18444] start block header download.
I, [2019-05-31T16:29:19.829118 #158 #47033197923780]  INFO -- : send message getheaders
I, [2019-05-31T16:29:19.830995 #158 #47033197928180]  INFO -- : [172.28.3.2:18444] process command inv.
I, [2019-05-31T16:29:19.831128 #158 #47033197928180]  INFO -- : receive inv message.
I, [2019-05-31T16:29:19.831221 #158 #47033197928180]  INFO -- : receive block= 1, txs: 0
I, [2019-05-31T16:29:19.831493 #158 #47033197928180]  INFO -- : send message getdata
I, [2019-05-31T16:29:19.831664 #158 #47033197928180]  INFO -- : [172.28.3.1:18444] process command merkleblock.
I, [2019-05-31T16:29:19.833169 #158 #47033197928180]  INFO -- : receive merkle block message. {"hashes":["36a39ed285a4ffdb141c16af1eb1029bf18a18a7fdc54c70561d9371714f0c74"],"header":"#<Bitcoin::BlockHeader:0x0000558d89b37a88>","tx_count":1,"flags":"01"}
I, [2019-05-31T16:29:19.838089 #158 #47033197928180]  INFO -- : [172.28.3.1:18444] process command tx.
I, [2019-05-31T16:29:19.848502 #158 #47033197881160]  INFO -- : [172.28.3.3:18444] process command inv.
I, [2019-05-31T16:29:19.848708 #158 #47033197881160]  INFO -- : receive inv message.
I, [2019-05-31T16:29:19.848793 #158 #47033197881160]  INFO -- : receive block= 1, txs: 0
I, [2019-05-31T16:29:19.848877 #158 #47033197881160]  INFO -- : send message getdata
I, [2019-05-31T16:29:19.849989 #158 #47033197928180]  INFO -- : receive tx message. {"tx":"#<Bitcoin::Tx:0x0000558d892c73f8>","use_segwit":false}
E, [2019-05-31T16:29:19.920867 #158 #47033187231140] ERROR -- : error occurred. undefined method `partial?' for nil:NilClass
E, [2019-05-31T16:29:19.921193 #158 #47033187231140] ERROR -- : ["/usr/local/bundle/bundler/gems/bitcoinrb-1ef6eaf9d15a/lib/bitcoin/merkle_tree.rb:106:in `next_partial'", "/usr/local/bundle/bundler/gems/bitcoinrb-1ef6eaf9d15a/lib/bitcoin/merkle_tree.rb:37:in `block in build_partial'", "/usr/local/bundle/bundler/gems/bitcoinrb-1ef6eaf9d15a/lib/bitcoin/merkle_tree.rb:31:in `each'", "/usr/local/bundle/bundler/gems/bitcoinrb-1ef6eaf9d15a/lib/bitcoin/merkle_tree.rb:31:in `build_partial'", "/home/wallet/app/lib/bitcoin/wallet/utxo_handler.rb:80:in `save_tx_position'", "/home/wallet/app/lib/bitcoin/wallet/utxo_handler.rb:73:in `merkleblock'", "/home/wallet/app/lib/bitcoin/wallet/utxo_handler.rb:17:in `update'", "/usr/local/lib/ruby/2.5.0/observer.rb:197:in `block in notify_observers'", "/usr/local/lib/ruby/2.5.0/observer.rb:196:in `each'", "/usr/local/lib/ruby/2.5.0/observer.rb:196:in `notify_observers'", "/usr/local/bundle/bundler/gems/bitcoinrb-1ef6eaf9d15a/lib/bitcoin/network/peer.rb:195:in `handle_merkle_block'", "/usr/local/bundle/bundler/gems/bitcoinrb-1ef6eaf9d15a/lib/bitcoin/network/message_handler.rb:229:in `on_merkle_block'", "/usr/local/bundle/bundler/gems/bitcoinrb-1ef6eaf9d15a/lib/bitcoin/network/message_handler.rb:94:in `handle_command'", "/usr/local/bundle/bundler/gems/bitcoinrb-1ef6eaf9d15a/lib/bitcoin/network/message_handler.rb:46:in `block in defer_handle_command'", "/usr/local/bundle/gems/eventmachine-1.2.7/lib/eventmachine.rb:1077:in `block in spawn_threadpool'"]
I, [2019-05-31T16:29:19.921350 #158 #47033187231140]  INFO -- : close connection with 172.28.3.4:18444. terminate
I, [2019-05-31T16:29:19.921460 #158 #47033187231140]  INFO -- : close connection with 172.28.3.1:18444. terminate
I, [2019-05-31T16:29:19.921545 #158 #47033187231140]  INFO -- : close connection with 172.28.3.2:18444. terminate
I, [2019-05-31T16:29:19.921635 #158 #47033187231140]  INFO -- : close connection with 172.28.3.3:18444. terminate
I, [2019-05-31T16:29:19.921729 #158 #47033187231140]  INFO -- : unbind. 172.28.3.1:18444
I, [2019-05-31T16:29:19.922016 #158 #47033187231140]  INFO -- : unbind. 172.28.3.4:18444
I, [2019-05-31T16:29:19.922383 #158 #47033187231140]  INFO -- : unbind. 172.28.3.2:18444
I, [2019-05-31T16:29:19.925973 #158 #47033187231140]  INFO -- : unbind. 172.28.3.3:18444

Bitcoin::Wallet::Base#watch_targets (Bitcoin::WalletAccount#watch_targets) is slow.

When I have about 30 addresses in my wallet, then the execution of watch_targets methods take more than 5 seconds.

c = Bitcoin::Node::Configuration.new(network: :regtest)
spv = Bitcoin::Node::SPV.new(c)

a = spv.wallet.accounts.first
=> 33

require 'benchmark';
Benchmark.measure { a.watch_targets }
=> #<Benchmark::Tms:0x000000010c78d5e0 @label="", @real=5.268244000035338, @cstime=0.0, @cutime=0.0, @stime=0.008423000000000014, @utime=5.255557, @total=5.263979999999999>

I found that this is because of performance of Bitcoin::Key.new, especially Bitcoin::Key.generate_pubkey

key = Bitcoin::Key.new
Benchmark.measure { key.send(:generate_pubkey, "11"*32, compressed: true) }
=> #<Benchmark::Tms:0x00007f994517b6d8 @label="", @real=0.06888899998739362, @cstime=0.0, @cutime=0.0, @stime=0.00018100000000001448, @utime=0.06847699999999435, @total=0.06865799999999436>

Key#generate_key spent about 0.07 seconds per once.
if i have 33 addresses, it takes 33 * 2 * 0.07 = 4.62 sec and it accounts for 88% of the total time.
( ExtKey#derive is called twice per one Account#watch_targets method)

SPV node does not receive tx message for addresses in wallet.

I have some keys in my spv wallet (testnet).
these are added bloom filter and watch_targets when connection is established.


...(connect peer)...

irb(main):019:0> spv.wallet.watch_targets.first
=> "5c41d00108478898102f5d3ce24c1b94bdd17efe"

irb(main):021:0> extkey = spv.wallet.accounts.first.derived_receive_keys.first
=> #<Bitcoin::ExtPubkey:0x007f9d4a950cd8 @ver="045f1cf6", @depth=5, @parent_fingerprint="a98946f5", @number=0, @chain_code="-*~$r\x9A,)16\x9C\xD2\xB3\xC3\xBA\x100\x81C\xCA\xCDq\x95p\xAC%\x7F\xE1Q\xC0Z\x19", @pubkey="035519a8837c17b239464f788fc05dee5ef3ff6a198374235a934920d50dc524b8">

irb(main):022:0> extkey.addr
=> "tb1qt3qaqqggg7yfsyp0t57wynqmjj7azlh7dlxugs"

irb(main):029:0> extkey.hash160
=> "5c41d00108478898102f5d3ce24c1b94bdd17efe"

when I send bitcoin to tb1qt3qaqqggg7yfsyp0t57wynqmjj7azlh7dlxugs, spv node did not receive any tx message.

https://testnet.blockchain.info/tx/ddcefb20c48131f9c985a374fc39f595408ebe3b62f8bafae141dea1392fa40e

output script is :

0[] PUSHDATA(20)[5c41d00108478898102f5d3ce24c1b94bdd17efe]

I'm afraid that reversing addresses is not required when adding them to bloom filter

def setup_filter
  @bloom = Bitcoin::BloomFilter.create_filter(512, 0.01)
  wallet.watch_targets.each{|t|bloom.add(t.htb.reverse)} if wallet
end

Disconnected to bitcoin-core node.

I tried to connect bitcoin-core nodes("172.18.1.1", "172.18.1.2", "172.18.1.3") as follows.
They were running in regtest mode.

c = Bitcoin::Node::Configuration.new(network: :regtest, connect:["172.18.1.1", "172.18.1.2", "172.18.1.3"])
spv = Bitcoin::Node::SPV.new(c)
Thread.start{ spv.run }

Then each node accepted the connection from bitcoinrb once but disconnected immediately.

Bitcoin's log is here: (-debug=net is specified)

2020-06-28T09:51:59Z Added connection peer=328
2020-06-28T09:51:59Z connection from 172.18.5.1:35578 accepted
2020-06-28T09:51:59Z received: version (103 bytes) peer=328
2020-06-28T09:51:59Z sending version (102 bytes) peer=328
2020-06-28T09:51:59Z send version message: version 70015, blocks=0, us=[::]:0, peer=328
2020-06-28T09:51:59Z sending verack (0 bytes) peer=328
2020-06-28T09:51:59Z receive version message: /bitcoinrb:0.4.0/: version 70013, blocks=1, us=127.0.0.1:18444, peer=328
2020-06-28T09:51:59Z received: verack (0 bytes) peer=328
2020-06-28T09:51:59Z sending sendheaders (0 bytes) peer=328
2020-06-28T09:51:59Z sending ping (8 bytes) peer=328
2020-06-28T09:51:59Z sending feefilter (8 bytes) peer=328
2020-06-28T09:51:59Z received: filterload (625 bytes) peer=328
2020-06-28T09:51:59Z Misbehaving: 172.18.5.1:35578 peer=328 (0 -> 100) BAN THRESHOLD EXCEEDED
2020-06-28T09:51:59Z ProcessMessages(filterload, 625 bytes) FAILED peer=328
2020-06-28T09:51:59Z disconnecting peer=328

Bitcoin::Key#to_point raises NameError when using libsecp256k1

Bitcoin::Key#to_point raises NameError when using libsecp256k1

constant Bitcoin::Secp256k1::GROUP should be defined in lib/bitcoin/secp256k1.rb instead of lib/bitcoin/secp256k1/ruby.rb ???

$ SECP256K1_LIB_PATH=./spec/lib/libsecp256k1.dylib ./bin/console 
irb(main):001:0> Bitcoin::Key.new(priv_key: "11"*32).to_point
Traceback (most recent call last):
        3: from ./bin/console:14:in `<main>'
        2: from (irb):1
        1: from /Users/H_Yamaguchi/Documents/Projects/my/bitcoinrb/lib/bitcoin/key.rb:106:in `to_point'
NameError (uninitialized constant Bitcoin::Secp256k1::GROUP)

NoMethodError undefined method `pushed_data` for nil:NilClass in chunks `"OP_RETURN" ` case

error happen in https://github.com/haw-itn/bitcoinrb/blob/master/lib/bitcoin/script/script.rb#L178

using transaction:

{
  “hex”: “010000000410ed34ec603feb4cb1bd26144b1fb215ed61e5e25ce85e595c342c2d640db8a7000000006a4730440220386e5797a5ea73b026da0eaf20ad597437e87c51b41df152cfcee60e14eb3ffc0220268d07db2b486ba21d4c99c1fa8361c128e97ea4d954e12128d15029bb781584822103a3716c681da7d08ea628811afa0002b9db1edb8206895e525f5e884e1164bb61ffffffffeb01e955f90b2ee74a8c9a358ef4a55223e298c12371cc7f0f1d4331c056499d000000006a473044022035b3f1102de5251767bbefb38452159a222c5046f65c303f38eed38e463f52ae02203fa3227c583e2b2a873c218a6242ea3a70103d7b5733c67f33754557dfd29431822103a3716c681da7d08ea628811afa0002b9db1edb8206895e525f5e884e1164bb61ffffffffb400a7956525f17823d37029300a1ccf41d033d003d943f42cf155f7ac7a061b010000006a473044022025fd93f6ce5a01091df59b252a9fe25e27aa4143586989a9065a58d3a0e4b72702205c633b2f04dbfb8d98d6a64404b72941dcf0ef40472d922273a7004eeb9fc2e4822103a3716c681da7d08ea628811afa0002b9db1edb8206895e525f5e884e1164bb61ffffffff9da7c020892acae83c4066d60de3f7157c084f8eea60b29d30f9ea9bbbb1262f000000006b483045022100f607d5dfc9519971671187e3e912156fe3816fe2b281ee0e06c07a5881eef4b302200492134ac1f970e15512a16bf92cfc08849cc677792e0c460e68064c68d1065c822103a3716c681da7d08ea628811afa0002b9db1edb8206895e525f5e884e1164bb61ffffffff010000000000000000016a00000000",
  “txid”: “ebbe3f95a6fe7639100f44c30eca2b12447b0b93200becf5a5405486575b8ff2",
  “hash”: “ebbe3f95a6fe7639100f44c30eca2b12447b0b93200becf5a5405486575b8ff2",
  “size”: 609,
  “vsize”: 609,
  “version”: 1,
  “locktime”: 0,
  “vin”: [
    {
      “txid”: “a7b80d642d2c345c595ee85ce2e561ed15b21f4b1426bdb14ceb3f60ec34ed10”,
      “vout”: 0,
      “scriptSig”: {
        “asm”: “30440220386e5797a5ea73b026da0eaf20ad597437e87c51b41df152cfcee60e14eb3ffc0220268d07db2b486ba21d4c99c1fa8361c128e97ea4d954e12128d15029bb781584[NONE|ANYONECANPAY] 03a3716c681da7d08ea628811afa0002b9db1edb8206895e525f5e884e1164bb61”,
        “hex”: “4730440220386e5797a5ea73b026da0eaf20ad597437e87c51b41df152cfcee60e14eb3ffc0220268d07db2b486ba21d4c99c1fa8361c128e97ea4d954e12128d15029bb781584822103a3716c681da7d08ea628811afa0002b9db1edb8206895e525f5e884e1164bb61”
      },
      “sequence”: 4294967295
    }, 
    {
      “txid”: “9d4956c031431d0f7fcc7123c198e22352a5f48e359a8c4ae72e0bf955e901eb”,
      “vout”: 0,
      “scriptSig”: {
        “asm”: “3044022035b3f1102de5251767bbefb38452159a222c5046f65c303f38eed38e463f52ae02203fa3227c583e2b2a873c218a6242ea3a70103d7b5733c67f33754557dfd29431[NONE|ANYONECANPAY] 03a3716c681da7d08ea628811afa0002b9db1edb8206895e525f5e884e1164bb61",
        “hex”: “473044022035b3f1102de5251767bbefb38452159a222c5046f65c303f38eed38e463f52ae02203fa3227c583e2b2a873c218a6242ea3a70103d7b5733c67f33754557dfd29431822103a3716c681da7d08ea628811afa0002b9db1edb8206895e525f5e884e1164bb61"
      },
      “sequence”: 4294967295
    }, 
    {
      “txid”: “1b067aacf755f12cf443d903d033d041cf1c0a302970d32378f1256595a700b4”,
      “vout”: 1,
      “scriptSig”: {
        “asm”: “3044022025fd93f6ce5a01091df59b252a9fe25e27aa4143586989a9065a58d3a0e4b72702205c633b2f04dbfb8d98d6a64404b72941dcf0ef40472d922273a7004eeb9fc2e4[NONE|ANYONECANPAY] 03a3716c681da7d08ea628811afa0002b9db1edb8206895e525f5e884e1164bb61”,
        “hex”: “473044022025fd93f6ce5a01091df59b252a9fe25e27aa4143586989a9065a58d3a0e4b72702205c633b2f04dbfb8d98d6a64404b72941dcf0ef40472d922273a7004eeb9fc2e4822103a3716c681da7d08ea628811afa0002b9db1edb8206895e525f5e884e1164bb61”
      },
      “sequence”: 4294967295
    }, 
    {
      “txid”: “2f26b1bb9beaf9309db260ea8e4f087c15f7e30dd666403ce8ca2a8920c0a79d”,
      “vout”: 0,
      “scriptSig”: {
        “asm”: “3045022100f607d5dfc9519971671187e3e912156fe3816fe2b281ee0e06c07a5881eef4b302200492134ac1f970e15512a16bf92cfc08849cc677792e0c460e68064c68d1065c[NONE|ANYONECANPAY] 03a3716c681da7d08ea628811afa0002b9db1edb8206895e525f5e884e1164bb61",
        “hex”: “483045022100f607d5dfc9519971671187e3e912156fe3816fe2b281ee0e06c07a5881eef4b302200492134ac1f970e15512a16bf92cfc08849cc677792e0c460e68064c68d1065c822103a3716c681da7d08ea628811afa0002b9db1edb8206895e525f5e884e1164bb61"
      },
      “sequence”: 4294967295
    }
  ],
  “vout”: [
    {
      “value”: 0.00000000,
      “n”: 0,
      “scriptPubKey”: {
        “asm”: “OP_RETURN”,
        “hex”: “6a”,
        “type”: “nulldata”
      }
    }
  ],
  “blockhash”: “000000005d25aa183eb4e16dc441b47e456b629b91b4510255c84d99858c3c6d”,
  “confirmations”: 1132609,
  “time”: 1393543407,
  “blocktime”: 1393543407
}

SpvChain#find_entry_by_height(height) returns wrong block for height below 16

chain.find_entry_by_height(1) returns 16th block
chain.find_entry_by_height(2) returns 32th block
...

irb(main):001:0> c = Bitcoin::Node::Configuration.new(network: :regtest)
irb(main):003:0> spv = Bitcoin::Node::SPV.new(c)

irb(main):004:0> spv.chain.find_entry_by_height(1)
=> #<Bitcoin::Store::ChainEntry:0x007f8623194078 @header=#<Bitcoin::BlockHeader:0x007f86231940f0 @version=536870912, 
@prev_hash="17c43d59fd61f0285f714fef20d99123fb17b6113c5b1b0b7e9bf134b4a18553", 
@merkle_root="62cfba7a97a118e5f8dee1d3c2b61a911de8c16a91c03f89dc90c57a75be212a", 
@time=1508298370, @bits=545259519, @nonce=0>, @height=16>

irb(main):005:0> spv.chain.find_entry_by_height(15)
=> #<Bitcoin::Store::ChainEntry:0x007f8624123660 @header=#<Bitcoin::BlockHeader:0x007f8624123688 @version=805306371, 
@prev_hash="1f305cf6495386247a331caf06974f84778d5a60ec969cc81906cbf49a27fe5e", 
@merkle_root="b0575be6cb588bcce660b4095b1f38551def636f092ad3ff9882ae01bc8f5bcf", 
@time=1508298911, @bits=545259519, @nonce=0>, @height=240>

irb(main):006:0> spv.chain.find_entry_by_height(16)
=> #<Bitcoin::Store::ChainEntry:0x007f8622a4ccc0 @header=#<Bitcoin::BlockHeader:0x007f8622a4cce8 @version=536870912, 
@prev_hash="17c43d59fd61f0285f714fef20d99123fb17b6113c5b1b0b7e9bf134b4a18553", 
@merkle_root="62cfba7a97a118e5f8dee1d3c2b61a911de8c16a91c03f89dc90c57a75be212a", 
@time=1508298370, @bits=545259519, @nonce=0>, @height=16>

Spec for wallet.rb fails.

$ bundle exec rspec ./spec/bitcoin/wallet/wallet_spec.rb 

Bitcoin::Wallet
  #load
    existing wallet
      should return wallet (FAILED - 1)
    dose not exist wallet
      should raise error (FAILED - 2)
  #create
    should create new wallet
      should be create (FAILED - 3)
    same wallet_id already exist
      should raise error (FAILED - 4)
  #wallets_path
    should return wallet dir. (FAILED - 5)
  #create_account
    should be created (FAILED - 6)

Failures:

  1) Bitcoin::Wallet#load existing wallet should return wallet
     Got 0 failures and 2 other errors:

     1.1) Failure/Error: @level_db = ::LevelDB::DB.new(path)
          
          LevelDB::Error:
            IO error: lock /var/folders/gl/_0rgn1fd3tq54qlrq8rfkfw00000gp/T/wallet/wallet1//LOCK: already held by process
          # ./lib/bitcoin/wallet/db.rb:16:in `initialize'
          # ./lib/bitcoin/wallet/base.rb:85:in `new'
          # ./lib/bitcoin/wallet/base.rb:85:in `initialize'
          # ./lib/bitcoin/wallet/base.rb:33:in `new'
          # ./lib/bitcoin/wallet/base.rb:33:in `load'
          # ./spec/bitcoin/wallet/wallet_spec.rb:11:in `block (4 levels) in <top (required)>'
          # ./spec/bitcoin/wallet/wallet_spec.rb:13:in `block (4 levels) in <top (required)>'

     1.2) Failure/Error: @level_db = ::LevelDB::DB.new(path)
          
          LevelDB::Error:
            IO error: lock /var/folders/gl/_0rgn1fd3tq54qlrq8rfkfw00000gp/T/wallet/wallet1//LOCK: already held by process
          # ./lib/bitcoin/wallet/db.rb:16:in `initialize'
          # ./lib/bitcoin/wallet/base.rb:85:in `new'
          # ./lib/bitcoin/wallet/base.rb:85:in `initialize'
          # ./lib/bitcoin/wallet/base.rb:33:in `new'
          # ./lib/bitcoin/wallet/base.rb:33:in `load'
          # ./spec/bitcoin/wallet/wallet_spec.rb:6:in `block (2 levels) in <top (required)>'
          # ./spec/bitcoin/wallet/wallet_spec.rb:7:in `block (2 levels) in <top (required)>'

  2) Bitcoin::Wallet#load dose not exist wallet should raise error
     Got 0 failures and 2 other errors:

     2.1) Failure/Error: @level_db = ::LevelDB::DB.new(path)
          
          LevelDB::Error:
            IO error: lock /var/folders/gl/_0rgn1fd3tq54qlrq8rfkfw00000gp/T/wallet/wallet1//LOCK: already held by process
          # ./lib/bitcoin/wallet/db.rb:16:in `initialize'
          # ./lib/bitcoin/wallet/base.rb:85:in `new'
          # ./lib/bitcoin/wallet/base.rb:85:in `initialize'
          # ./lib/bitcoin/wallet/base.rb:20:in `new'
          # ./lib/bitcoin/wallet/base.rb:20:in `create'
          # ./spec/spec_helper.rb:54:in `create_test_wallet'
          # ./spec/bitcoin/wallet/wallet_spec.rb:5:in `block (2 levels) in <top (required)>'

     2.2) Failure/Error: @level_db = ::LevelDB::DB.new(path)
          
          LevelDB::Error:
            IO error: lock /var/folders/gl/_0rgn1fd3tq54qlrq8rfkfw00000gp/T/wallet/wallet1//LOCK: already held by process
          # ./lib/bitcoin/wallet/db.rb:16:in `initialize'
          # ./lib/bitcoin/wallet/base.rb:85:in `new'
          # ./lib/bitcoin/wallet/base.rb:85:in `initialize'
          # ./lib/bitcoin/wallet/base.rb:33:in `new'
          # ./lib/bitcoin/wallet/base.rb:33:in `load'
          # ./spec/bitcoin/wallet/wallet_spec.rb:6:in `block (2 levels) in <top (required)>'
          # ./spec/bitcoin/wallet/wallet_spec.rb:7:in `block (2 levels) in <top (required)>'

  3) Bitcoin::Wallet#create should create new wallet should be create
     Got 0 failures and 2 other errors:

     3.1) Failure/Error: @level_db = ::LevelDB::DB.new(path)
          
          LevelDB::Error:
            IO error: lock /var/folders/gl/_0rgn1fd3tq54qlrq8rfkfw00000gp/T/wallet/wallet1//LOCK: already held by process
          # ./lib/bitcoin/wallet/db.rb:16:in `initialize'
          # ./lib/bitcoin/wallet/base.rb:85:in `new'
          # ./lib/bitcoin/wallet/base.rb:85:in `initialize'
          # ./lib/bitcoin/wallet/base.rb:20:in `new'
          # ./lib/bitcoin/wallet/base.rb:20:in `create'
          # ./spec/spec_helper.rb:54:in `create_test_wallet'
          # ./spec/bitcoin/wallet/wallet_spec.rb:5:in `block (2 levels) in <top (required)>'

     3.2) Failure/Error: @level_db = ::LevelDB::DB.new(path)
          
          LevelDB::Error:
            IO error: lock /var/folders/gl/_0rgn1fd3tq54qlrq8rfkfw00000gp/T/wallet/wallet1//LOCK: already held by process
          # ./lib/bitcoin/wallet/db.rb:16:in `initialize'
          # ./lib/bitcoin/wallet/base.rb:85:in `new'
          # ./lib/bitcoin/wallet/base.rb:85:in `initialize'
          # ./lib/bitcoin/wallet/base.rb:33:in `new'
          # ./lib/bitcoin/wallet/base.rb:33:in `load'
          # ./spec/bitcoin/wallet/wallet_spec.rb:6:in `block (2 levels) in <top (required)>'
          # ./spec/bitcoin/wallet/wallet_spec.rb:7:in `block (2 levels) in <top (required)>'

  4) Bitcoin::Wallet#create same wallet_id already exist should raise error
     Got 0 failures and 2 other errors:

     4.1) Failure/Error: @level_db = ::LevelDB::DB.new(path)
          
          LevelDB::Error:
            IO error: lock /var/folders/gl/_0rgn1fd3tq54qlrq8rfkfw00000gp/T/wallet/wallet1//LOCK: already held by process
          # ./lib/bitcoin/wallet/db.rb:16:in `initialize'
          # ./lib/bitcoin/wallet/base.rb:85:in `new'
          # ./lib/bitcoin/wallet/base.rb:85:in `initialize'
          # ./lib/bitcoin/wallet/base.rb:20:in `new'
          # ./lib/bitcoin/wallet/base.rb:20:in `create'
          # ./spec/spec_helper.rb:54:in `create_test_wallet'
          # ./spec/bitcoin/wallet/wallet_spec.rb:5:in `block (2 levels) in <top (required)>'

     4.2) Failure/Error: @level_db = ::LevelDB::DB.new(path)
          
          LevelDB::Error:
            IO error: lock /var/folders/gl/_0rgn1fd3tq54qlrq8rfkfw00000gp/T/wallet/wallet1//LOCK: already held by process
          # ./lib/bitcoin/wallet/db.rb:16:in `initialize'
          # ./lib/bitcoin/wallet/base.rb:85:in `new'
          # ./lib/bitcoin/wallet/base.rb:85:in `initialize'
          # ./lib/bitcoin/wallet/base.rb:33:in `new'
          # ./lib/bitcoin/wallet/base.rb:33:in `load'
          # ./spec/bitcoin/wallet/wallet_spec.rb:6:in `block (2 levels) in <top (required)>'
          # ./spec/bitcoin/wallet/wallet_spec.rb:7:in `block (2 levels) in <top (required)>'

  5) Bitcoin::Wallet#wallets_path should return wallet dir.
     Got 0 failures and 2 other errors:

     5.1) Failure/Error: @level_db = ::LevelDB::DB.new(path)
          
          LevelDB::Error:
            IO error: lock /var/folders/gl/_0rgn1fd3tq54qlrq8rfkfw00000gp/T/wallet/wallet1//LOCK: already held by process
          # ./lib/bitcoin/wallet/db.rb:16:in `initialize'
          # ./lib/bitcoin/wallet/base.rb:85:in `new'
          # ./lib/bitcoin/wallet/base.rb:85:in `initialize'
          # ./lib/bitcoin/wallet/base.rb:20:in `new'
          # ./lib/bitcoin/wallet/base.rb:20:in `create'
          # ./spec/spec_helper.rb:54:in `create_test_wallet'
          # ./spec/bitcoin/wallet/wallet_spec.rb:5:in `block (2 levels) in <top (required)>'

     5.2) Failure/Error: @level_db = ::LevelDB::DB.new(path)
          
          LevelDB::Error:
            IO error: lock /var/folders/gl/_0rgn1fd3tq54qlrq8rfkfw00000gp/T/wallet/wallet1//LOCK: already held by process
          # ./lib/bitcoin/wallet/db.rb:16:in `initialize'
          # ./lib/bitcoin/wallet/base.rb:85:in `new'
          # ./lib/bitcoin/wallet/base.rb:85:in `initialize'
          # ./lib/bitcoin/wallet/base.rb:33:in `new'
          # ./lib/bitcoin/wallet/base.rb:33:in `load'
          # ./spec/bitcoin/wallet/wallet_spec.rb:6:in `block (2 levels) in <top (required)>'
          # ./spec/bitcoin/wallet/wallet_spec.rb:7:in `block (2 levels) in <top (required)>'

  6) Bitcoin::Wallet#create_account should be created
     Got 0 failures and 2 other errors:

     6.1) Failure/Error: @level_db = ::LevelDB::DB.new(path)
          
          LevelDB::Error:
            IO error: lock /var/folders/gl/_0rgn1fd3tq54qlrq8rfkfw00000gp/T/wallet/wallet1//LOCK: already held by process
          # ./lib/bitcoin/wallet/db.rb:16:in `initialize'
          # ./lib/bitcoin/wallet/base.rb:85:in `new'
          # ./lib/bitcoin/wallet/base.rb:85:in `initialize'
          # ./lib/bitcoin/wallet/base.rb:20:in `new'
          # ./lib/bitcoin/wallet/base.rb:20:in `create'
          # ./spec/spec_helper.rb:54:in `create_test_wallet'
          # ./spec/bitcoin/wallet/wallet_spec.rb:5:in `block (2 levels) in <top (required)>'

     6.2) Failure/Error: @level_db = ::LevelDB::DB.new(path)
          
          LevelDB::Error:
            IO error: lock /var/folders/gl/_0rgn1fd3tq54qlrq8rfkfw00000gp/T/wallet/wallet1//LOCK: already held by process
          # ./lib/bitcoin/wallet/db.rb:16:in `initialize'
          # ./lib/bitcoin/wallet/base.rb:85:in `new'
          # ./lib/bitcoin/wallet/base.rb:85:in `initialize'
          # ./lib/bitcoin/wallet/base.rb:33:in `new'
          # ./lib/bitcoin/wallet/base.rb:33:in `load'
          # ./spec/bitcoin/wallet/wallet_spec.rb:6:in `block (2 levels) in <top (required)>'
          # ./spec/bitcoin/wallet/wallet_spec.rb:7:in `block (2 levels) in <top (required)>'

Finished in 0.04242 seconds (files took 0.29127 seconds to load)
6 examples, 6 failures

Failed examples:

rspec ./spec/bitcoin/wallet/wallet_spec.rb:12 # Bitcoin::Wallet#load existing wallet should return wallet
rspec ./spec/bitcoin/wallet/wallet_spec.rb:19 # Bitcoin::Wallet#load dose not exist wallet should raise error
rspec ./spec/bitcoin/wallet/wallet_spec.rb:28 # Bitcoin::Wallet#create should create new wallet should be create
rspec ./spec/bitcoin/wallet/wallet_spec.rb:39 # Bitcoin::Wallet#create same wallet_id already exist should raise error
rspec ./spec/bitcoin/wallet/wallet_spec.rb:47 # Bitcoin::Wallet#wallets_path should return wallet dir.
rspec ./spec/bitcoin/wallet/wallet_spec.rb:57 # Bitcoin::Wallet#create_account should be created

Method to restore mnemonic to db

Wallet::Base class only has create method which create new mnemonic.
It is useful if there is method which restore master key from mnemonic.

Is this in the scope of this library?
If so, I will make PR.

Bitcoin::PSBT::Tx.parse_from_payload return wrong previous tx hash

Bitcoin.chain_params = :testnet

payload = '70736274ff010053020000000113a74a3fb29ebc282d3cbf0a8bee086188d7e533d71e976419c955215ff50d530000000000ffffffff01a8c8fa020000000017a914ffd0dbb44402d5f8f12d9ba5b484a2c1bb47da4287000000000001012030dcfa020000000017a9144e269b90bfdc52dbd46b13eaaefaa55dcffda15787220203c1917544fd6f2c832618d41eace312600d75da50005a467cc82b4ef81555097b47304402202eda814690158067e4822e963454a503814bbb5ae7450b0bdc7fa6b22d95945902204f1741cc533134a0a0137ad86ba8251ea4cd3aac9f3d500f74085284e8a7b2640101042200200fc49349c98ac78e320d9a0249af566fea3d22d801abc52884da5fddaf736f8d010547522103c1917544fd6f2c832618d41eace312600d75da50005a467cc82b4ef81555097b210397923a255b75bd469886fd1564de7372a54dc8fd348499c25ca88d8383edc26352ae0000'
psbt = Bitcoin::PSBT::Tx.parse_from_payload(payload.htb)
psbt.tx.inputs[0].out_point.hash # 13a74a3fb29ebc282d3cbf0a8bee086188d7e533d71e976419c955215ff50d53

Expected: 530df55f2155c91964971ed733e5d7886108ee8b0abf3c2d28bc9eb23f4aa713

UTXO management on bitcoinrb

We need to manage UTXO on bitcoinrb.

Since bitcoinrb notifies tx message to applications, the applications can manage UTXO related to the wallet.
(#20)

But in some cases, it is preferred that bitcoinrb itself manages UTXO.
(especially if multiple apps should access the same utxos)

I implemented a thin wrapper library of bitcoinrb and are trying to manage UTXO in bitcoinrb (experimentally).
(https://github.com/Yamaguchi/bitcoinrb-grpc)

If possible, just porting this code should be able to manage UTXO.

  • receive notification (UtxoHandler)
  • store it (UtxoDb)
  • add rpc interface "listunspent" and "getbalance" by extending rpc/request_handler.rb and
  • add rpc "signrawtransaction", as well

Note: "bitcoinrb-grpc" includes some features about open-assets-protocol. these should be left it

Creating a wallet after changing Bitcoin.chain_params fails.

(1)Create a wallet on mainnet(e.g. id = 99999)
(2)Close wallet.
(3)Change chain with Bitcoin.chain_params = :regtest
(4)Create another wallet with same id as mainnet on regtest.

I expected the wallet files are created on the regtest path ~/.bitcoinrb/regtest/db/wallet/wallet99999/
,but it raises an error with message wallet_id : 99999 already exist.

this is because constant Bitcoin::Wallet::Base::DEFAULT_PATH_PREFIX does not change when chain_params is changed.


$ ./bin/console 
irb(main):001:0> 
irb(main):002:0> 
irb(main):003:0> wallet = Bitcoin::Wallet::Base.create(99999)
=> #<Bitcoin::Wallet::Base:0x00007fb6fe930730 @path="/Users/h_yamaguchi/.bitcoinrb/mainnet/db/wallet/wallet99999/", @db=#<Bitcoin::Wallet::DB:0x000000011038bd08 @level_db=<LevelDB::DB "/Users/h_yamaguchi/.bitcoinrb/mainnet/db/wallet/wallet99999/">, @master_key=#<Bitcoin::Wallet::MasterKey:0x00007fb6fe147ed8 @mnemonic=["filter", "symptom", "bonus", "around", "accuse", "when", "accident", "arctic", "raven", "change", "dilemma", "pave", "general", "argue", "whip", "soup", "uncle", "beef", "solar", "happy", "together", "eyebrow", "alter", "deliver"], @seed="220193b9ec78a6edf6081aaec0c2068a7d4d3b8c5eeebc6348ba9fa5b974b8656a38817c5ee37a6b66a73c7f18b309ae9d3197caa83ce4019e3aa1bb9a9d6959", @encrypted=false, @salt="">>, @wallet_id=99999>
irb(main):004:0> wallet.close
=> true
irb(main):005:0> 
irb(main):006:0> Bitcoin.chain_params = :regtest
=> :regtest
irb(main):007:0> wallet = Bitcoin::Wallet::Base.create(99999)
Traceback (most recent call last):
        3: from ./bin/console:14:in `<main>'
        2: from (irb):7
        1: from /Users/h_yamaguchi/Documents/Projects/bitcoinrb/lib/bitcoin/wallet/base.rb:20:in `create'
ArgumentError (wallet_id : 99999 already exist.)
irb(main):008:0> 

Bitcoin::Script.parse_from_addr("tb1qft3tvl3nu7zzggg5unpvwzyg7y6tnwhpm546xt") in Ruby 3.0.2 (ArgumentError)

Bitcoin :: Script.parse_from_addr ("tb1qft3tvl3nu7zzggg5unpvwzyg7y6tnwhpm546xt") works fine in Ruby 3.0.1. but, in Ruby 3.0.2 it causes an error

home/yamasaki/.rbenv/versions/3.0.2/lib/ruby/gems/3.0.0/gems/bitcoinrb-0.8.0/lib/bitcoin/script/script.rb:96:in rescue in rescue in parse_from_addr': Invalid address. (ArgumentError) from /home/yamasaki/.rbenv/versions/3.0.2/lib/ruby/gems/3.0.0/gems/bitcoinrb-0.8.0/lib/bitcoin/script/script.rb:93:in rescue in parse_from_addr'
from /home/yamasaki/.rbenv/versions/3.0.2/lib/ruby/gems/3.0.0/gems/bitcoinrb-0.8.0/lib/bitcoin/script/script.rb:87:in parse_from_addr' from (irb):43:in

'
from /home/yamasaki/.rbenv/versions/3.0.2/lib/ruby/gems/3.0.0/gems/irb-1.3.7/exe/irb:11:in <top (required)>' from /home/yamasaki/.rbenv/versions/3.0.2/bin/irb:25:in load'
from /home/yamasaki/.rbenv/versions/3.0.2/bin/irb:25:in <main>' /home/yamasaki/.rbenv/versions/3.0.2/lib/ruby/gems/3.0.0/gems/bitcoinrb-0.8.0/lib/bitcoin/base58.rb:27:in block in decode': Value passed not a valid Base58 String. (ArgumentError)
from /home/yamasaki/.rbenv/versions/3.0.2/lib/ruby/gems/3.0.0/gems/bitcoinrb-0.8.0/lib/bitcoin/base58.rb:26:in each' from /home/yamasaki/.rbenv/versions/3.0.2/lib/ruby/gems/3.0.0/gems/bitcoinrb-0.8.0/lib/bitcoin/base58.rb:26:in each_with_index'
from /home/yamasaki/.rbenv/versions/3.0.2/lib/ruby/gems/3.0.0/gems/bitcoinrb-0.8.0/lib/bitcoin/base58.rb:26:in decode' from /home/yamasaki/.rbenv/versions/3.0.2/lib/ruby/gems/3.0.0/gems/bitcoinrb-0.8.0/lib/bitcoin/util.rb:121:in decode_base58_address'
from /home/yamasaki/.rbenv/versions/3.0.2/lib/ruby/gems/3.0.0/gems/bitcoinrb-0.8.0/lib/bitcoin/script/script.rb:94:in rescue in parse_from_addr' from /home/yamasaki/.rbenv/versions/3.0.2/lib/ruby/gems/3.0.0/gems/bitcoinrb-0.8.0/lib/bitcoin/script/script.rb:87:in parse_from_addr'
from (irb):43:in <main>' from /home/yamasaki/.rbenv/versions/3.0.2/lib/ruby/gems/3.0.0/gems/irb-1.3.7/exe/irb:11:in <top (required)>'
from /home/yamasaki/.rbenv/versions/3.0.2/bin/irb:25:in load' from /home/yamasaki/.rbenv/versions/3.0.2/bin/irb:25:in '
/home/yamasaki/.rbenv/versions/3.0.2/lib/ruby/gems/3.0.0/gems/psych-4.0.1/lib/psych/class_loader.rb:99:in find': Tried to load unspecified class: Bitcoin::ChainParams (Psych::DisallowedClass) from /home/yamasaki/.rbenv/versions/3.0.2/lib/ruby/gems/3.0.0/gems/psych-4.0.1/lib/psych/class_loader.rb:28:in load'
from /home/yamasaki/.rbenv/versions/3.0.2/lib/ruby/gems/3.0.0/gems/psych-4.0.1/lib/psych/visitors/to_ruby.rb:424:in resolve_class' from /home/yamasaki/.rbenv/versions/3.0.2/lib/ruby/gems/3.0.0/gems/psych-4.0.1/lib/psych/visitors/to_ruby.rb:213:in visit_Psych_Nodes_Mapping'
from /home/yamasaki/.rbenv/versions/3.0.2/lib/ruby/gems/3.0.0/gems/psych-4.0.1/lib/psych/visitors/visitor.rb:30:in visit' from /home/yamasaki/.rbenv/versions/3.0.2/lib/ruby/gems/3.0.0/gems/psych-4.0.1/lib/psych/visitors/visitor.rb:6:in accept'
from /home/yamasaki/.rbenv/versions/3.0.2/lib/ruby/gems/3.0.0/gems/psych-4.0.1/lib/psych/visitors/to_ruby.rb:35:in accept' from /home/yamasaki/.rbenv/versions/3.0.2/lib/ruby/gems/3.0.0/gems/psych-4.0.1/lib/psych/visitors/to_ruby.rb:318:in visit_Psych_Nodes_Document'
from /home/yamasaki/.rbenv/versions/3.0.2/lib/ruby/gems/3.0.0/gems/psych-4.0.1/lib/psych/visitors/visitor.rb:30:in visit' from /home/yamasaki/.rbenv/versions/3.0.2/lib/ruby/gems/3.0.0/gems/psych-4.0.1/lib/psych/visitors/visitor.rb:6:in accept'
from /home/yamasaki/.rbenv/versions/3.0.2/lib/ruby/gems/3.0.0/gems/psych-4.0.1/lib/psych/visitors/to_ruby.rb:35:in accept' from /home/yamasaki/.rbenv/versions/3.0.2/lib/ruby/gems/3.0.0/gems/psych-4.0.1/lib/psych.rb:335:in safe_load'
from /home/yamasaki/.rbenv/versions/3.0.2/lib/ruby/gems/3.0.0/gems/psych-4.0.1/lib/psych.rb:370:in load' from /home/yamasaki/.rbenv/versions/3.0.2/lib/ruby/gems/3.0.0/gems/bitcoinrb-0.8.0/lib/bitcoin/chain_params.rb:83:in init'
from /home/yamasaki/.rbenv/versions/3.0.2/lib/ruby/gems/3.0.0/gems/bitcoinrb-0.8.0/lib/bitcoin/chain_params.rb:56:in signet' from /home/yamasaki/.rbenv/versions/3.0.2/lib/ruby/gems/3.0.0/gems/bitcoinrb-0.8.0/lib/bitcoin.rb:91:in chain_params'
from /home/yamasaki/.rbenv/versions/3.0.2/lib/ruby/gems/3.0.0/gems/bitcoinrb-0.8.0/lib/bitcoin/script/script.rb:90:in `parse_from_addr'
... 4 levels...
i

Verifying signature with sighash_type fails when using secp256k1 library.

  1. Verifying the signature without sighash_type returns TRUE (using libsecp256k1 )
$ SECP256K1_LIB_PATH=./spec/lib/libsecp256k1.dylib ./bin/console 
irb(main):001:0> Bitcoin::Key.new(pubkey:"0251f5f22b4656f5991ec8c6928901d6f5f466286059f9108409d6f3e8b85c04f2").verify("304402201862554e825a38d3de70e31dd18315868dc217cb2c1131deafef3b4623bb82eb022055850038f75e9248f9290532df3c7fb0f3a965f03539e684b18ce690e13f1b92".htb,"7fa142ede3c5c87f3dcd61a9d4dd2e6d0f018c837d4ded05f5a22300b921b719".htb)
=> true
  1. Verifying the signature with sighash_type(01) returns FALSE (using libsecp256k1 )
irb(main):002:0> Bitcoin::Key.new(pubkey:"0251f5f22b4656f5991ec8c6928901d6f5f466286059f9108409d6f3e8b85c04f2").verify("304402201862554e825a38d3de70e31dd18315868dc217cb2c1131deafef3b4623bb82eb022055850038f75e9248f9290532df3c7fb0f3a965f03539e684b18ce690e13f1b9201".htb,"7fa142ede3c5c87f3dcd61a9d4dd2e6d0f018c837d4ded05f5a22300b921b719".htb)
=> false
  1. Verifying the signature without sighash_type returns TRUE (using ruby_ecdsa)
$ ./bin/console 
irb(main):001:0> Bitcoin::Key.new(pubkey:"0251f5f22b4656f5991ec8c6928901d6f5f466286059f9108409d6f3e8b85c04f2").verify("304402201862554e825a38d3de70e31dd18315868dc217cb2c1131deafef3b4623bb82eb022055850038f75e9248f9290532df3c7fb0f3a965f03539e684b18ce690e13f1b92".htb,"7fa142ede3c5c87f3dcd61a9d4dd2e6d0f018c837d4ded05f5a22300b921b719".htb)
=> true
  1. Verifying the signature with sighash_type(01) returns TRUE (using ruby_ecdsa)
irb(main):002:0> Bitcoin::Key.new(pubkey:"0251f5f22b4656f5991ec8c6928901d6f5f466286059f9108409d6f3e8b85c04f2").verify("304402201862554e825a38d3de70e31dd18315868dc217cb2c1131deafef3b4623bb82eb022055850038f75e9248f9290532df3c7fb0f3a965f03539e684b18ce690e13f1b9201".htb,"7fa142ede3c5c87f3dcd61a9d4dd2e6d0f018c837d4ded05f5a22300b921b719".htb)
=> true
irb(main):003:0> 

Bitcoin::Wallet::Base.current_wallet return wrong value when it include '-' in dir name.

Bitcoin::Wallet::Base Line 51:
wallet_id = path.delete(path_prefix + '/wallet').delete("/").to_i
It is failed when path_prefix include '-'.

Steps to Reproduce

irb(main):001:0>"/bitcoinrb-grpc/.bitcoinrb/regtest/db/wallet/wallet1/".delete("/bitcoinrb-grpc/.bitcoinrb/regtest/db/wallet/" + '/wallet').delete('/').to_i
=> -1

Expect

example: "/bitcoinrb-grpc/.bitcoinrb/regtest/db/wallet/wallet1/".delete("/bitcoinrb-grpc/.bitcoinrb/regtest/db/wallet/" + '/wallet').delete('/').to_i
result: 1

Actual

result: -1
application failed.

That is wrong use to String#delete.
String#delete can use range character.

irb(main):001:0> "12345".delete("1-3")
=> "45"

`psbt.to_base64` version v0.5.0 is different from version v0.4.0

I'm using v0.4.0, I got a difference base64 value after upgrading to v0.5.0. Could you help ?!

My code:

receipient_address = 'mnJ54cVoPcuBQCiLFzJsewtj1Nt6EFVHwo'
send_output_amount = 10000
change_output_amount = 964800

tx = Bitcoin::Tx.new
tx.version = 2

# Add inputs
tx_id = '7f70edc2bbd0affd41042b358880f61101bc47ae49da2435815b36c89b7bd75f'
output_index = 0
tx.in << Bitcoin::TxIn.new(out_point: Bitcoin::OutPoint.from_txid(tx_id, output_index))

# Add outputs
tx.out << Bitcoin::TxOut.new(value: send_output_amount, script_pubkey: Bitcoin::Script.parse_from_addr(receipient_address))
tx.out << Bitcoin::TxOut.new(value: change_output_amount, script_pubkey: Bitcoin::Script.parse_from_addr('2N4t9j1DcsRz3e5cG2px2LAgJf51X4gwTs4'))

psbt = Bitcoin::PSBT::Tx.new(tx)
prev_tx_hex = "010000000333dde3fedd5fe72b2f19e66c6fbc33c996a7391fb77d14272acddf63f905a740010000006a47304402201d4fa7f795a17fee374863a4fe58ac233c6672d52bb88ac76df60b35ff631f66022008e5510ae7397f79ed94b5425438dc8d7427252a7ab003b7d78ffea24c21d736012102256fac28ccd985b33bd2e7260242f4a1e5287b88387b533a385a9aab22550742ffffffffcd48e9e35ac5d63d1e33527d6af4f7047cb89508f35b473d56d75b6c679e72ef010000006b483045022100d48e11bd56236243400fa249b365fa5d64fa08fc55d1bd936f354dcc948699660220667e8a6591086ef59f48ae9741923a7a32e31154bea44538148875abdb3502b1012103ae2784a837787f818dc1ca79ee3299590ef54f702a7190bc19f69426ce6af7a8ffffffff2989d56a1733a270d48ae0c49da961f25a923d3db6fffd089f101e7ea57c0366000000006b483045022100eafae96096103d80f38c2d789621b331c329e56011154aeb580c7f01e151ff7f02201c7e96d030d3c0f92ec640e6448b2acb57bf5209df9d38e659f8cbcf956eab4001210222e73c0771d4900c66e45a88d8bbc13e9f3b14e2bce2677de5d59fc9dfe950d3ffffffff02f02d0f000000000017a9147fa5371be2349ec496ebd9134663f8db737d635f87df9e31070000000017a914653ff6f081b35f78fd874e54065767130dc093848700000000"
prev_tx = Bitcoin::Tx.parse_from_payload(prev_tx_hex.htb)
redeem_script = Bitcoin::Script.parse_from_payload('0020720653117b7ee3abbc5cdd5141d2ae58f40de43240417891003e99b117863bed'.htb)
witness_script = Bitcoin::Script.parse_from_payload('522103c1917544fd6f2c832618d41eace312600d75da50005a467cc82b4ef81555097b210283a5b7f3c199a9b2033dd14e69a51b2ec6a5d3c128901d36962180f79501bf5e52ae'.htb)
psbt.update!(prev_tx, redeem_script: redeem_script, witness_script: witness_script)
psbt.to_base64

Ver 0.4.0 return :

cHNidP8BAHUCAAAAAV/Xe5vINluBNSTaSa5HvAER9oCINSsEQf2v0LvC7XB/AAAAAAD/////AhAnAAAAAAAAGXapFEpZH3JSKjObF8P931h2RiB1pd28iKzAuA4AAAAAABepFH+lNxviNJ7EluvZE0Zj+NtzfWNfhwAAAAAAAQEg8C0PAAAAAAAXqRR/pTcb4jSexJbr2RNGY/jbc31jX4cBBCIAIHIGUxF7fuOrvFzdUUHSrlj0DeQyQEF4kQA+mbEXhjvtAQVHUiEDwZF1RP1vLIMmGNQerOMSYA112lAAWkZ8yCtO+BVVCXshAoOlt/PBmamyAz3RTmmlGy7GpdPBKJAdNpYhgPeVAb9eUq4AAAA=

Ver 0.5.0 return :

cHNidP8BAHUCAAAAAV/Xe5vINluBNSTaSa5HvAER9oCINSsEQf2v0LvC7XB/AAAAAAD/////AhAnAAAAAAAAGXapFEpZH3JSKjObF8P931h2RiB1pd28iKzAuA4AAAAAABepFH+lNxviNJ7EluvZE0Zj+NtzfWNfhwAAAAAAAQD9BQIBAAAAAzPd4/7dX+crLxnmbG+8M8mWpzkft30UJyrN32P5BadAAQAAAGpHMEQCIB1Pp/eVoX/uN0hjpP5YrCM8ZnLVK7iKx232CzX/Yx9mAiAI5VEK5zl/ee2UtUJUONyNdCclKnqwA7fXj/6iTCHXNgEhAiVvrCjM2YWzO9LnJgJC9KHlKHuIOHtTOjhamqsiVQdC/////81I6eNaxdY9HjNSfWr09wR8uJUI81tHPVbXW2xnnnLvAQAAAGtIMEUCIQDUjhG9ViNiQ0APokmzZfpdZPoI/FXRvZNvNU3MlIaZZgIgZn6KZZEIbvWfSK6XQZI6ejLjEVS+pEU4FIh1q9s1ArEBIQOuJ4SoN3h/gY3BynnuMplZDvVPcCpxkLwZ9pQmzmr3qP////8pidVqFzOicNSK4MSdqWHyWpI9Pbb//QifEB5+pXwDZgAAAABrSDBFAiEA6vrpYJYQPYDzjC14liGzMcMp5WARFUrrWAx/AeFR/38CIBx+ltAw08D5LsZA5kSLKstXv1IJ35045ln4y8+VbqtAASECIuc8B3HUkAxm5FqI2LvBPp87FOK84md95dWfyd/pUNP/////AvAtDwAAAAAAF6kUf6U3G+I0nsSW69kTRmP423N9Y1+H354xBwAAAAAXqRRlP/bwgbNfeP2HTlQGV2cTDcCThIcAAAAAAQEg8C0PAAAAAAAXqRR/pTcb4jSexJbr2RNGY/jbc31jX4cBBCIAIHIGUxF7fuOrvFzdUUHSrlj0DeQyQEF4kQA+mbEXhjvtAQVHUiEDwZF1RP1vLIMmGNQerOMSYA112lAAWkZ8yCtO+BVVCXshAoOlt/PBmamyAz3RTmmlGy7GpdPBKJAdNpYhgPeVAb9eUq4AAAA=

I noticed that psbt.update!(prev_tx, redeem_script: redeem_script, witness_script: witness_script) return nil at ver 0.5.0
meanwhile 0.4.0 return:

[#<Bitcoin::TxIn:0x00007f83520752b0
  @out_point=#<Bitcoin::OutPoint:0x00007f8352075300 @index=0, @tx_hash="5fd77b9bc8365b813524da49ae47bc0111f68088352b0441fdafd0bbc2ed707f">,
  @script_sig=#<Bitcoin::Script:0x00007f834b7c0238 @chunks=[]>,
  @script_witness=#<Bitcoin::ScriptWitness:0x00007f835209d288 @stack=[]>,
  @sequence=4294967295>]

Thank you!

OpenAssets::MARKER is modified every OpenAssets::Payload#to_payload calls

OpenAssets::MARKER is constant,so SHOULD NOT be modified

$ ./bin/console 
irb(main):005:0> OpenAssets::Payload
=> OpenAssets::Payload
irb(main):006:0> OpenAssets::MARKER
=> "OA"
irb(main):007:0> OpenAssets::Payload.new([],'').to_payload
=> "OA\u0001\u0000\u0000\u0000"
irb(main):008:0> OpenAssets::MARKER
=> "OA\u0001\u0000\u0000\u0000"
irb(main):009:0> 

MerkleTree::Node#value fails for nodes in tree which has odd number of txids

For the tree created by using an odd number of txids, Node#value failed in this tree.

$ ./bin/console 
irb(main):001:0> hashes = ["eabc5a0f2db047073fd8bcc8317b72578f705a0845b33d3c0fa939421219a452", "15157a0138efe2d76ca0ef26f4b42341bd14ff2871603e7364a1d404da51493f"]
=> ["eabc5a0f2db047073fd8bcc8317b72578f705a0845b33d3c0fa939421219a452", "15157a0138efe2d76ca0ef26f4b42341bd14ff2871603e7364a1d404da51493f"]
irb(main):002:0> tree = Bitcoin::MerkleTree.build_partial(3, hashes, Bitcoin.byte_to_bit('1d'.htb))
irb(main):004:0> tree.root.right.value
Traceback (most recent call last):
        5: from ./bin/console:14:in `<main>'
        4: from (irb):4
        3: from /Users/h_yamaguchi/Documents/Projects/haw/bitcoinrb/lib/bitcoin/merkle_tree.rb:85:in `value'
        2: from /Users/h_yamaguchi/Documents/Projects/haw/bitcoinrb/lib/bitcoin/merkle_tree.rb:84:in `value'
        1: from /Users/h_yamaguchi/Documents/Projects/haw/bitcoinrb/lib/bitcoin/merkle_tree.rb:78:in `right='
NoMethodError (undefined method `parent=' for nil:NilClass)
irb(main):005:0> 
$ bitcoin-cli getblock 58802a21341ec5fc825b68241c1425e82625cbac56a8b18317b27a23101acf00
{
  "hash": "58802a21341ec5fc825b68241c1425e82625cbac56a8b18317b27a23101acf00",
  "confirmations": 1,
  "strippedsize": 435,
  "size": 803,
  "weight": 2108,
  "height": 4031,
  "version": 536870912,
  "versionHex": "20000000",
  "merkleroot": "166b3b66ec34f5be025b677961289b0584b6be7a2fb1cc25f4d9e84fd78a2789",
  "tx": [
    "0766fe643cfd100cee17dbd3d035ecac3df10b6fe10d031c718d26d1583ea659",
    "6b049004a60d6e57b507ae8cfbe481aa4c8959c802e724b056a8e29cbf485d9a",
    "3f4951da04d4a164733e607128ff14bd4123b4f426efa06cd7e2ef38017a1515"
  ],
  "time": 1537959102,
  "mediantime": 1537956553,
  "nonce": 0,
  "bits": "207fffff",
  "difficulty": 4.656542373906925e-10,
  "chainwork": "0000000000000000000000000000000000000000000000000000000000001f80",
  "previousblockhash": "566f35243e9e969f6756d78323fa313c3ae3d878242a58ef2ba963d0f5db9221"
}

Support blockchain reorganization.

The bitcoinrb does not support blockchain reorganization.
When reorg occurred, it will raise an error "header's previous hash ... does not match current best block's ... ".
https://github.com/chaintope/bitcoinrb/blob/master/lib/bitcoin/store/spv_chain.rb#L58

To support reorg, we need to implement

  • Store the orphan block(s), if it's previous block is not match the best block (longest chain)
  • Calculate the sum of chain difficulties which was forked from the longest chain.
  • Replace chain when the sum of difficulties is larger than that of the current chain.
  • Remove old (orphan) chain after many blocks have created
  • etc...

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.