Commit 4514f06b31f54ba26d49b845bb8168c31fa28ff4

Authored by Marius Hanne
1 parent 35429d1f5f
Exists in utxo_namecoin

WIP: make utxo store work with namecoin

basically works, but sometimes fail to find a name script in the database

Showing 2 changed files with 110 additions and 60 deletions Side-by-side Diff

lib/bitcoin/storage/utxo/utxo_store.rb
... ... @@ -249,6 +249,34 @@
249 249 txout
250 250 end
251 251  
  252 + def get_txouts_for_name_hash(hash)
  253 + name_new_pattern = "Q\x14#{hash.htb}mv\xa9\x14%"
  254 + @db[:utxo].filter("pk_script LIKE ?", name_new_pattern.to_sequel_blob).map {|o|
  255 + wrap_txout(o) }
  256 + end
  257 +
  258 + def get_txouts_for_name(name)
  259 + name_firstupdate_pattern = "R\x04#{name}%mmv\xa9\x14%"
  260 + name_update_pattern = "S\x04#{name}%muv\xa9\x14%"
  261 + @db[:utxo].filter("pk_script LIKE ?", name_firstupdate_pattern.to_sequel_blob)
  262 + .or("pk_script LIKE ?", name_update_pattern.to_sequel_blob).sort_by {|o| o[:blk_id] }
  263 + end
  264 +
  265 + def name_show(name)
  266 + wrap_name(get_txouts_for_name(name).last)
  267 + end
  268 +
  269 + def wrap_name txout
  270 + return nil unless txout
  271 + script = Bitcoin::Script.new(txout[:pk_script])
  272 + data = { txout_id: [txout[:tx_hash].hth, txout[:tx_idx]],
  273 + hash: script.get_namecoin_hash,
  274 + name: script.get_namecoin_name,
  275 + value: script.get_namecoin_value }
  276 + Bitcoin::Storage::Models::Name.new(self, data)
  277 +
  278 + end
  279 +
252 280 end
253 281  
254 282 end
spec/bitcoin/namecoin_spec.rb
... ... @@ -64,81 +64,103 @@
64 64 Script.new(script).to_string.should =~
65 65 /^1 (.*?) OP_2DROP OP_DUP OP_HASH160 #{key.hash160} OP_EQUALVERIFY OP_CHECKSIG$/
66 66 @rand.should != nil
  67 + Script.new(script).type.should == :name_new
67 68  
68 69 script = Script.to_name_firstupdate_script("test/foo", "1234", "testing", key.addr)
69 70 Script.new(script).to_string.should ==
70 71 "2 746573742f666f6f 1234 74657374696e67 OP_2DROP OP_2DROP " +
71 72 "OP_DUP OP_HASH160 #{key.hash160} OP_EQUALVERIFY OP_CHECKSIG"
  73 + Script.new(script).type.should == :name_firstupdate
72 74  
73 75 script = Script.to_name_update_script("test/foo", "more testing", key.addr)
74 76 Script.new(script).to_string.should ==
75 77 "3 746573742f666f6f 6d6f72652074657374696e67 OP_2DROP OP_DROP " +
76 78 "OP_DUP OP_HASH160 #{key.hash160} OP_EQUALVERIFY OP_CHECKSIG"
  79 + Script.new(script).type.should == :name_update
77 80 end
78 81  
79 82 end
80 83  
81   - describe "Namecoin" do
  84 + [
  85 + { :name => :utxo, :db => 'sqlite:/', utxo_cache: 0 }, # in memory
  86 + { :name => :sequel, :db => 'sqlite:/' }, # in memory
  87 + ].each do |configuration|
  88 + describe "Bitcoin::Storage::Backends::#{configuration[:name].capitalize}Store" do
82 89  
83   - before do
84   - Bitcoin.network = :namecoin
85   - class Bitcoin::Validation::Block; def difficulty; true; end; end
86   - class Bitcoin::Validation::Block; def min_timestamp; true; end; end
87   - Bitcoin.network[:proof_of_work_limit] = Bitcoin.encode_compact_bits("ff"*32)
88   - [:name_new, :name_firstupdate, :name_update].each {|type|
89   - Bitcoin::Storage::Backends::SequelStore::SCRIPT_TYPES << type }
90   - @store = Bitcoin::Storage.sequel(db: "sqlite:/")
91   - @store.reset
92   - @store.log.level = 4
93   - @key = Bitcoin::Key.generate
94   - @block = create_block "00"*32, false, [], @key
95   - Bitcoin.network[:genesis_hash] = @block.hash
96   - @store.store_block(@block)
97   - end
  90 + before do
  91 + Bitcoin.network = :namecoin
  92 + class Bitcoin::Validation::Block; def difficulty; true; end; end
  93 + class Bitcoin::Validation::Block; def min_timestamp; true; end; end
  94 + Bitcoin.network[:proof_of_work_limit] = Bitcoin.encode_compact_bits("ff"*32)
  95 + [:name_new, :name_firstupdate, :name_update].each {|type|
  96 + Bitcoin::Storage::Backends::SequelStore::SCRIPT_TYPES << type }
  97 + @store = Bitcoin::Storage.send(configuration[:name], configuration)
  98 + @store.reset
  99 + @store.log.level = 3
  100 + @key = Bitcoin::Key.generate
  101 + @block = create_block "00"*32, false, [], @key
  102 + Bitcoin.network[:genesis_hash] = @block.hash
  103 + @store.store_block(@block)
  104 + end
98 105  
99   - def set_rand r; @rand = r; end
  106 + def set_rand r; @rand = r; end
100 107  
101   - it "should store names" do
102   - # create name_new
103   - @block = create_block @block.hash, true, [->(t) {
104   - t.input {|i| i.prev_out @block.tx[0]; i.prev_out_index 0; i.signature_key @key }
105   - t.output {|o| o.value 50e8; o.script {|s| s.type(:name_new)
106   - s.recipient(self, "test", @key.addr) } } }], @key
107   - @store.db[:names][hash: Bitcoin.hash160(@rand + "test".hth)].should != nil
  108 + it "should store names" do
  109 + # create name_new
  110 + @block = create_block @block.hash, true, [->(t) {
  111 + t.input {|i| i.prev_out @block.tx[0]; i.prev_out_index 0; i.signature_key @key }
  112 + t.output {|o| o.value 50e8; o.script {|s| s.type(:name_new)
  113 + s.recipient(self, "test", @key.addr) } } }], @key
108 114  
109   - # name_firstupdate should not be valid yet
110   - @block = create_block @block.hash, true, [->(t) {
111   - t.input {|i| i.prev_out @block.tx[0]; i.prev_out_index 0; i.signature_key @key }
112   - t.output {|o| o.value 50e8; o.script {|s| s.type(:name_firstupdate)
113   - s.recipient("test", @rand, "testvalue", @key.addr) } } }], @key
114   - @store.name_show("test").should == nil
  115 + Bitcoin::Script.new(@block.tx[1].out[0].pk_script).type.should == :name_new
115 116  
116   - # create enough blocks for name_new to become valid
117   - i = Bitcoin::Storage::Backends::SequelStore::NAMECOIN_FIRSTUPDATE_LIMIT
118   - i.times { @block = create_block @block.hash, true, [], @key }
  117 + hash = Bitcoin.hash160(@rand + "test".hth)
  118 + txouts = @store.get_txouts_for_name_hash(hash)
  119 + txouts.size.should == 1
  120 + txouts[0].get_tx.hash.should == @block.tx[1].hash
119 121  
120   - # name_firstupdate should be valid now
121   - @block = create_block @block.hash, true, [->(t) {
122   - t.input {|i| i.prev_out @block.tx[0]; i.prev_out_index 0; i.signature_key @key }
123   - t.output {|o| o.value 50e8; o.script {|s|; s.type(:name_firstupdate)
124   - s.recipient("test", @rand, "testvalue", @key.addr) } } }], @key
  122 + # # name_firstupdate should not be valid yet
  123 + # @block = create_block @block.hash, true, [->(t) {
  124 + # t.input {|i| i.prev_out @block.tx[0]; i.prev_out_index 0; i.signature_key @key }
  125 + # t.output {|o| o.value 50e8; o.script {|s| s.type(:name_firstupdate)
  126 + # s.recipient("test", @rand, "testvalue", @key.addr) } } }], @key
  127 + # @store.name_show("test").should == nil
125 128  
126   - name = @store.name_show("test")
127   - name.get_address.should == @key.addr
128   - name.name.should == "test"
129   - name.value.should == "testvalue"
130   - name.hash.should == Bitcoin.hash160(@rand + "test".hth)
  129 + # create enough blocks for name_new to become valid
  130 + i = Bitcoin::Storage::Backends::SequelStore::NAMECOIN_FIRSTUPDATE_LIMIT
  131 + i.times { @block = create_block @block.hash, true, [], @key }
131 132  
132   - # create name_update
133   - @new_key = Bitcoin::Key.generate
134   - @block = create_block @block.hash, true, [->(t) {
135   - t.input {|i| i.prev_out @block.tx[0]; i.prev_out_index 0; i.signature_key @key}
136   - t.output {|o|o.value 50e8; o.script {|s| s.type(:name_update)
137   - s.recipient("test", "testupdate", @new_key.addr) } } }], @new_key
  133 +#10.times do
  134 + # name_firstupdate should be valid now
  135 + @block = create_block @block.hash, true, [->(t) {
  136 + t.input {|i| i.prev_out @block.tx[0]; i.prev_out_index 0; i.signature_key @key }
  137 + t.output {|o| o.value 50e8; o.script {|s|; s.type(:name_firstupdate)
  138 + s.recipient("test", @rand, "testvalue", @key.addr) } } }], @key
138 139  
139   - name = @store.name_show("test")
140   - name.get_address.should == @new_key.addr
141   - name.value.should == "testupdate"
  140 +
  141 + Bitcoin::Script.new(@block.tx[1].out[0].pk_script).type.should == :name_firstupdate
  142 +
  143 + name = @store.name_show("test")
  144 + binding.pry unless name
  145 + name.get_address.should == @key.addr
  146 + name.name.should == "test"
  147 + name.value.should == "testvalue"
  148 + name.hash.should == Bitcoin.hash160(@rand + "test".hth)
  149 +
  150 + # create name_update
  151 + @new_key = Bitcoin::Key.generate
  152 + @block = create_block @block.hash, true, [->(t) {
  153 + t.input {|i| i.prev_out @block.tx[0]; i.prev_out_index 0; i.signature_key @key}
  154 + t.output {|o|o.value 50e8; o.script {|s| s.type(:name_update)
  155 + s.recipient("test", "testupdate", @new_key.addr) } } }], @new_key
  156 +
  157 + Bitcoin::Script.new(@block.tx[1].out[0].pk_script).type.should == :name_update
  158 +
  159 + name = @store.name_show("test")
  160 + name.get_address.should == @new_key.addr
  161 + name.value.should == "testupdate"
  162 + end
  163 +
142 164 end
143 165  
144 166 end