bitcoin-ruby 0.0.6 → 0.0.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (128) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +0 -1
  3. data/.travis.yml +2 -7
  4. data/COPYING +1 -1
  5. data/Gemfile +2 -6
  6. data/Gemfile.lock +34 -0
  7. data/README.rdoc +16 -68
  8. data/Rakefile +3 -6
  9. data/bin/bitcoin_shell +0 -1
  10. data/{concept-examples/blockchain-pow.rb → examples/concept-blockchain-pow.rb} +0 -0
  11. data/lib/bitcoin.rb +350 -296
  12. data/lib/bitcoin/builder.rb +3 -1
  13. data/lib/bitcoin/connection.rb +2 -1
  14. data/lib/bitcoin/contracthash.rb +76 -0
  15. data/lib/bitcoin/dogecoin.rb +97 -0
  16. data/lib/bitcoin/ffi/bitcoinconsensus.rb +74 -0
  17. data/lib/bitcoin/ffi/openssl.rb +98 -2
  18. data/lib/bitcoin/ffi/secp256k1.rb +144 -0
  19. data/lib/bitcoin/key.rb +12 -2
  20. data/lib/bitcoin/logger.rb +3 -12
  21. data/lib/bitcoin/protocol/block.rb +3 -9
  22. data/lib/bitcoin/protocol/parser.rb +6 -2
  23. data/lib/bitcoin/protocol/tx.rb +44 -13
  24. data/lib/bitcoin/protocol/txin.rb +4 -2
  25. data/lib/bitcoin/protocol/txout.rb +2 -2
  26. data/lib/bitcoin/script.rb +212 -37
  27. data/lib/bitcoin/trezor/mnemonic.rb +130 -0
  28. data/lib/bitcoin/version.rb +1 -1
  29. data/spec/bitcoin/bitcoin_spec.rb +32 -3
  30. data/spec/bitcoin/builder_spec.rb +18 -0
  31. data/spec/bitcoin/contracthash_spec.rb +45 -0
  32. data/spec/bitcoin/dogecoin_spec.rb +176 -0
  33. data/spec/bitcoin/ffi_openssl.rb +45 -0
  34. data/spec/bitcoin/fixtures/156e6e1b84c5c3bd3a0927b25e4119fadce6e6d5186f363317511d1d680fae9a.json +24 -0
  35. data/spec/bitcoin/fixtures/8d0b238a06b5a70be75d543902d02d7a514d68d3252a949a513865ac3538874c.json +24 -0
  36. data/spec/bitcoin/fixtures/coinbase-toshi.json +33 -0
  37. data/spec/bitcoin/fixtures/coinbase.json +24 -0
  38. data/spec/bitcoin/fixtures/dogecoin-block-60323982f9c5ff1b5a954eac9dc1269352835f47c2c5222691d80f0d50dcf053.bin +0 -0
  39. data/spec/bitcoin/fixtures/rawtx-01-toshi.json +46 -0
  40. data/spec/bitcoin/fixtures/rawtx-02-toshi.json +46 -0
  41. data/spec/bitcoin/fixtures/rawtx-03-toshi.json +73 -0
  42. data/spec/bitcoin/fixtures/rawtx-testnet-04fdc38d6722ab4b12d79113fc4b2896bdcc5169710690ee4e78541b98e467b4.bin +0 -0
  43. data/spec/bitcoin/fixtures/rawtx-testnet-0b294c7d11dd21bcccb8393e6744fed7d4d1981a08c00e3e88838cc421f33c9f.bin +0 -0
  44. data/spec/bitcoin/fixtures/rawtx-testnet-3bc52ac063291ad92d95ddda5fd776a342083b95607ad32ed8bc6f8f7d30449e.bin +0 -0
  45. data/spec/bitcoin/fixtures/rawtx-testnet-6f0bbdd4e71a8af4305018d738184df32dbb6f27284fdebd5b56d16947f7c181.bin +0 -0
  46. data/spec/bitcoin/fixtures/rawtx-testnet-a7c9b06e275e8674cc19a5f7d3e557c72c6d93576e635b33212dbe08ab7cdb60.bin +0 -0
  47. data/spec/bitcoin/fixtures/rawtx-testnet-f80acbd2f594d04ddb0e1cacba662132104909157dff526935a3c88abe9201a5.bin +0 -0
  48. data/spec/bitcoin/protocol/block_spec.rb +0 -22
  49. data/spec/bitcoin/protocol/tx_spec.rb +145 -2
  50. data/spec/bitcoin/script/script_spec.rb +282 -0
  51. data/spec/bitcoin/secp256k1_spec.rb +48 -0
  52. data/spec/bitcoin/spec_helper.rb +0 -51
  53. data/spec/bitcoin/trezor/mnemonic_spec.rb +161 -0
  54. metadata +48 -98
  55. data/bin/bitcoin_dns_seed +0 -130
  56. data/bin/bitcoin_gui +0 -80
  57. data/bin/bitcoin_node +0 -153
  58. data/bin/bitcoin_node_cli +0 -81
  59. data/bin/bitcoin_wallet +0 -402
  60. data/doc/CONFIG.rdoc +0 -66
  61. data/doc/EXAMPLES.rdoc +0 -13
  62. data/doc/NAMECOIN.rdoc +0 -34
  63. data/doc/NODE.rdoc +0 -225
  64. data/doc/STORAGE.rdoc +0 -33
  65. data/doc/WALLET.rdoc +0 -102
  66. data/examples/balance.rb +0 -66
  67. data/examples/forwarder.rb +0 -73
  68. data/examples/index_nhash.rb +0 -24
  69. data/examples/reindex_p2sh_addrs.rb +0 -44
  70. data/examples/relay_tx.rb +0 -22
  71. data/examples/verify_tx.rb +0 -57
  72. data/lib/bitcoin/config.rb +0 -58
  73. data/lib/bitcoin/gui/addr_view.rb +0 -44
  74. data/lib/bitcoin/gui/bitcoin-ruby.png +0 -0
  75. data/lib/bitcoin/gui/bitcoin-ruby.svg +0 -80
  76. data/lib/bitcoin/gui/conn_view.rb +0 -38
  77. data/lib/bitcoin/gui/connection.rb +0 -70
  78. data/lib/bitcoin/gui/em_gtk.rb +0 -30
  79. data/lib/bitcoin/gui/gui.builder +0 -1643
  80. data/lib/bitcoin/gui/gui.rb +0 -292
  81. data/lib/bitcoin/gui/helpers.rb +0 -115
  82. data/lib/bitcoin/gui/tree_view.rb +0 -84
  83. data/lib/bitcoin/gui/tx_view.rb +0 -69
  84. data/lib/bitcoin/namecoin.rb +0 -280
  85. data/lib/bitcoin/network/command_client.rb +0 -104
  86. data/lib/bitcoin/network/command_handler.rb +0 -570
  87. data/lib/bitcoin/network/connection_handler.rb +0 -387
  88. data/lib/bitcoin/network/node.rb +0 -565
  89. data/lib/bitcoin/storage/dummy/dummy_store.rb +0 -179
  90. data/lib/bitcoin/storage/models.rb +0 -171
  91. data/lib/bitcoin/storage/sequel/migrations.rb +0 -99
  92. data/lib/bitcoin/storage/sequel/migrations/001_base_schema.rb +0 -52
  93. data/lib/bitcoin/storage/sequel/migrations/002_tx.rb +0 -45
  94. data/lib/bitcoin/storage/sequel/migrations/003_change_txin_script_sig_to_blob.rb +0 -18
  95. data/lib/bitcoin/storage/sequel/migrations/004_change_txin_prev_out_to_blob.rb +0 -18
  96. data/lib/bitcoin/storage/sequel/migrations/005_change_tx_hash_to_bytea.rb +0 -14
  97. data/lib/bitcoin/storage/sequel/migrations/006_add_tx_nhash.rb +0 -31
  98. data/lib/bitcoin/storage/sequel/migrations/007_add_prev_out_index_index.rb +0 -16
  99. data/lib/bitcoin/storage/sequel/migrations/008_add_txin_p2sh_type.rb +0 -31
  100. data/lib/bitcoin/storage/sequel/migrations/009_add_addrs_type.rb +0 -56
  101. data/lib/bitcoin/storage/sequel/sequel_store.rb +0 -551
  102. data/lib/bitcoin/storage/storage.rb +0 -517
  103. data/lib/bitcoin/storage/utxo/migrations/001_base_schema.rb +0 -52
  104. data/lib/bitcoin/storage/utxo/migrations/002_utxo.rb +0 -18
  105. data/lib/bitcoin/storage/utxo/migrations/003_update_indices.rb +0 -14
  106. data/lib/bitcoin/storage/utxo/migrations/004_add_addrs_type.rb +0 -14
  107. data/lib/bitcoin/storage/utxo/utxo_store.rb +0 -374
  108. data/lib/bitcoin/validation.rb +0 -400
  109. data/lib/bitcoin/wallet/coinselector.rb +0 -33
  110. data/lib/bitcoin/wallet/keygenerator.rb +0 -77
  111. data/lib/bitcoin/wallet/keystore.rb +0 -207
  112. data/lib/bitcoin/wallet/txdp.rb +0 -118
  113. data/lib/bitcoin/wallet/wallet.rb +0 -281
  114. data/spec/bitcoin/fixtures/freicoin-block-000000005d231b285e63af83edae2d8f5e50e70d396468643092b9239fd3be3c.bin +0 -0
  115. data/spec/bitcoin/fixtures/freicoin-block-000000005d231b285e63af83edae2d8f5e50e70d396468643092b9239fd3be3c.json +0 -43
  116. data/spec/bitcoin/fixtures/freicoin-genesis-block-000000005b1e3d23ecfd2dd4a6e1a35238aa0392c0a8528c40df52376d7efe2c.bin +0 -0
  117. data/spec/bitcoin/fixtures/freicoin-genesis-block-000000005b1e3d23ecfd2dd4a6e1a35238aa0392c0a8528c40df52376d7efe2c.json +0 -67
  118. data/spec/bitcoin/namecoin_spec.rb +0 -182
  119. data/spec/bitcoin/node/command_api_spec.rb +0 -663
  120. data/spec/bitcoin/storage/models_spec.rb +0 -104
  121. data/spec/bitcoin/storage/reorg_spec.rb +0 -236
  122. data/spec/bitcoin/storage/storage_spec.rb +0 -387
  123. data/spec/bitcoin/storage/validation_spec.rb +0 -300
  124. data/spec/bitcoin/wallet/coinselector_spec.rb +0 -38
  125. data/spec/bitcoin/wallet/keygenerator_spec.rb +0 -69
  126. data/spec/bitcoin/wallet/keystore_spec.rb +0 -190
  127. data/spec/bitcoin/wallet/txdp_spec.rb +0 -76
  128. data/spec/bitcoin/wallet/wallet_spec.rb +0 -238
@@ -0,0 +1,130 @@
1
+ # encoding: ascii-8bit
2
+ # port of https://github.com/trezor/python-mnemonic/blob/master/mnemonic/mnemonic.py
3
+
4
+ require 'openssl'
5
+ require 'securerandom'
6
+ require 'digest'
7
+
8
+ module Bitcoin
9
+ module Trezor
10
+
11
+ module Mnemonic
12
+ def self.to_seed(mnemonic, passphrase='')
13
+ OpenSSL::PKCS5.pbkdf2_hmac(mnemonic, 'mnemonic'+passphrase, 2048, 64, OpenSSL::Digest::SHA512.new).unpack("H*")[0]
14
+ end
15
+
16
+ def self.generate(strength_bits = 256)
17
+ raise ArgumentError, 'Strength should be divisible by 32, but it is not (%d)' % [strength_bits] if (strength_bits % 32) > 0
18
+ data = SecureRandom.random_bytes( (strength_bits / 8).floor )
19
+ to_mnemonic(data)
20
+ end
21
+
22
+ def self.wordlist
23
+ return @wordlist if @wordlist
24
+ @wordlist = WORDLIST_ENGLISH.split(/[ \n]/).map{|i| i.strip }
25
+ if @wordlist.size != (radix=2048)
26
+ raise ArgumentError, 'Wordlist should contain %d words, but it contains %d words.' % [radix, wordlist.size]
27
+ end
28
+ @wordlist
29
+ end
30
+
31
+ def self.to_mnemonic(data)
32
+ if (data.bytesize % 4) > 0
33
+ raise ArgumentError, 'Data length in bits should be divisible by 32, but it is not (%d bytes = %d bits).' % [data.bytesize, data.bytesize * 8]
34
+ end
35
+ b = data.unpack("B*")[0] + Digest::SHA256.digest(data).unpack("B*")[0].ljust(256, '0')[0...(data.bytesize * 8 / 32)]
36
+
37
+ (0...(b.bytesize / 11)).map{|i|
38
+ idx = b[ (i * 11)...((i+1) * 11) ].to_i(2)
39
+ wordlist[idx]
40
+ }.join(" ")
41
+ end
42
+
43
+ WORDLIST_ENGLISH = <<-TEXT
44
+ abandon ability able about above absent absorb abstract absurd abuse access accident account accuse achieve acid acoustic acquire across act action actor actress actual adapt
45
+ add addict address adjust admit adult advance advice aerobic affair afford afraid again age agent agree ahead aim air airport aisle alarm album alcohol alert
46
+ alien all alley allow almost alone alpha already also alter always amateur amazing among amount amused analyst anchor ancient anger angle angry animal ankle announce
47
+ annual another answer antenna antique anxiety any apart apology appear apple approve april arch arctic area arena argue arm armed armor army around arrange arrest
48
+ arrive arrow art artefact artist artwork ask aspect assault asset assist assume asthma athlete atom attack attend attitude attract auction audit august aunt author auto
49
+ autumn average avocado avoid awake aware away awesome awful awkward axis baby bachelor bacon badge bag balance balcony ball bamboo banana banner bar barely bargain
50
+ barrel base basic basket battle beach bean beauty because become beef before begin behave behind believe below belt bench benefit best betray better between beyond
51
+ bicycle bid bike bind biology bird birth bitter black blade blame blanket blast bleak bless blind blood blossom blouse blue blur blush board boat body
52
+ boil bomb bone bonus book boost border boring borrow boss bottom bounce box boy bracket brain brand brass brave bread breeze brick bridge brief bright
53
+ bring brisk broccoli broken bronze broom brother brown brush bubble buddy budget buffalo build bulb bulk bullet bundle bunker burden burger burst bus business busy
54
+ butter buyer buzz cabbage cabin cable cactus cage cake call calm camera camp can canal cancel candy cannon canoe canvas canyon capable capital captain car
55
+ carbon card cargo carpet carry cart case cash casino castle casual cat catalog catch category cattle caught cause caution cave ceiling celery cement census century
56
+ cereal certain chair chalk champion change chaos chapter charge chase chat cheap check cheese chef cherry chest chicken chief child chimney choice choose chronic chuckle
57
+ chunk churn cigar cinnamon circle citizen city civil claim clap clarify claw clay clean clerk clever click client cliff climb clinic clip clock clog close
58
+ cloth cloud clown club clump cluster clutch coach coast coconut code coffee coil coin collect color column combine come comfort comic common company concert conduct
59
+ confirm congress connect consider control convince cook cool copper copy coral core corn correct cost cotton couch country couple course cousin cover coyote crack cradle
60
+ craft cram crane crash crater crawl crazy cream credit creek crew cricket crime crisp critic crop cross crouch crowd crucial cruel cruise crumble crunch crush
61
+ cry crystal cube culture cup cupboard curious current curtain curve cushion custom cute cycle dad damage damp dance danger daring dash daughter dawn day deal
62
+ debate debris decade december decide decline decorate decrease deer defense define defy degree delay deliver demand demise denial dentist deny depart depend deposit depth deputy
63
+ derive describe desert design desk despair destroy detail detect develop device devote diagram dial diamond diary dice diesel diet differ digital dignity dilemma dinner dinosaur
64
+ direct dirt disagree discover disease dish dismiss disorder display distance divert divide divorce dizzy doctor document dog doll dolphin domain donate donkey donor door dose
65
+ double dove draft dragon drama drastic draw dream dress drift drill drink drip drive drop drum dry duck dumb dune during dust dutch duty dwarf
66
+ dynamic eager eagle early earn earth easily east easy echo ecology economy edge edit educate effort egg eight either elbow elder electric elegant element elephant
67
+ elevator elite else embark embody embrace emerge emotion employ empower empty enable enact end endless endorse enemy energy enforce engage engine enhance enjoy enlist enough
68
+ enrich enroll ensure enter entire entry envelope episode equal equip era erase erode erosion error erupt escape essay essence estate eternal ethics evidence evil evoke
69
+ evolve exact example excess exchange excite exclude excuse execute exercise exhaust exhibit exile exist exit exotic expand expect expire explain expose express extend extra eye
70
+ eyebrow fabric face faculty fade faint faith fall false fame family famous fan fancy fantasy farm fashion fat fatal father fatigue fault favorite feature february
71
+ federal fee feed feel female fence festival fetch fever few fiber fiction field figure file film filter final find fine finger finish fire firm first
72
+ fiscal fish fit fitness fix flag flame flash flat flavor flee flight flip float flock floor flower fluid flush fly foam focus fog foil fold
73
+ follow food foot force forest forget fork fortune forum forward fossil foster found fox fragile frame frequent fresh friend fringe frog front frost frown frozen
74
+ fruit fuel fun funny furnace fury future gadget gain galaxy gallery game gap garage garbage garden garlic garment gas gasp gate gather gauge gaze general
75
+ genius genre gentle genuine gesture ghost giant gift giggle ginger giraffe girl give glad glance glare glass glide glimpse globe gloom glory glove glow glue
76
+ goat goddess gold good goose gorilla gospel gossip govern gown grab grace grain grant grape grass gravity great green grid grief grit grocery group grow
77
+ grunt guard guess guide guilt guitar gun gym habit hair half hammer hamster hand happy harbor hard harsh harvest hat have hawk hazard head health
78
+ heart heavy hedgehog height hello helmet help hen hero hidden high hill hint hip hire history hobby hockey hold hole holiday hollow home honey hood
79
+ hope horn horror horse hospital host hotel hour hover hub huge human humble humor hundred hungry hunt hurdle hurry hurt husband hybrid ice icon idea
80
+ identify idle ignore ill illegal illness image imitate immense immune impact impose improve impulse inch include income increase index indicate indoor industry infant inflict inform
81
+ inhale inherit initial inject injury inmate inner innocent input inquiry insane insect inside inspire install intact interest into invest invite involve iron island isolate issue
82
+ item ivory jacket jaguar jar jazz jealous jeans jelly jewel job join joke journey joy judge juice jump jungle junior junk just kangaroo keen keep
83
+ ketchup key kick kid kidney kind kingdom kiss kit kitchen kite kitten kiwi knee knife knock know lab label labor ladder lady lake lamp language
84
+ laptop large later latin laugh laundry lava law lawn lawsuit layer lazy leader leaf learn leave lecture left leg legal legend leisure lemon lend length
85
+ lens leopard lesson letter level liar liberty library license life lift light like limb limit link lion liquid list little live lizard load loan lobster
86
+ local lock logic lonely long loop lottery loud lounge love loyal lucky luggage lumber lunar lunch luxury lyrics machine mad magic magnet maid mail main
87
+ major make mammal man manage mandate mango mansion manual maple marble march margin marine market marriage mask mass master match material math matrix matter maximum
88
+ maze meadow mean measure meat mechanic medal media melody melt member memory mention menu mercy merge merit merry mesh message metal method middle midnight milk
89
+ million mimic mind minimum minor minute miracle mirror misery miss mistake mix mixed mixture mobile model modify mom moment monitor monkey monster month moon moral
90
+ more morning mosquito mother motion motor mountain mouse move movie much muffin mule multiply muscle museum mushroom music must mutual myself mystery myth naive name
91
+ napkin narrow nasty nation nature near neck need negative neglect neither nephew nerve nest net network neutral never news next nice night noble noise nominee
92
+ noodle normal north nose notable note nothing notice novel now nuclear number nurse nut oak obey object oblige obscure observe obtain obvious occur ocean october
93
+ odor off offer office often oil okay old olive olympic omit once one onion online only open opera opinion oppose option orange orbit orchard order
94
+ ordinary organ orient original orphan ostrich other outdoor outer output outside oval oven over own owner oxygen oyster ozone pact paddle page pair palace palm
95
+ panda panel panic panther paper parade parent park parrot party pass patch path patient patrol pattern pause pave payment peace peanut pear peasant pelican pen
96
+ penalty pencil people pepper perfect permit person pet phone photo phrase physical piano picnic picture piece pig pigeon pill pilot pink pioneer pipe pistol pitch
97
+ pizza place planet plastic plate play please pledge pluck plug plunge poem poet point polar pole police pond pony pool popular portion position possible post
98
+ potato pottery poverty powder power practice praise predict prefer prepare present pretty prevent price pride primary print priority prison private prize problem process produce profit
99
+ program project promote proof property prosper protect proud provide public pudding pull pulp pulse pumpkin punch pupil puppy purchase purity purpose purse push put puzzle
100
+ pyramid quality quantum quarter question quick quit quiz quote rabbit raccoon race rack radar radio rail rain raise rally ramp ranch random range rapid rare
101
+ rate rather raven raw razor ready real reason rebel rebuild recall receive recipe record recycle reduce reflect reform refuse region regret regular reject relax release
102
+ relief rely remain remember remind remove render renew rent reopen repair repeat replace report require rescue resemble resist resource response result retire retreat return reunion
103
+ reveal review reward rhythm rib ribbon rice rich ride ridge rifle right rigid ring riot ripple risk ritual rival river road roast robot robust rocket
104
+ romance roof rookie room rose rotate rough round route royal rubber rude rug rule run runway rural sad saddle sadness safe sail salad salmon salon
105
+ salt salute same sample sand satisfy satoshi sauce sausage save say scale scan scare scatter scene scheme school science scissors scorpion scout scrap screen script
106
+ scrub sea search season seat second secret section security seed seek segment select sell seminar senior sense sentence series service session settle setup seven shadow
107
+ shaft shallow share shed shell sheriff shield shift shine ship shiver shock shoe shoot shop short shoulder shove shrimp shrug shuffle shy sibling sick side
108
+ siege sight sign silent silk silly silver similar simple since sing siren sister situate six size skate sketch ski skill skin skirt skull slab slam
109
+ sleep slender slice slide slight slim slogan slot slow slush small smart smile smoke smooth snack snake snap sniff snow soap soccer social sock soda
110
+ soft solar soldier solid solution solve someone song soon sorry sort soul sound soup source south space spare spatial spawn speak special speed spell spend
111
+ sphere spice spider spike spin spirit split spoil sponsor spoon sport spot spray spread spring spy square squeeze squirrel stable stadium staff stage stairs stamp
112
+ stand start state stay steak steel stem step stereo stick still sting stock stomach stone stool story stove strategy street strike strong struggle student stuff
113
+ stumble style subject submit subway success such sudden suffer sugar suggest suit summer sun sunny sunset super supply supreme sure surface surge surprise surround survey
114
+ suspect sustain swallow swamp swap swarm swear sweet swift swim swing switch sword symbol symptom syrup system table tackle tag tail talent talk tank tape
115
+ target task taste tattoo taxi teach team tell ten tenant tennis tent term test text thank that theme then theory there they thing this thought
116
+ three thrive throw thumb thunder ticket tide tiger tilt timber time tiny tip tired tissue title toast tobacco today toddler toe together toilet token tomato
117
+ tomorrow tone tongue tonight tool tooth top topic topple torch tornado tortoise toss total tourist toward tower town toy track trade traffic tragic train transfer
118
+ trap trash travel tray treat tree trend trial tribe trick trigger trim trip trophy trouble truck true truly trumpet trust truth try tube tuition tumble
119
+ tuna tunnel turkey turn turtle twelve twenty twice twin twist two type typical ugly umbrella unable unaware uncle uncover under undo unfair unfold unhappy uniform
120
+ unique unit universe unknown unlock until unusual unveil update upgrade uphold upon upper upset urban urge usage use used useful useless usual utility vacant vacuum
121
+ vague valid valley valve van vanish vapor various vast vault vehicle velvet vendor venture venue verb verify version very vessel veteran viable vibrant vicious victory
122
+ video view village vintage violin virtual virus visa visit visual vital vivid vocal voice void volcano volume vote voyage wage wagon wait walk wall walnut
123
+ want warfare warm warrior wash wasp waste water wave way wealth weapon wear weasel weather web wedding weekend weird welcome west wet whale what wheat
124
+ wheel when where whip whisper wide width wife wild will win window wine wing wink winner winter wire wisdom wise wish witness wolf woman wonder
125
+ wood wool word work world worry worth wrap wreck wrestle wrist write wrong yard year yellow you young youth zebra zero zone zoo
126
+ TEXT
127
+ end
128
+
129
+ end
130
+ end
@@ -1,3 +1,3 @@
1
1
  module Bitcoin
2
- VERSION = "0.0.6"
2
+ VERSION = "0.0.7"
3
3
  end
@@ -163,6 +163,14 @@ describe 'Bitcoin Address/Hash160/PubKey' do
163
163
  success.should == true
164
164
  end
165
165
 
166
+ it 'validate bitcoin public key' do
167
+ key = Bitcoin::Key.generate
168
+ Bitcoin.valid_pubkey?(key.pub_compressed).should == true
169
+ Bitcoin.valid_pubkey?(key.pub_uncompressed).should == true
170
+ Bitcoin.valid_pubkey?(key.addr).should == false
171
+ Bitcoin.valid_pubkey?(key.priv).should == false
172
+ end
173
+
166
174
  it 'validate p2sh address' do
167
175
  Bitcoin.network = :testnet
168
176
  Bitcoin.valid_address?("2MyLngQnhzjzatKsB7XfHYoP9e2XUXSiBMM").should == true
@@ -318,6 +326,13 @@ describe 'Bitcoin Address/Hash160/PubKey' do
318
326
  Bitcoin.hash_mrkl_tree(["aa", "bb", "cc"]).last.should !=
319
327
  Bitcoin.hash_mrkl_tree(["aa", "bb", "cc", "cc"]).last
320
328
  end
329
+
330
+ it 'return a value even if a merkle branch is empty' do
331
+ branch = []
332
+ mrkl_index = 0
333
+ target = "089b911f5e471c0e1800f3384281ebec5b372fbb6f358790a92747ade271ccdf"
334
+ Bitcoin.mrkl_branch_root(branch.map(&:hth), target, mrkl_index).should == target
335
+ end
321
336
 
322
337
  it 'nonce compact bits to bignum hex' do
323
338
  Bitcoin.decode_compact_bits( "1b00b5ac".to_i(16) ).index(/[^0]/).should == 12
@@ -339,6 +354,9 @@ describe 'Bitcoin Address/Hash160/PubKey' do
339
354
  Bitcoin.decode_compact_bits(target).should ==
340
355
  "0000000065465700000000000000000000000000000000000000000000000000"
341
356
  Bitcoin.encode_compact_bits( Bitcoin.decode_compact_bits( target ) ).should == target
357
+
358
+ #Bitcoin.network = :dogecoin
359
+ #Bitcoin.decode_compact_bits( "01fedcba".to_i(16) ).to_i(16).should == -0x7e
342
360
  end
343
361
 
344
362
  it '#block_hash' do
@@ -421,12 +439,13 @@ describe 'Bitcoin Address/Hash160/PubKey' do
421
439
  "030b4c866585dd868a9d62348a9cd008d6a312937048fff31670e7e920cfc7a744"]
422
440
  ].each{|address, privkey, pubkey|
423
441
  key = Bitcoin.open_key(privkey)
424
- 16.times.all?{|n|
442
+ 16.times.each { |n|
425
443
  #10_000.times.all?{|n|
426
444
  # puts 'RAM USAGE: ' + `pmap #{Process.pid} | tail -1`[10,40].strip if (n % 1_000) == 0
427
445
  s = Bitcoin.sign_message(key.private_key_hex, key.public_key_hex, "Very secret message %d: 11" % n)
428
- Bitcoin.verify_message(s['address'], s['signature'], s['message'])
429
- }.should == true
446
+ Bitcoin.verify_message(s['address'], 'invalid-signature', s['message']).should == false
447
+ Bitcoin.verify_message(s['address'], s['signature'], s['message']).should == true
448
+ }
430
449
  }
431
450
  end
432
451
  rescue LoadError
@@ -488,6 +507,16 @@ describe 'Bitcoin Address/Hash160/PubKey' do
488
507
  Bitcoin.block_difficulty(436835377).should == "1751454.5353407"
489
508
  end
490
509
 
510
+ it 'should calculate retarget difficulty' do
511
+ prev_height = 201599
512
+ prev_block_time = 1349227021
513
+ prev_block_bits = 0x1a05db8b
514
+ last_retarget_time = 1348092851
515
+ new_difficulty = Bitcoin.block_new_target(prev_height, prev_block_time, prev_block_bits, last_retarget_time)
516
+
517
+ Bitcoin.decode_compact_bits(new_difficulty.should) == Bitcoin.decode_compact_bits(0x1a057e08)
518
+ end
519
+
491
520
  it '#block_hashes_to_win' do
492
521
  Bitcoin.block_hashes_to_win(436835377).should == 7522554734795001
493
522
  end
@@ -78,11 +78,18 @@ describe "Bitcoin::Builder" do
78
78
  tx2 = build_tx do |t|
79
79
  t.input {|i| i.prev_out @block.tx[0], 0; i.signature_key @keys[0] }
80
80
  t.output {|o| o.value 123; o.script {|s| s.recipient @keys[1].addr } }
81
+ t.output {|o| o.to @keys[1].addr; o.value 321 }
82
+ t.output {|o| o.to "deadbeef", :op_return }
81
83
  end
82
84
  tx2.in[0].prev_out.should == tx.in[0].prev_out
83
85
  tx2.in[0].prev_out_index.should == tx.in[0].prev_out_index
84
86
  tx2.out[0].value.should == tx.out[0].value
85
87
  tx2.out[0].pk_script.should == tx.out[0].pk_script
88
+ Bitcoin::Script.new(tx2.out[0].pk_script).to_string.should ==
89
+ "OP_DUP OP_HASH160 #{@keys[1].hash160} OP_EQUALVERIFY OP_CHECKSIG"
90
+ Bitcoin::Script.new(tx2.out[0].pk_script).to_string.should ==
91
+ "OP_DUP OP_HASH160 #{@keys[1].hash160} OP_EQUALVERIFY OP_CHECKSIG"
92
+ tx2.out[2].value.should == 0
86
93
  end
87
94
 
88
95
  it "should allow txin.prev_out as tx or hash" do
@@ -225,6 +232,17 @@ describe "Bitcoin::Builder" do
225
232
  tx.out.map(&:value).inject(:+).should == 50e8 - 10000
226
233
  end
227
234
 
235
+ it "should build op_return output" do
236
+ builder = TxOutBuilder.new
237
+ builder.to "deadbeef", :op_return
238
+ builder.txout.parsed_script.to_string.should == "OP_RETURN deadbeef"
239
+ end
240
+
241
+ it "should build op_return script" do
242
+ s = script {|s| s.type :op_return; s.recipient "deadbeef" }
243
+ Bitcoin::Script.new(s).to_string.should == "OP_RETURN deadbeef"
244
+ end
245
+
228
246
  it "should build address script" do
229
247
  key = Bitcoin::Key.generate
230
248
  s = script {|s| s.type :address; s.recipient key.addr }
@@ -0,0 +1,45 @@
1
+ # encoding: ascii-8bit
2
+
3
+ require_relative 'spec_helper.rb'
4
+
5
+ # https://github.com/aalness/contracthashtool-ruby
6
+ # ruby port of https://github.com/Blockstream/contracthashtool
7
+
8
+ describe 'Bitcoin::ContractHash' do
9
+ it 'should generate and claim' do
10
+ Bitcoin::network = :testnet3
11
+
12
+ # Example parameters from the original tool's usage().
13
+
14
+ redeem_script_template = '5121038695b28f1649c711aedb1fec8df54874334cfb7ddf31ba3132a94d00bdc9715251ae'
15
+ payee_address = 'mqWkEAFeQdrQvyaWNRn5vijPJeiQAjtxL2'
16
+ nonce_hex = '3a11be476485a6273fad4a0e09117d42'
17
+ private_key_wif = 'cMcpaCT6pHkyS4347i4rSmecaQtLiu1eH28NWmBiePn8bi6N4kzh'
18
+
19
+ # Someone wanting to send funds to the sidechain would call this
20
+ # to calculate a P2SH address to send to. They would then send the
21
+ # MDFs (mutually distrusting functionaries) the target address
22
+ # and nonce so they are able to locate the subsequent transaction.
23
+ # The caller would then send the desired amount of coin to the P2SH
24
+ # address to initiate the peg protocol.
25
+
26
+ nonce, redeem_script, p2sh_address = Bitcoin::ContractHash.generate(redeem_script_template, payee_address, nonce_hex)
27
+
28
+ nonce.should == "3a11be476485a6273fad4a0e09117d42"
29
+ p2sh_address.should == "2MvGPFfDXbJZyH79u187VNZbuCgyRBhcdsw"
30
+ redeem_script.should == "512102944aba05d40d8df1724f8ab2f5f3a58d052d26aedc93e175534cb782becc8ff751ae"
31
+
32
+ # Each MDF would call this to derive a private key to redeem the
33
+ # locked transaction.
34
+
35
+ key = Bitcoin::ContractHash.claim(private_key_wif, payee_address, nonce)
36
+ key.to_base58.should == "cSBD8yM62R82RfbugiGK8Lui9gdMB81NtZBckxe5YxRsDSKySwHK"
37
+
38
+ # Verify homomorphic derivation was successful.
39
+
40
+ signature = key.sign_message(message="derp")
41
+ script = Bitcoin::Script.new([redeem_script].pack("H*"))
42
+ pubkey = Bitcoin::Key.new(nil, script.get_multisig_pubkeys.first.unpack("H*").first)
43
+ pubkey.verify_message(signature, message).should == true
44
+ end
45
+ end
@@ -0,0 +1,176 @@
1
+ # encoding: ascii-8bit
2
+
3
+ require_relative 'spec_helper.rb'
4
+ require 'bitcoin/script'
5
+
6
+ include Bitcoin
7
+ include Bitcoin::Builder
8
+
9
+ describe 'Bitcoin::Dogecoin' do
10
+ it 'validate dogecoin-address' do
11
+
12
+ Bitcoin::network = :dogecoin_testnet
13
+
14
+ # Testnet address
15
+ Bitcoin.valid_address?("nUtMFED5VRg5xuj9QCrNFt9mVPFDXo7TTE").should == true
16
+ # Livenet address
17
+ Bitcoin.valid_address?("DSpgzjPyfQB6ZzeSbMWpaZiTTxGf2oBCs4").should == false
18
+ # Broken address
19
+ Bitcoin.valid_address?("DRjyUS2uuieEPkhZNdQz8hE5YycxVEqSXA").should == false
20
+
21
+ Bitcoin::network = :dogecoin
22
+
23
+ # Testnet address
24
+ Bitcoin.valid_address?("nUtMFED5VRg5xuj9QCrNFt9mVPFDXo7TTE").should == false
25
+ # Livenet address
26
+ Bitcoin.valid_address?("DSpgzjPyfQB6ZzeSbMWpaZiTTxGf2oBCs4").should == true
27
+ # Broken address
28
+ Bitcoin.valid_address?("DRjyUS2uuieEPkhZNdQz8hE5YycxVEqSXA").should == false
29
+ end
30
+
31
+ it 'should calculate retarget difficulty' do
32
+ Bitcoin::network = :dogecoin
33
+
34
+ prev_height = 239
35
+ prev_block_time = 1386475638 # Block 239
36
+ prev_block_bits = 0x1e0ffff0
37
+ last_retarget_time = 1386474927 # Block 1
38
+ new_difficulty = Bitcoin.block_new_target(prev_height, prev_block_time, prev_block_bits, last_retarget_time)
39
+ new_difficulty.to_s(16).should == 0x1e00ffff.to_s(16)
40
+
41
+ prev_height = 479
42
+ prev_block_time = 1386475840
43
+ prev_block_bits = 0x1e0fffff
44
+ last_retarget_time = 1386475638 # Block 239
45
+ new_difficulty = Bitcoin.block_new_target(prev_height, prev_block_time, prev_block_bits, last_retarget_time)
46
+ new_difficulty.to_s(16).should == 0x1e00ffff.to_s(16)
47
+
48
+ prev_height = 9_599
49
+ prev_block_time = 1386954113
50
+ prev_block_bits = 0x1c1a1206
51
+ last_retarget_time = 1386942008 # Block 9359
52
+ new_difficulty = Bitcoin.block_new_target(prev_height, prev_block_time, prev_block_bits, last_retarget_time)
53
+ new_difficulty.to_s(16).should == 0x1c15ea59.to_s(16)
54
+
55
+ # First hard-fork at 145,000, which applies to block 145,001 onwards
56
+ prev_height = 145_000
57
+ prev_block_time = 1395094679
58
+ prev_block_bits = 0x1b499dfd
59
+ last_retarget_time = 1395094427
60
+ new_difficulty = Bitcoin.block_new_target(prev_height, prev_block_time, prev_block_bits, last_retarget_time)
61
+ new_difficulty.to_s(16).should == 0x1b671062.to_s(16)
62
+
63
+ # Test case for correct rounding of modulated time - by default C++ and Ruby do not
64
+ # necessarily round identically
65
+ prev_height = 145_001
66
+ prev_block_time = 1395094727
67
+ prev_block_bits = 0x1b671062
68
+ last_retarget_time = 1395094679
69
+ new_difficulty = Bitcoin.block_new_target(prev_height, prev_block_time, prev_block_bits, last_retarget_time)
70
+ new_difficulty.to_s(16).should == 0x1b6558a4.to_s(16)
71
+
72
+ # Test the second hard-fork at 371,337 as well
73
+ prev_height = 371336
74
+ prev_block_time = 1410464569
75
+ prev_block_bits = 0x1b2fdf75
76
+ last_retarget_time = 1410464445
77
+ new_difficulty = Bitcoin.block_new_target(prev_height, prev_block_time, prev_block_bits, last_retarget_time)
78
+ new_difficulty.to_s(16).should == 0x1b364184.to_s(16)
79
+
80
+ prev_height = 408_596
81
+ prev_block_time = 1412800112
82
+ prev_block_bits = 0x1b033d8b
83
+ last_retarget_time = 1412799989 # Block 408,595
84
+ new_difficulty = Bitcoin.block_new_target(prev_height, prev_block_time, prev_block_bits, last_retarget_time)
85
+ new_difficulty.to_s(16).should == 0x1b039e52.to_s(16)
86
+ end
87
+
88
+ it 'should calculate reward upper bounds' do
89
+ Bitcoin::network = :dogecoin
90
+
91
+ Bitcoin.block_creation_reward(99000).should == 1000000 * COIN # Note this is the maximum possible, not actual reward
92
+ Bitcoin.block_creation_reward(144999).should == 500000 * COIN
93
+ Bitcoin.block_creation_reward(145000).should == 250000 * COIN # Hard-forked to remove random rewards
94
+ Bitcoin.block_creation_reward(199999).should == 250000 * COIN
95
+ Bitcoin.block_creation_reward(299999).should == 125000 * COIN
96
+ Bitcoin.block_creation_reward(399999).should == 62500 * COIN
97
+ Bitcoin.block_creation_reward(499999).should == 31250 * COIN
98
+ Bitcoin.block_creation_reward(599999).should == 15625 * COIN
99
+ Bitcoin.block_creation_reward(600000).should == 10000 * COIN
100
+ Bitcoin.block_creation_reward(700000).should == 10000 * COIN
101
+ end
102
+
103
+ it 'should calculate merkle root from AuxPoW transaction branch' do
104
+ # Taken directly from Dogecoin block #403,931
105
+
106
+ # Branch stored as bytes to reflect how data is stored in AuxPow class
107
+ branch = [
108
+ "\xbe\x07\x90\x78\x86\x93\x99\xfa\xcc\xaa\x76\x4c\x10\xe9\xdf\x6e\x99\x81\x70\x17\x59\xad\x18\xe1\x37\x24\xd9\xca\x58\x83\x13\x48",
109
+ "\x5f\x5b\xfb\x2c\x79\x54\x17\x78\x49\x9c\xab\x95\x6a\x10\x38\x87\x14\x7f\x2a\xb5\xd4\xa7\x17\xf3\x2f\x9e\xee\xbd\x29\xe1\xf8\x94",
110
+ "\xd8\xc6\xfe\x42\xca\x25\x07\x61\x59\xcd\x12\x1a\x5e\x20\xc4\x8c\x1b\xc5\x3a\xb9\x07\x30\x08\x3e\x44\xa3\x34\x56\x6e\xa6\xbb\xcb"
111
+ ]
112
+ mrkl_index = 0
113
+ target = "089b911f5e471c0e1800f3384281ebec5b372fbb6f358790a92747ade271ccdf" # Coinbase TX ID
114
+ Bitcoin.mrkl_branch_root(branch.map(&:hth), target, mrkl_index).should == "f29cd14243ed542d9a0b495efcb9feca1b208bb5b717dc5ac04f068d2fef595a"
115
+ end
116
+
117
+ it 'should calculate merkle root from AuxPoW branch' do
118
+ # Taken directly from Dogecoin block #403,931
119
+
120
+ # Branch stored as bytes to reflect how data is stored in AuxPow class
121
+ aux_branch = [
122
+ "\x47\xa0\x22\x8b\x06\xc9\x36\x8f\x96\xc5\xf0\x4e\xb1\x09\xf8\x2c\xef\x36\xda\xe7\xc1\xbf\x25\x4c\x1a\x3f\x78\x61\x5e\xb0\xbe\x83",
123
+ "\xee\x67\xde\x31\x75\x76\x58\xdd\xd7\x40\x3e\x1a\x35\xd9\xc0\x6a\x5a\x13\xe6\x68\x98\x44\x3b\x45\x8c\xd6\xa7\x1b\x66\x27\x41\x6c",
124
+ "\xab\x9e\xf9\xbd\xa0\x2c\xad\x27\x90\xef\x9b\xb7\xc9\xa0\x7f\xe1\x79\x1a\x9d\x5a\xe0\x43\x09\xc0\xe9\x06\x48\x19\x19\x4c\x28\x31",
125
+ "\xff\x51\x61\x01\x80\xf6\x4d\x33\xa8\xc1\xba\x1d\xd9\xa9\xd0\x40\x48\x88\xc9\x6e\xaf\xd1\x57\x03\x64\x35\x8b\xbe\x99\x8f\x2d\xfe",
126
+ "\x9e\xe4\x18\x36\x7c\x3b\xce\x06\x5e\x7c\x01\x61\x29\x6e\xaa\x0d\x54\x96\xf9\x0f\x8b\x7b\x24\xeb\xf7\x2c\xc4\xba\xa5\x60\x9a\x1f",
127
+ "\x0b\x35\xf3\x73\x10\xe1\xde\x3f\xa4\xe1\x37\x7c\x02\x12\x62\x20\xe1\x64\xfa\x59\xec\xfe\xdc\xf4\x71\x4e\x61\xad\x74\xcc\x4b\x08"
128
+ ]
129
+ aux_mrkl_index = 56
130
+ target = "0c836b86991631d34a8a68054e2f62db919b39d1ee43c27ab3344d6aa82fa609" # Block hash
131
+ Bitcoin.mrkl_branch_root(aux_branch.map(&:hth), target, aux_mrkl_index).should == "ce3040fdb7e37484f6a1ca4f8f5da81e6b7e404ec91102315a233e03a0c39c95" # Merkle root in coinbase script
132
+ end
133
+
134
+ it 'parse AuxPoW' do
135
+ Bitcoin::network = :dogecoin
136
+
137
+ block_hash = "60323982f9c5ff1b5a954eac9dc1269352835f47c2c5222691d80f0d50dcf053"
138
+ data = fixtures_file("dogecoin-block-#{block_hash}.bin")
139
+ block = P::Block.new(data)
140
+ aux_pow = block.aux_pow
141
+ aux_pow.nil?.should == false
142
+ aux_pow.mrkl_index.should == 0
143
+
144
+ parent_block_merkle_root = Bitcoin.mrkl_branch_root(aux_pow.branch.map(&:reverse_hth), aux_pow.tx.hash, aux_pow.mrkl_index)
145
+ parent_block_merkle_root.should == aux_pow.parent_block.mrkl_root.reverse.unpack("H*")[0]
146
+
147
+ # Find the merged mining header in the coinbase input script
148
+ merged_mining_header = "\xfa\xbemm"
149
+ script = aux_pow.tx.in[0].script
150
+ header_idx = script.index(merged_mining_header)
151
+
152
+ header_idx.should == 4
153
+
154
+ chain_merkle_root = Bitcoin.mrkl_branch_root(aux_pow.aux_branch.map(&:reverse_hth), block_hash, aux_pow.aux_index)
155
+
156
+ # Drop everything up to the merged mining data
157
+ script = script.slice(header_idx + merged_mining_header.length, chain_merkle_root.length / 2 + 8)
158
+
159
+ tx_root_hash = script.slice(0, chain_merkle_root.length / 2).unpack("H*")[0]
160
+ chain_merkle_root.should == tx_root_hash
161
+
162
+ merkle_branch_size = script.slice(chain_merkle_root.length / 2, 4).unpack("V")[0]
163
+ merkle_branch_size.should == (1 << aux_pow.aux_branch.length)
164
+
165
+ # Choose a pseudo-random slot in the chain merkle tree
166
+ # but have it be fixed for a size/nonce/chain combination.
167
+ nonce = script.slice(chain_merkle_root.length / 2 + 4, 4).unpack("V")[0]
168
+ rand = nonce
169
+ rand = rand * 1103515245 + 12345
170
+ rand += Bitcoin.network[:auxpow_chain_id]
171
+ rand = rand * 1103515245 + 12345
172
+
173
+ aux_pow.aux_index.should == (rand % merkle_branch_size)
174
+ end
175
+
176
+ end