sighash sewgit
sign P2WPKH, P2WSH, P2SH-P2WPKH, P2WSH-MULTISIG, P2SH-P2WSH-MULTISIG
This commit is contained in:
parent
2ff46649d9
commit
3da185c241
BIN
docs/build/doctrees/environment.pickle
vendored
BIN
docs/build/doctrees/environment.pickle
vendored
Binary file not shown.
BIN
docs/build/doctrees/index.doctree
vendored
BIN
docs/build/doctrees/index.doctree
vendored
Binary file not shown.
BIN
docs/build/doctrees/transaction.doctree
vendored
BIN
docs/build/doctrees/transaction.doctree
vendored
Binary file not shown.
51
docs/build/html/_modules/pybtc/address.html
vendored
51
docs/build/html/_modules/pybtc/address.html
vendored
@ -78,10 +78,11 @@
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">hex</span> <span class="o">=</span> <span class="n">hexlify</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">key</span><span class="p">)</span><span class="o">.</span><span class="n">decode</span><span class="p">()</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">wif</span> <span class="o">=</span> <span class="n">private_key_to_wif</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">key</span><span class="p">,</span> <span class="n">compressed</span><span class="p">,</span> <span class="n">testnet</span><span class="p">)</span>
|
||||
<span class="k">return</span>
|
||||
<span class="k">assert</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">key</span><span class="p">,</span> <span class="nb">str</span><span class="p">)</span>
|
||||
<span class="k">if</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">key</span><span class="p">,</span> <span class="nb">str</span><span class="p">)</span> <span class="ow">or</span> <span class="ow">not</span> <span class="n">is_wif_valid</span><span class="p">(</span><span class="n">key</span><span class="p">):</span>
|
||||
<span class="k">raise</span> <span class="ne">TypeError</span><span class="p">(</span><span class="s2">"private key invalid"</span><span class="p">)</span>
|
||||
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">key</span> <span class="o">=</span> <span class="n">wif_to_private_key</span><span class="p">(</span><span class="n">key</span><span class="p">,</span> <span class="nb">hex</span><span class="o">=</span><span class="kc">False</span><span class="p">)</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">hex</span> <span class="o">=</span> <span class="n">hexlify</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">key</span><span class="p">)</span><span class="o">.</span><span class="n">decode</span><span class="p">()</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">wif</span> <span class="o">=</span> <span class="n">private_key_to_wif</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">key</span><span class="p">,</span> <span class="n">compressed</span><span class="p">,</span> <span class="n">testnet</span><span class="p">)</span>
|
||||
<span class="k">if</span> <span class="n">key</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="ow">in</span> <span class="p">(</span><span class="n">MAINNET_PRIVATE_KEY_UNCOMPRESSED_PREFIX</span><span class="p">,</span>
|
||||
<span class="n">TESTNET_PRIVATE_KEY_UNCOMPRESSED_PREFIX</span><span class="p">):</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">compressed</span> <span class="o">=</span> <span class="kc">False</span>
|
||||
@ -92,6 +93,7 @@
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">testnet</span> <span class="o">=</span> <span class="kc">True</span>
|
||||
<span class="k">else</span><span class="p">:</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">testnet</span> <span class="o">=</span> <span class="kc">False</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">wif</span> <span class="o">=</span> <span class="n">private_key_to_wif</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">key</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">compressed</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">testnet</span><span class="p">)</span>
|
||||
|
||||
<span class="k">def</span> <span class="nf">__str__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">wif</span></div>
|
||||
@ -252,6 +254,51 @@
|
||||
<span class="n">witness_version</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">witness_version</span><span class="p">,</span>
|
||||
<span class="n">testnet</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">testnet</span><span class="p">)</span>
|
||||
|
||||
<span class="nd">@classmethod</span>
|
||||
<span class="k">def</span> <span class="nf">multisig</span><span class="p">(</span><span class="bp">cls</span><span class="p">,</span> <span class="n">n</span><span class="p">,</span> <span class="n">m</span><span class="p">,</span> <span class="n">public_key_list</span><span class="p">,</span> <span class="n">testnet</span> <span class="o">=</span> <span class="kc">False</span><span class="p">):</span>
|
||||
<span class="sd">"""</span>
|
||||
<span class="sd"> The class method for creating a multisig address.</span>
|
||||
|
||||
<span class="sd"> :param n: count of required signatures (max 15).</span>
|
||||
<span class="sd"> :param m: count of total addresses of participants (max 15).</span>
|
||||
<span class="sd"> :param list address_list: addresses list, allowed types:</span>
|
||||
<span class="sd"> </span>
|
||||
<span class="sd"> - bytes or HEX encoded private key</span>
|
||||
<span class="sd"> - private key in WIF format</span>
|
||||
<span class="sd"> - PrivateKey instance,</span>
|
||||
<span class="sd"> - bytes or HEX encoded public key</span>
|
||||
<span class="sd"> - PublicKey instance</span>
|
||||
<span class="sd"> </span>
|
||||
<span class="sd"> </span>
|
||||
<span class="sd"> """</span>
|
||||
<span class="k">if</span> <span class="n">n</span> <span class="o">></span> <span class="mi">15</span> <span class="ow">or</span> <span class="n">m</span> <span class="o">></span> <span class="mi">15</span> <span class="ow">or</span> <span class="n">n</span> <span class="o">></span> <span class="n">m</span> <span class="ow">or</span> <span class="n">n</span> <span class="o"><</span> <span class="mi">1</span> <span class="ow">or</span> <span class="n">m</span> <span class="o"><</span> <span class="mi">1</span><span class="p">:</span>
|
||||
<span class="k">raise</span> <span class="ne">TypeError</span><span class="p">(</span><span class="s2">"invalid n of m maximum 15 of 15 multisig allowed"</span><span class="p">)</span>
|
||||
<span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">public_key_list</span><span class="p">)</span> <span class="o">!=</span> <span class="n">m</span><span class="p">:</span>
|
||||
<span class="k">raise</span> <span class="ne">TypeError</span><span class="p">(</span><span class="s2">"invalid address list count"</span><span class="p">)</span>
|
||||
<span class="n">script</span> <span class="o">=</span> <span class="nb">bytes</span><span class="p">([</span><span class="mh">0x50</span> <span class="o">+</span> <span class="n">n</span><span class="p">])</span>
|
||||
<span class="k">for</span> <span class="n">a</span> <span class="ow">in</span> <span class="nb">list</span><span class="p">(</span><span class="n">public_key_list</span><span class="p">):</span>
|
||||
<span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="nb">str</span><span class="p">):</span>
|
||||
<span class="k">try</span><span class="p">:</span>
|
||||
<span class="n">a</span> <span class="o">=</span> <span class="n">unhexlify</span><span class="p">(</span><span class="n">a</span><span class="p">)</span>
|
||||
<span class="k">except</span><span class="p">:</span>
|
||||
<span class="k">if</span> <span class="n">is_wif_valid</span><span class="p">(</span><span class="n">a</span><span class="p">):</span>
|
||||
<span class="n">a</span> <span class="o">=</span> <span class="n">private_to_public_key</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="nb">hex</span><span class="o">=</span><span class="kc">False</span><span class="p">)</span>
|
||||
<span class="k">pass</span>
|
||||
<span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">Address</span><span class="p">):</span>
|
||||
<span class="n">a</span> <span class="o">=</span> <span class="n">a</span><span class="o">.</span><span class="n">public_key</span><span class="o">.</span><span class="n">key</span>
|
||||
<span class="k">elif</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">PublicKey</span><span class="p">):</span>
|
||||
<span class="n">a</span> <span class="o">=</span> <span class="n">a</span><span class="o">.</span><span class="n">key</span>
|
||||
<span class="k">elif</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">PrivateKey</span><span class="p">):</span>
|
||||
<span class="n">a</span> <span class="o">=</span> <span class="n">private_to_public_key</span><span class="p">(</span><span class="n">a</span><span class="o">.</span><span class="n">key</span><span class="p">)</span>
|
||||
<span class="k">if</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="nb">bytes</span><span class="p">):</span>
|
||||
<span class="k">raise</span> <span class="ne">TypeError</span><span class="p">(</span><span class="s2">"invalid public key list element"</span><span class="p">)</span>
|
||||
<span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">a</span><span class="p">)</span> <span class="o">==</span> <span class="mi">32</span><span class="p">:</span>
|
||||
<span class="n">a</span> <span class="o">=</span> <span class="n">private_to_public_key</span><span class="p">(</span><span class="n">a</span><span class="p">)</span>
|
||||
<span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">a</span><span class="p">)</span> <span class="o">!=</span> <span class="mi">33</span><span class="p">:</span>
|
||||
<span class="k">raise</span> <span class="ne">TypeError</span><span class="p">(</span><span class="s2">"invalid public key list element size"</span><span class="p">)</span>
|
||||
<span class="n">script</span> <span class="o">+=</span> <span class="n">int_to_var_int</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">a</span><span class="p">))</span> <span class="o">+</span> <span class="n">a</span>
|
||||
<span class="n">script</span> <span class="o">+=</span> <span class="nb">bytes</span><span class="p">([</span><span class="mh">0x50</span> <span class="o">+</span> <span class="n">m</span><span class="p">])</span> <span class="o">+</span> <span class="n">OP_CHECKMULTISIG</span>
|
||||
<span class="k">return</span> <span class="bp">cls</span><span class="p">(</span><span class="n">script</span><span class="p">,</span> <span class="n">testnet</span><span class="o">=</span><span class="n">testnet</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
|
||||
</div>
|
||||
|
||||
1286
docs/build/html/_modules/pybtc/transaction.html
vendored
1286
docs/build/html/_modules/pybtc/transaction.html
vendored
File diff suppressed because it is too large
Load Diff
2
docs/build/html/_sources/index.rst.txt
vendored
2
docs/build/html/_sources/index.rst.txt
vendored
@ -44,7 +44,7 @@ Usage example::
|
||||
import pybtc
|
||||
a = pybtc.Address()
|
||||
print(a.address)
|
||||
print(a.private_key.wif())
|
||||
print(a.private_key.wif)
|
||||
|
||||
|
||||
|
||||
|
||||
3
docs/build/html/_sources/transaction.rst.txt
vendored
3
docs/build/html/_sources/transaction.rst.txt
vendored
@ -6,6 +6,7 @@ The class for creating transaction.
|
||||
|
||||
|
||||
.. autoclass:: pybtc.Transaction
|
||||
:members:
|
||||
:members:
|
||||
|
||||
|
||||
|
||||
|
||||
22
docs/build/html/genindex.html
vendored
22
docs/build/html/genindex.html
vendored
@ -41,9 +41,11 @@
|
||||
| <a href="#B"><strong>B</strong></a>
|
||||
| <a href="#C"><strong>C</strong></a>
|
||||
| <a href="#D"><strong>D</strong></a>
|
||||
| <a href="#E"><strong>E</strong></a>
|
||||
| <a href="#G"><strong>G</strong></a>
|
||||
| <a href="#H"><strong>H</strong></a>
|
||||
| <a href="#I"><strong>I</strong></a>
|
||||
| <a href="#J"><strong>J</strong></a>
|
||||
| <a href="#K"><strong>K</strong></a>
|
||||
| <a href="#M"><strong>M</strong></a>
|
||||
| <a href="#P"><strong>P</strong></a>
|
||||
@ -113,6 +115,8 @@
|
||||
<h2 id="D">D</h2>
|
||||
<table style="width: 100%" class="indextable genindextable"><tr>
|
||||
<td style="width: 33%; vertical-align: top;"><ul>
|
||||
<li><a href="transaction.html#pybtc.Transaction.decode">decode() (pybtc.Transaction method)</a>
|
||||
</li>
|
||||
<li><a href="functional.html#pybtc.decode_script">decode_script() (in module pybtc)</a>
|
||||
</li>
|
||||
</ul></td>
|
||||
@ -124,6 +128,14 @@
|
||||
</ul></td>
|
||||
</tr></table>
|
||||
|
||||
<h2 id="E">E</h2>
|
||||
<table style="width: 100%" class="indextable genindextable"><tr>
|
||||
<td style="width: 33%; vertical-align: top;"><ul>
|
||||
<li><a href="transaction.html#pybtc.Transaction.encode">encode() (pybtc.Transaction method)</a>
|
||||
</li>
|
||||
</ul></td>
|
||||
</tr></table>
|
||||
|
||||
<h2 id="G">G</h2>
|
||||
<table style="width: 100%" class="indextable genindextable"><tr>
|
||||
<td style="width: 33%; vertical-align: top;"><ul>
|
||||
@ -174,6 +186,14 @@
|
||||
</ul></td>
|
||||
</tr></table>
|
||||
|
||||
<h2 id="J">J</h2>
|
||||
<table style="width: 100%" class="indextable genindextable"><tr>
|
||||
<td style="width: 33%; vertical-align: top;"><ul>
|
||||
<li><a href="transaction.html#pybtc.Transaction.json">json() (pybtc.Transaction method)</a>
|
||||
</li>
|
||||
</ul></td>
|
||||
</tr></table>
|
||||
|
||||
<h2 id="K">K</h2>
|
||||
<table style="width: 100%" class="indextable genindextable"><tr>
|
||||
<td style="width: 33%; vertical-align: top;"><ul>
|
||||
@ -254,6 +274,8 @@
|
||||
</ul></td>
|
||||
<td style="width: 33%; vertical-align: top;"><ul>
|
||||
<li><a href="functional.html#pybtc.script_to_hash">script_to_hash() (in module pybtc)</a>
|
||||
</li>
|
||||
<li><a href="transaction.html#pybtc.Transaction.serialize">serialize() (pybtc.Transaction method)</a>
|
||||
</li>
|
||||
<li><a href="functional.html#pybtc.sign_message">sign_message() (in module pybtc)</a>
|
||||
</li>
|
||||
|
||||
2
docs/build/html/index.html
vendored
2
docs/build/html/index.html
vendored
@ -59,7 +59,7 @@
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">pybtc</span>
|
||||
<span class="n">a</span> <span class="o">=</span> <span class="n">pybtc</span><span class="o">.</span><span class="n">Address</span><span class="p">()</span>
|
||||
<span class="nb">print</span><span class="p">(</span><span class="n">a</span><span class="o">.</span><span class="n">address</span><span class="p">)</span>
|
||||
<span class="nb">print</span><span class="p">(</span><span class="n">a</span><span class="o">.</span><span class="n">private_key</span><span class="o">.</span><span class="n">wif</span><span class="p">())</span>
|
||||
<span class="nb">print</span><span class="p">(</span><span class="n">a</span><span class="o">.</span><span class="n">private_key</span><span class="o">.</span><span class="n">wif</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
BIN
docs/build/html/objects.inv
vendored
BIN
docs/build/html/objects.inv
vendored
Binary file not shown.
2
docs/build/html/searchindex.js
vendored
2
docs/build/html/searchindex.js
vendored
File diff suppressed because one or more lines are too long
75
docs/build/html/transaction.html
vendored
75
docs/build/html/transaction.html
vendored
@ -39,8 +39,79 @@
|
||||
<p>The class for creating transaction.</p>
|
||||
<dl class="class">
|
||||
<dt id="pybtc.Transaction">
|
||||
<em class="property">class </em><code class="descclassname">pybtc.</code><code class="descname">Transaction</code><span class="sig-paren">(</span><em>raw_tx=None</em>, <em>tx_format='decoded'</em>, <em>version=1</em>, <em>lockTime=0</em>, <em>testnet=False</em><span class="sig-paren">)</span><a class="reference internal" href="_modules/pybtc/transaction.html#Transaction"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#pybtc.Transaction" title="Permalink to this definition">¶</a></dt>
|
||||
<dd></dd></dl>
|
||||
<em class="property">class </em><code class="descclassname">pybtc.</code><code class="descname">Transaction</code><span class="sig-paren">(</span><em>raw_tx=None</em>, <em>tx_format='decoded'</em>, <em>version=1</em>, <em>lock_time=0</em>, <em>testnet=False</em><span class="sig-paren">)</span><a class="reference internal" href="_modules/pybtc/transaction.html#Transaction"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#pybtc.Transaction" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>The class for Transaction object</p>
|
||||
<table class="docutils field-list" frame="void" rules="none">
|
||||
<col class="field-name" />
|
||||
<col class="field-body" />
|
||||
<tbody valign="top">
|
||||
<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><ul class="first last simple">
|
||||
<li><strong>raw_tx</strong> – (optional) raw transaction in bytes or HEX encoded string, if no raw transaction provided
|
||||
well be created new empty transaction template.</li>
|
||||
<li><strong>tx_format</strong> – “raw” or “decoded” format. Raw format is mean that all transaction represented in bytes
|
||||
for best performance.
|
||||
Decoded transaction is represented in human readable format using base68, hex, bech32,
|
||||
asm and opcodes. By default “decoded” format using.</li>
|
||||
<li><strong>version</strong> (<a class="reference external" href="https://docs.python.org/3/library/functions.html#int" title="(in Python v3.6)"><em>int</em></a>) – transaction version for new template, by default 1.</li>
|
||||
<li><strong>lock_time</strong> (<a class="reference external" href="https://docs.python.org/3/library/functions.html#int" title="(in Python v3.6)"><em>int</em></a>) – transaction lock time for new template, by default 0.</li>
|
||||
<li><strong>testnet</strong> (<em>boolean</em>) – address type for “decoded” transaction representation.</li>
|
||||
</ul>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<dl class="method">
|
||||
<dt id="pybtc.Transaction.decode">
|
||||
<code class="descname">decode</code><span class="sig-paren">(</span><em>testnet=None</em><span class="sig-paren">)</span><a class="reference internal" href="_modules/pybtc/transaction.html#Transaction.decode"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#pybtc.Transaction.decode" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>change Transacion object representation to “decoded” human readable format</p>
|
||||
<table class="docutils field-list" frame="void" rules="none">
|
||||
<col class="field-name" />
|
||||
<col class="field-body" />
|
||||
<tbody valign="top">
|
||||
<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><strong>testnet</strong> (<a class="reference external" href="https://docs.python.org/3/library/functions.html#bool" title="(in Python v3.6)"><em>bool</em></a>) – (optional) address type for “decoded” transaction representation, by default None.
|
||||
if None used type from transaction property “format”.</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="method">
|
||||
<dt id="pybtc.Transaction.encode">
|
||||
<code class="descname">encode</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="reference internal" href="_modules/pybtc/transaction.html#Transaction.encode"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#pybtc.Transaction.encode" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>change Transaction object representation to “raw” bytes format,
|
||||
all human readable part will be stripped.</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="method">
|
||||
<dt id="pybtc.Transaction.json">
|
||||
<code class="descname">json</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="reference internal" href="_modules/pybtc/transaction.html#Transaction.json"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#pybtc.Transaction.json" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>Get json transaction representation</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="method">
|
||||
<dt id="pybtc.Transaction.serialize">
|
||||
<code class="descname">serialize</code><span class="sig-paren">(</span><em>segwit=True</em>, <em>hex=True</em><span class="sig-paren">)</span><a class="reference internal" href="_modules/pybtc/transaction.html#Transaction.serialize"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#pybtc.Transaction.serialize" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>Get serialized transaction</p>
|
||||
<table class="docutils field-list" frame="void" rules="none">
|
||||
<col class="field-name" />
|
||||
<col class="field-body" />
|
||||
<tbody valign="top">
|
||||
<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><ul class="first simple">
|
||||
<li><strong>segwit</strong> (<a class="reference external" href="https://docs.python.org/3/library/functions.html#bool" title="(in Python v3.6)"><em>bool</em></a>) – (optional) flag for segwit representation of serialized transaction, by
|
||||
default True.</li>
|
||||
<li><strong>hex</strong> (<a class="reference external" href="https://docs.python.org/3/library/functions.html#bool" title="(in Python v3.6)"><em>bool</em></a>) – (optional) if set to True return HEX encoded string, by default True.</li>
|
||||
</ul>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="field-even field"><th class="field-name" colspan="2">Return str,bytes:</th></tr>
|
||||
<tr class="field-even field"><td> </td><td class="field-body"><p class="first last">serialized transaction in HEX or bytes.</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</dd></dl>
|
||||
|
||||
</dd></dl>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
@ -6,6 +6,7 @@ The class for creating transaction.
|
||||
|
||||
|
||||
.. autoclass:: pybtc.Transaction
|
||||
:members:
|
||||
:members:
|
||||
|
||||
|
||||
|
||||
|
||||
@ -43,10 +43,11 @@ class PrivateKey():
|
||||
self.hex = hexlify(self.key).decode()
|
||||
self.wif = private_key_to_wif(self.key, compressed, testnet)
|
||||
return
|
||||
assert isinstance(key, str)
|
||||
if not isinstance(key, str) or not is_wif_valid(key):
|
||||
raise TypeError("private key invalid")
|
||||
|
||||
self.key = wif_to_private_key(key, hex=False)
|
||||
self.hex = hexlify(self.key).decode()
|
||||
self.wif = private_key_to_wif(self.key, compressed, testnet)
|
||||
if key[0] in (MAINNET_PRIVATE_KEY_UNCOMPRESSED_PREFIX,
|
||||
TESTNET_PRIVATE_KEY_UNCOMPRESSED_PREFIX):
|
||||
self.compressed = False
|
||||
@ -57,6 +58,7 @@ class PrivateKey():
|
||||
self.testnet = True
|
||||
else:
|
||||
self.testnet = False
|
||||
self.wif = private_key_to_wif(self.key, self.compressed, self.testnet)
|
||||
|
||||
def __str__(self):
|
||||
return self.wif
|
||||
@ -201,15 +203,18 @@ class Address():
|
||||
|
||||
|
||||
class ScriptAddress():
|
||||
def __init__(self, script, address_type="P2SH",
|
||||
testnet=False, witness_version=None):
|
||||
def __init__(self, script,
|
||||
testnet=False, witness_version=0):
|
||||
self.witness_version = witness_version
|
||||
self.testnet = testnet
|
||||
if isinstance(script, str):
|
||||
script = unhexlify(script)
|
||||
self.script = script
|
||||
self.script_hex = hexlify(self.script).decode()
|
||||
self.hash = hash160(self.script)
|
||||
if witness_version is None:
|
||||
self.hash = hash160(self.script)
|
||||
else:
|
||||
self.hash = sha256(self.script)
|
||||
self.script_opcodes = decode_script(self.script)
|
||||
self.script_opcodes_asm = decode_script(self.script, 1)
|
||||
self.address = hash_to_address(self.hash,
|
||||
@ -217,3 +222,49 @@ class ScriptAddress():
|
||||
witness_version=self.witness_version,
|
||||
testnet=self.testnet)
|
||||
|
||||
@classmethod
|
||||
def multisig(cls, n, m, public_key_list,
|
||||
testnet=False, witness_version=0):
|
||||
"""
|
||||
The class method for creating a multisig address.
|
||||
|
||||
:param n: count of required signatures (max 15).
|
||||
:param m: count of total addresses of participants (max 15).
|
||||
:param list address_list: addresses list, allowed types:
|
||||
|
||||
- bytes or HEX encoded private key
|
||||
- private key in WIF format
|
||||
- PrivateKey instance,
|
||||
- bytes or HEX encoded public key
|
||||
- PublicKey instance
|
||||
|
||||
|
||||
"""
|
||||
if n > 15 or m > 15 or n > m or n < 1 or m < 1:
|
||||
raise TypeError("invalid n of m maximum 15 of 15 multisig allowed")
|
||||
if len(public_key_list) != m:
|
||||
raise TypeError("invalid address list count")
|
||||
script = bytes([0x50 + n])
|
||||
for a in list(public_key_list):
|
||||
if isinstance(a, str):
|
||||
try:
|
||||
a = unhexlify(a)
|
||||
except:
|
||||
if is_wif_valid(a):
|
||||
a = private_to_public_key(a, hex=False)
|
||||
pass
|
||||
if isinstance(a, Address):
|
||||
a = a.public_key.key
|
||||
elif isinstance(a, PublicKey):
|
||||
a = a.key
|
||||
elif isinstance(a, PrivateKey):
|
||||
a = private_to_public_key(a.key)
|
||||
if not isinstance(a, bytes):
|
||||
raise TypeError("invalid public key list element")
|
||||
if len(a) == 32:
|
||||
a = private_to_public_key(a)
|
||||
if len(a) != 33:
|
||||
raise TypeError("invalid public key list element size")
|
||||
script += int_to_var_int(len(a)) + a
|
||||
script += bytes([0x50 + m]) + OP_CHECKMULTISIG
|
||||
return cls(script, testnet=testnet, witness_version=witness_version)
|
||||
|
||||
@ -11,8 +11,8 @@ OPCODE["OP_PUSHDATA2"] = 0x4d
|
||||
OPCODE["OP_PUSHDATA4"] = 0x4e
|
||||
OPCODE["OP_1NEGATE"] = 0x4f
|
||||
OPCODE["OP_RESERVED"] = 0x50
|
||||
OPCODE["OP_1"] = 0x51
|
||||
OPCODE["OP_TRUE"] = 0x51
|
||||
OPCODE["OP_1"] = 0x51
|
||||
OPCODE["OP_2"] = 0x52
|
||||
OPCODE["OP_3"] = 0x53
|
||||
OPCODE["OP_4"] = 0x54
|
||||
|
||||
124
pybtc/tools.py
124
pybtc/tools.py
@ -438,6 +438,13 @@ def get_witness_version(address):
|
||||
|
||||
# Script
|
||||
|
||||
def public_key_to_pubkey_script(key, hex=True):
|
||||
if isinstance(key, str):
|
||||
key = unhexlify(key)
|
||||
s = bytes([len(key)]) + key + OP_CHECKSIG
|
||||
return hexlify(s).decode() if hex else s
|
||||
|
||||
|
||||
def parse_script(script, segwit=True):
|
||||
"""
|
||||
Parse script and return script type, script address and required signatures count.
|
||||
@ -552,9 +559,10 @@ def decode_script(script, asm=False):
|
||||
Decode script to ASM format or to human readable OPCODES string.
|
||||
|
||||
:param script: script in bytes string or HEX encoded string format.
|
||||
:param asm: (optional) If set to True decode to ASM fromat, by default set to False.
|
||||
:param asm: (optional) If set to True decode to ASM format, by default set to False.
|
||||
:return: script in ASM format string or OPCODES string.
|
||||
"""
|
||||
|
||||
if isinstance(script, str):
|
||||
try:
|
||||
script = unhexlify(script)
|
||||
@ -573,14 +581,35 @@ def decode_script(script, asm=False):
|
||||
result.append('[%s]' % script[s])
|
||||
s += script[s] + 1
|
||||
continue
|
||||
elif script[s] == OPCODE["OP_PUSHDATA1"]:
|
||||
s += 1 + script[s + 1]
|
||||
|
||||
if script[s] == OPCODE["OP_PUSHDATA1"]:
|
||||
ld = script[s + 1]
|
||||
if asm:
|
||||
result.append(hexlify(script[s + 1:s + 1 + ld]).decode())
|
||||
else:
|
||||
result.append(RAW_OPCODE[script[s]])
|
||||
result.append('[%s]' % ld)
|
||||
s += 1 + script[s + 1] + 1
|
||||
elif script[s] == OPCODE["OP_PUSHDATA2"]:
|
||||
s += 2 + struct.unpack('<H', script[s: s + 2])
|
||||
|
||||
ld = struct.unpack('<H', script[s+1: s + 3])[0]
|
||||
if asm:
|
||||
result.append(hexlify(script[s + 1:s + 1 + ld]).decode())
|
||||
else:
|
||||
result.append(RAW_OPCODE[script[s]])
|
||||
result.append('[%s]' % ld)
|
||||
s += 2 + 1 + ld
|
||||
elif script[s] == OPCODE["OP_PUSHDATA4"]:
|
||||
s += 4 + struct.unpack('<L', script[s: s + 4])
|
||||
result.append(RAW_OPCODE[script[s]])
|
||||
s += 1
|
||||
ld = struct.unpack('<L', script[s + 1: s + 5])[0]
|
||||
if asm:
|
||||
result.append(hexlify(script[s + 1:s + 1 + ld]).decode())
|
||||
else:
|
||||
result.append(RAW_OPCODE[script[s]])
|
||||
result.append('[%s]' % ld)
|
||||
s += 5 + 1 + ld
|
||||
else:
|
||||
result.append(RAW_OPCODE[script[s]])
|
||||
s += 1
|
||||
return ' '.join(result)
|
||||
|
||||
|
||||
@ -673,7 +702,44 @@ def script_to_hash(script, witness=False, hex=True):
|
||||
return hash160(script, hex)
|
||||
|
||||
|
||||
# Signatures
|
||||
def op_push_data(data):
|
||||
if len(data) <= 0x4b:
|
||||
return b''.join([bytes([len(data)]),data])
|
||||
elif len(data) <= 0xff:
|
||||
return b''.join([OP_PUSHDATA1, bytes([len(data)]), data])
|
||||
elif len(data) <= 0xffff:
|
||||
return b''.join([OP_PUSHDATA2, int_to_bytes(len(data), byteorder="little"), data])
|
||||
|
||||
else:
|
||||
return b''.join([OP_PUSHDATA4, int_to_bytes(len(data), byteorder="little"), data])
|
||||
|
||||
|
||||
def get_multisig_public_keys(script):
|
||||
pub_keys = []
|
||||
s = get_stream(script)
|
||||
o, d = read_opcode(s)
|
||||
while o:
|
||||
o, d = read_opcode(s)
|
||||
if d:
|
||||
pub_keys.append(d)
|
||||
return pub_keys
|
||||
|
||||
|
||||
def read_opcode(stream):
|
||||
b = stream.read(1)
|
||||
if not b:
|
||||
return None, None
|
||||
if b[0] <= 0x4b:
|
||||
return b, stream.read(b[0])
|
||||
elif b[0] == OP_PUSHDATA1:
|
||||
return b, stream.read(stream.read(1)[0])
|
||||
elif b[0] == OP_PUSHDATA2:
|
||||
return b, stream.read(struct.unpack("<H", stream.read(2)[0]))
|
||||
elif b[0] == OP_PUSHDATA4:
|
||||
return b, stream.read(struct.unpack("<L", stream.read(4)[0]))
|
||||
else:
|
||||
return b, None
|
||||
|
||||
|
||||
def verify_signature(sig, pub_key, msg):
|
||||
"""
|
||||
@ -759,9 +825,51 @@ def sign_message(msg, private_key, hex=True):
|
||||
if not res:
|
||||
raise RuntimeError("secp256k1 error")
|
||||
signature = bytes(ffi.buffer(output, outputlen[0]))
|
||||
raw_sig = ffi.new('secp256k1_ecdsa_signature *')
|
||||
return hexlify(signature).decode() if hex else signature
|
||||
|
||||
|
||||
def public_key_recovery(signature, messsage, rec_id, compressed=True, hex=True):
|
||||
if isinstance(signature, str):
|
||||
signature = unhexlify(signature)
|
||||
if isinstance(messsage, str):
|
||||
messsage = unhexlify(messsage)
|
||||
raw_sig = ffi.new('secp256k1_ecdsa_signature *')
|
||||
r = secp256k1.secp256k1_ecdsa_signature_parse_der(ECDSA_CONTEXT_SIGN,
|
||||
raw_sig,
|
||||
signature,
|
||||
len(signature))
|
||||
if not r:
|
||||
raise RuntimeError("secp256k1 error")
|
||||
compact_sig = ffi.new('unsigned char[%d]' % 64)
|
||||
r = secp256k1.secp256k1_ecdsa_signature_serialize_compact(ECDSA_CONTEXT_VERIFY,
|
||||
compact_sig,
|
||||
raw_sig)
|
||||
if not r:
|
||||
raise RuntimeError("secp256k1 error")
|
||||
|
||||
recover_sig = ffi.new('secp256k1_ecdsa_recoverable_signature *')
|
||||
t = secp256k1.secp256k1_ecdsa_recoverable_signature_parse_compact(
|
||||
ECDSA_CONTEXT_ALL, recover_sig, compact_sig, rec_id)
|
||||
if not r:
|
||||
raise RuntimeError("secp256k1 error")
|
||||
|
||||
pubkey_ptr = ffi.new('secp256k1_pubkey *')
|
||||
t = secp256k1.secp256k1_ecdsa_recover(
|
||||
ECDSA_CONTEXT_ALL, pubkey_ptr, recover_sig, messsage)
|
||||
len_key = 33 if compressed else 65
|
||||
pubkey = ffi.new('char [%d]' % len_key)
|
||||
outlen = ffi.new('size_t *', len_key)
|
||||
compflag = EC_COMPRESSED if compressed else EC_UNCOMPRESSED
|
||||
if bytes(ffi.buffer(pubkey_ptr.data, 64)) == b"\x00" * 64:
|
||||
return None
|
||||
r = secp256k1.secp256k1_ec_pubkey_serialize(ECDSA_CONTEXT_VERIFY, pubkey, outlen, pubkey_ptr, compflag)
|
||||
if not r:
|
||||
raise RuntimeError("secp256k1 error")
|
||||
pub = bytes(ffi.buffer(pubkey, len_key))
|
||||
return hexlify(pub).decode() if hex else pub
|
||||
|
||||
|
||||
def is_valid_signature_encoding(sig):
|
||||
"""
|
||||
Check is valid signature encoded in DER format
|
||||
|
||||
1593
pybtc/transaction.py
1593
pybtc/transaction.py
File diff suppressed because it is too large
Load Diff
@ -1,9 +1,9 @@
|
||||
from .hash_functions import *
|
||||
from .integer import *
|
||||
from .address_functions import *
|
||||
from .address_class import *
|
||||
from .ecdsa import *
|
||||
from .transaction_deserialize import *
|
||||
# from .hash_functions import *
|
||||
# from .integer import *
|
||||
# from .address_functions import *
|
||||
# from .address_class import *
|
||||
# from .ecdsa import *
|
||||
# from .transaction_deserialize import *
|
||||
from .transaction_constructor import *
|
||||
|
||||
|
||||
|
||||
@ -6,6 +6,7 @@ if parentPath not in sys.path:
|
||||
|
||||
|
||||
from pybtc import address
|
||||
from pybtc.transaction import *
|
||||
from pybtc import OPCODE
|
||||
from binascii import unhexlify
|
||||
|
||||
@ -16,6 +17,25 @@ class AddressClassTests(unittest.TestCase):
|
||||
print("\nTesting address class:\n")
|
||||
|
||||
def test_is_WIF_valid(self):
|
||||
# mainnet
|
||||
self.assertEqual(address.PrivateKey("7B56E2B7BD189F4491D43A1D209E6268046DF1741F61B6397349D7AA54978E76",
|
||||
compressed=True, testnet=False).wif,
|
||||
'L1MU1jUjUwZ6Fd1L2HDZ8qH4oSWxct5boCQ4C87YvoSZbTW41hg4')
|
||||
self.assertEqual(address.PrivateKey("7B56E2B7BD189F4491D43A1D209E6268046DF1741F61B6397349D7AA54978E76",
|
||||
compressed=False, testnet=False).wif,
|
||||
'5Jkc7xqsrqA5pGQdwDHSQXRV3pUBLTXVjBjqJUSVz3pUmyuAFwP')
|
||||
# testnet
|
||||
self.assertEqual(address.PrivateKey("7B56E2B7BD189F4491D43A1D209E6268046DF1741F61B6397349D7AA54978E76",
|
||||
compressed=True, testnet=True).wif,
|
||||
'cRiTUeUav1FMR4UbQh2gW9n8RfpNHLBHsEYXJYa4Rv6ZrCdTPGqv')
|
||||
self.assertEqual(address.PrivateKey("7B56E2B7BD189F4491D43A1D209E6268046DF1741F61B6397349D7AA54978E76",
|
||||
compressed=False, testnet=True).wif,
|
||||
'92XEhhfRT4EDnKuvZZBMH7yShUptVd4h58bnP6o1KnZXYzkVa55')
|
||||
|
||||
self.assertEqual(address.PrivateKey("L1MU1jUjUwZ6Fd1L2HDZ8qH4oSWxct5boCQ4C87YvoSZbTW41hg4",
|
||||
compressed=False, testnet=True).wif,
|
||||
'L1MU1jUjUwZ6Fd1L2HDZ8qH4oSWxct5boCQ4C87YvoSZbTW41hg4')
|
||||
|
||||
p = address.PrivateKey("L1MU1jUjUwZ6Fd1L2HDZ8qH4oSWxct5boCQ4C87YvoSZbTW41hg4")
|
||||
pub = address.PublicKey(p)
|
||||
a = address.Address(p)
|
||||
@ -29,7 +49,30 @@ class AddressClassTests(unittest.TestCase):
|
||||
self.assertEqual(a.redeem_script_hex, '001434370a8d74e9965d7aade2ba2f30110b321bf236')
|
||||
self.assertEqual(a.public_key.hex, '02a8fb85e98c99b79150df12fde488639d8445c57babef83d53c66c1e5c818eeb4')
|
||||
|
||||
cpk = "02a8fb85e98c99b79150df12fde488639d8445c57babef83d53c66c1e5c818eeb4"
|
||||
ucpk = "04a8fb85e98c99b79150df12fde488639d8445c57babef83d53c66c1e5c818eeb" \
|
||||
"43bbd96a641808e5f34eb568e804fe679de82de419e2512736ea09013a82324a6"
|
||||
# public key uncompressed from HEX private
|
||||
self.assertEqual(address.PublicKey("7b56e2b7bd189f4491d43a1d209e6268046df1741f61b6397349d7aa54978e76",
|
||||
compressed=False).hex, ucpk)
|
||||
# public key compressed from HEX private
|
||||
self.assertEqual(address.PublicKey("7b56e2b7bd189f4491d43a1d209e6268046df1741f61b6397349d7aa54978e76",
|
||||
compressed=True).hex, cpk)
|
||||
# public key compressed from WIF private
|
||||
self.assertEqual(address.PublicKey("L1MU1jUjUwZ6Fd1L2HDZ8qH4oSWxct5boCQ4C87YvoSZbTW41hg4",
|
||||
compressed=False).hex, cpk)
|
||||
# public key compressed from PrivateKey instance (flags have no effect)
|
||||
p = address.PrivateKey("L1MU1jUjUwZ6Fd1L2HDZ8qH4oSWxct5boCQ4C87YvoSZbTW41hg4")
|
||||
self.assertEqual(address.PublicKey(p, compressed=False).hex, cpk)
|
||||
|
||||
# public key compressed from public
|
||||
self.assertEqual(address.PublicKey(cpk, compressed=False).hex, cpk)
|
||||
|
||||
# public key compressed from public
|
||||
self.assertEqual(address.PublicKey(unhexlify(cpk), compressed=False).hex, cpk)
|
||||
|
||||
# compressed public key
|
||||
# private key hex string to compressed pub key
|
||||
p = address.PrivateKey("7b56e2b7bd189f4491d43a1d209e6268046df1741f61b6397349d7aa54978e76", compressed=False)
|
||||
pub = address.PublicKey(p)
|
||||
a = address.Address(p, address_type="P2PKH")
|
||||
@ -51,13 +94,18 @@ class AddressClassTests(unittest.TestCase):
|
||||
self.assertEqual(a.public_key.hex, '02a8fb85e98c99b79150df12fde488639d8445c57babef83d53c66c1e5c818eeb4')
|
||||
|
||||
# from uncompressed pubkey
|
||||
p = address.PublicKey('04a8fb85e98c99b79150df12fde488639d8445c57babef83d53c66c1e5c818eeb43bbd96a641808e5f34eb568e804fe679de82de419e2512736ea09013a82324a6')
|
||||
p = address.PublicKey('04a8fb85e98c99b79150df12fde488639d8445c57babef83d53c66c1e5c818eeb43bbd96a641808'
|
||||
'e5f34eb568e804fe679de82de419e2512736ea09013a82324a6')
|
||||
a = address.Address(p, address_type="P2PKH")
|
||||
self.assertEqual(a.address, '17suVjHXyWF9KiGkpRRQW4ysiEqdDkRqo1')
|
||||
a = address.Address(p, address_type="PUBKEY")
|
||||
self.assertEqual(a.address, '17suVjHXyWF9KiGkpRRQW4ysiEqdDkRqo1')
|
||||
|
||||
redeem = "5221032bfc25cf7cccc278b26473e2967b8fd403b4b544b836e71abdfebb08d8c96d6921032bfc25cf7cccc278b26473e2967b8fd403b4b544b836e71abdfebb08d8c96d6921032bfc25cf7cccc278b26473e2967b8fd403b4b544b836e71abdfebb08d8c96d6953ae"
|
||||
redeem = "5221032bfc25cf7cccc278b26473e2967b8fd403b4b544b836e71abdfebb08d8c96d6921032bfc25cf7cccc278b2" \
|
||||
"6473e2967b8fd403b4b544b836e71abdfebb08d8c96d6921032bfc25cf7cccc278b26473e2967b8fd403b4b544b8" \
|
||||
"36e71abdfebb08d8c96d6953ae"
|
||||
a = address.ScriptAddress(redeem)
|
||||
print(a.script_opcodes_asm)
|
||||
self.assertEqual(a.address, '3KCqqS6eznp3ucVPxtNkiYcVg6kQKNX9sg')
|
||||
self.assertEqual(a.address, '3KCqqS6eznp3ucVPxtNkiYcVg6kQKNX9sg')
|
||||
|
||||
|
||||
|
||||
|
||||
@ -4,8 +4,7 @@ parentPath = os.path.abspath("..")
|
||||
if parentPath not in sys.path:
|
||||
sys.path.insert(0, parentPath)
|
||||
from pybtc import *
|
||||
from binascii import unhexlify
|
||||
from pybtc import address_to_hash as address2hash160
|
||||
|
||||
|
||||
class SighashTests(unittest.TestCase):
|
||||
@classmethod
|
||||
@ -517,86 +516,70 @@ class SighashTests(unittest.TestCase):
|
||||
]
|
||||
for k in t:
|
||||
tx = Transaction(k[0])
|
||||
self.assertEqual(tx.sig_hash_input(k[2], k[1], k[3]), k[4])
|
||||
self.assertEqual(tx.sig_hash(k[2], k[1], k[3]), k[4])
|
||||
|
||||
def test_sighash_segwit(self):
|
||||
"""
|
||||
["raw_transaction, script, input_index, hashType, signature_hash (result)"],
|
||||
:return:
|
||||
"""
|
||||
print("\nNative P2WPKH")
|
||||
raw_tx = "0100000002fff7f7881a8099afa6940d42d1e7f6362bec38171ea3edf433541db4e4ad969f0000000000eeffffffef51e1b804cc89d182d279655c3aa89e815b1b309fe287d9b2b55d57b90ec68a0100000000ffffffff02202cb206000000001976a9148280b37df378db99f66f85c95a783a76ac7a6d5988ac9093510d000000001976a9143bde42dbee7e4dbe6a21b2d50ce2f0167faa815988ac11000000"
|
||||
self.assertEqual(Transaction(raw_tx).sig_hash_segwit(1, 600000000, "1976a9141d0f172a0ecb48aee1be1f2687"
|
||||
"d2963ae33f71a188ac",
|
||||
SIGHASH_ALL),
|
||||
"c37af31116d1b27caf68aae9e3ac82f1477929014d5b917657d0eb49478cb670")
|
||||
|
||||
|
||||
print("P2SH-P2WPKH")
|
||||
raw_tx = "0100000001db6b1b20aa0fd7b23880be2ecbd4a98130974cf4748fb66092ac4d3ceb1a54770100000000feffffff02b8b4eb0b000000001976a914a457b684d7f0d539a46a45bbc043f35b59d0d96388ac0008af2f000000001976a914fd270b1ee6abcaea97fea7ad0402e8bd8ad6d77c88ac92040000"
|
||||
self.assertEqual(Transaction(raw_tx).sig_hash_segwit(0, 1000000000,
|
||||
"1976a91479091972186c449eb1ded22b78e40d009bdf008988ac",
|
||||
SIGHASH_ALL),
|
||||
"64f3b0f4dd2bb3aa1ce8566d220cc74dda9df97d8490cc81d89d735c92e59fb6")
|
||||
print("Native P2WSH")
|
||||
raw_tx = "0100000002fe3dc9208094f3ffd12645477b3dc56f60ec4fa8e6f5d67c565d1c6b9216b36e0000000000ffffffff0815cf020f013ed6cf91d29f4202e8a58726b1ac6c79da47c23d1bee0a6925f80000000000ffffffff0100f2052a010000001976a914a30741f8145e5acadf23f751864167f32e0963f788ac00000000"
|
||||
self.assertEqual(Transaction(raw_tx).sig_hash_segwit(1, 4900000000,
|
||||
"23210255a9626aebf5e29c0e6538428ba0d1dcf6ca98ffdf086aa8ced5e0d0215ea465ac",
|
||||
SIGHASH_SINGLE),
|
||||
"fef7bd749cce710c5c052bd796df1af0d935e59cea63736268bcbe2d2134fc47")
|
||||
|
||||
# def test_sighash_segwit(self):
|
||||
# """
|
||||
# ["raw_transaction, script, input_index, hashType, signature_hash (result)"],
|
||||
# :return:
|
||||
# """
|
||||
# print("\nNative P2WPKH")
|
||||
# raw_tx = "0100000002fff7f7881a8099afa6940d42d1e7f6362bec38171ea3edf433541db4e4ad969f0000000000eeffffffef51e1b804cc89d182d279655c3aa89e815b1b309fe287d9b2b55d57b90ec68a0100000000ffffffff02202cb206000000001976a9148280b37df378db99f66f85c95a783a76ac7a6d5988ac9093510d000000001976a9143bde42dbee7e4dbe6a21b2d50ce2f0167faa815988ac11000000"
|
||||
# self.assertEqual((Transaction.deserialize(raw_tx).sighash_segwit(SIGHASH_ALL,
|
||||
# 1,
|
||||
# "1976a9141d0f172a0ecb48aee1be1f2687d2963ae33f71a188ac",
|
||||
# 600000000,
|
||||
# True)),
|
||||
# "c37af31116d1b27caf68aae9e3ac82f1477929014d5b917657d0eb49478cb670")
|
||||
# print(Script("c37af31116d1b27caf68aae9e3ac82f1477929014d5b917657d0eb49478cb670").type)
|
||||
# print("P2SH-P2WPKH")
|
||||
# raw_tx = "0100000001db6b1b20aa0fd7b23880be2ecbd4a98130974cf4748fb66092ac4d3ceb1a54770100000000feffffff02b8b4eb0b000000001976a914a457b684d7f0d539a46a45bbc043f35b59d0d96388ac0008af2f000000001976a914fd270b1ee6abcaea97fea7ad0402e8bd8ad6d77c88ac92040000"
|
||||
# self.assertEqual((Transaction.deserialize(raw_tx).sighash_segwit(SIGHASH_ALL,
|
||||
# 0,
|
||||
# "1976a91479091972186c449eb1ded22b78e40d009bdf008988ac",
|
||||
# 1000000000,
|
||||
# True)),
|
||||
# "64f3b0f4dd2bb3aa1ce8566d220cc74dda9df97d8490cc81d89d735c92e59fb6")
|
||||
# print("Native P2WSH")
|
||||
# raw_tx = "0100000002fe3dc9208094f3ffd12645477b3dc56f60ec4fa8e6f5d67c565d1c6b9216b36e0000000000ffffffff0815cf020f013ed6cf91d29f4202e8a58726b1ac6c79da47c23d1bee0a6925f80000000000ffffffff0100f2052a010000001976a914a30741f8145e5acadf23f751864167f32e0963f788ac00000000"
|
||||
# self.assertEqual((Transaction.deserialize(raw_tx).sighash_segwit(SIGHASH_SINGLE,
|
||||
# 1,
|
||||
# "23210255a9626aebf5e29c0e6538428ba0d1dcf6ca98ffdf086aa8ced5e0d0215ea465ac",
|
||||
# 4900000000,
|
||||
# True)),
|
||||
# "fef7bd749cce710c5c052bd796df1af0d935e59cea63736268bcbe2d2134fc47")
|
||||
#
|
||||
# print("P2SH-P2WSH SIGHASH_ALL")
|
||||
# raw_tx = "010000000136641869ca081e70f394c6948e8af409e18b619df2ed74aa106c1ca29787b96e0100000000ffffffff0200e9a435000000001976a914389ffce9cd9ae88dcc0631e88a821ffdbe9bfe2688acc0832f05000000001976a9147480a33f950689af511e6e84c138dbbd3c3ee41588ac00000000"
|
||||
# self.assertEqual((Transaction.deserialize(raw_tx).sighash_segwit(SIGHASH_ALL,
|
||||
# 0,
|
||||
# "cf56210307b8ae49ac90a048e9b53357a2354b3334e9c8bee813ecb98e99a7e07e8c3ba32103b28f0c28bfab54554ae8c658ac5c3e0ce6e79ad336331f78c428dd43eea8449b21034b8113d703413d57761b8b9781957b8c0ac1dfe69f492580ca4195f50376ba4a21033400f6afecb833092a9a21cfdf1ed1376e58c5d1f47de74683123987e967a8f42103a6d48b1131e94ba04d9737d61acdaa1322008af9602b3b14862c07a1789aac162102d8b661b0b3302ee2f162b09e07a55ad5dfbe673a9f01d9f0c19617681024306b56ae",
|
||||
# 987654321,
|
||||
# True)),
|
||||
# "185c0be5263dce5b4bb50a047973c1b6272bfbd0103a89444597dc40b248ee7c")
|
||||
# print("P2SH-P2WSH SIGHASH_NONE")
|
||||
# self.assertEqual((Transaction.deserialize(raw_tx).sighash_segwit(SIGHASH_NONE,
|
||||
# 0,
|
||||
# "cf56210307b8ae49ac90a048e9b53357a2354b3334e9c8bee813ecb98e99a7e07e8c3ba32103b28f0c28bfab54554ae8c658ac5c3e0ce6e79ad336331f78c428dd43eea8449b21034b8113d703413d57761b8b9781957b8c0ac1dfe69f492580ca4195f50376ba4a21033400f6afecb833092a9a21cfdf1ed1376e58c5d1f47de74683123987e967a8f42103a6d48b1131e94ba04d9737d61acdaa1322008af9602b3b14862c07a1789aac162102d8b661b0b3302ee2f162b09e07a55ad5dfbe673a9f01d9f0c19617681024306b56ae",
|
||||
# 987654321,
|
||||
# True)),
|
||||
# "e9733bc60ea13c95c6527066bb975a2ff29a925e80aa14c213f686cbae5d2f36")
|
||||
# print("P2SH-P2WSH SIGHASH_SINGLE")
|
||||
# self.assertEqual((Transaction.deserialize(raw_tx).sighash_segwit(SIGHASH_SINGLE,
|
||||
# 0,
|
||||
# "cf56210307b8ae49ac90a048e9b53357a2354b3334e9c8bee813ecb98e99a7e07e8c3ba32103b28f0c28bfab54554ae8c658ac5c3e0ce6e79ad336331f78c428dd43eea8449b21034b8113d703413d57761b8b9781957b8c0ac1dfe69f492580ca4195f50376ba4a21033400f6afecb833092a9a21cfdf1ed1376e58c5d1f47de74683123987e967a8f42103a6d48b1131e94ba04d9737d61acdaa1322008af9602b3b14862c07a1789aac162102d8b661b0b3302ee2f162b09e07a55ad5dfbe673a9f01d9f0c19617681024306b56ae",
|
||||
# 987654321,
|
||||
# True)),
|
||||
# "1e1f1c303dc025bd664acb72e583e933fae4cff9148bf78c157d1e8f78530aea")
|
||||
#
|
||||
# print("P2SH-P2WSH SIGHASH_ALL + SIGHASH_ANYONECANPAY")
|
||||
# self.assertEqual((Transaction.deserialize(raw_tx).sighash_segwit(SIGHASH_ALL + SIGHASH_ANYONECANPAY,
|
||||
# 0,
|
||||
# "cf56210307b8ae49ac90a048e9b53357a2354b3334e9c8bee813ecb98e99a7e07e8c3ba32103b28f0c28bfab54554ae8c658ac5c3e0ce6e79ad336331f78c428dd43eea8449b21034b8113d703413d57761b8b9781957b8c0ac1dfe69f492580ca4195f50376ba4a21033400f6afecb833092a9a21cfdf1ed1376e58c5d1f47de74683123987e967a8f42103a6d48b1131e94ba04d9737d61acdaa1322008af9602b3b14862c07a1789aac162102d8b661b0b3302ee2f162b09e07a55ad5dfbe673a9f01d9f0c19617681024306b56ae",
|
||||
# 987654321,
|
||||
# True)),
|
||||
# "2a67f03e63a6a422125878b40b82da593be8d4efaafe88ee528af6e5a9955c6e")
|
||||
# print("P2SH-P2WSH SIGHASH_NONE + SIGHASH_ANYONECANPAY")
|
||||
#
|
||||
# self.assertEqual((Transaction.deserialize(raw_tx).sighash_segwit(SIGHASH_NONE + SIGHASH_ANYONECANPAY,
|
||||
# 0,
|
||||
# "cf56210307b8ae49ac90a048e9b53357a2354b3334e9c8bee813ecb98e99a7e07e8c3ba32103b28f0c28bfab54554ae8c658ac5c3e0ce6e79ad336331f78c428dd43eea8449b21034b8113d703413d57761b8b9781957b8c0ac1dfe69f492580ca4195f50376ba4a21033400f6afecb833092a9a21cfdf1ed1376e58c5d1f47de74683123987e967a8f42103a6d48b1131e94ba04d9737d61acdaa1322008af9602b3b14862c07a1789aac162102d8b661b0b3302ee2f162b09e07a55ad5dfbe673a9f01d9f0c19617681024306b56ae",
|
||||
# 987654321,
|
||||
# True)),
|
||||
# "781ba15f3779d5542ce8ecb5c18716733a5ee42a6f51488ec96154934e2c890a")
|
||||
# print("P2SH-P2WSH SIGHASH_SINGLE + SIGHASH_ANYONECANPAY")
|
||||
#
|
||||
# self.assertEqual((Transaction.deserialize(raw_tx).sighash_segwit(SIGHASH_SINGLE + SIGHASH_ANYONECANPAY,
|
||||
# 0,
|
||||
# "cf56210307b8ae49ac90a048e9b53357a2354b3334e9c8bee813ecb98e99a7e07e8c3ba32103b28f0c28bfab54554ae8c658ac5c3e0ce6e79ad336331f78c428dd43eea8449b21034b8113d703413d57761b8b9781957b8c0ac1dfe69f492580ca4195f50376ba4a21033400f6afecb833092a9a21cfdf1ed1376e58c5d1f47de74683123987e967a8f42103a6d48b1131e94ba04d9737d61acdaa1322008af9602b3b14862c07a1789aac162102d8b661b0b3302ee2f162b09e07a55ad5dfbe673a9f01d9f0c19617681024306b56ae",
|
||||
# 987654321,
|
||||
# True)),
|
||||
# "511e8e52ed574121fc1b654970395502128263f62662e076dc6baf05c2e6a99b")
|
||||
print("P2SH-P2WSH SIGHASH_ALL")
|
||||
raw_tx = "010000000136641869ca081e70f394c6948e8af409e18b619df2ed74aa106c1ca29787b96e0100000000ffffffff0200e9a435000000001976a914389ffce9cd9ae88dcc0631e88a821ffdbe9bfe2688acc0832f05000000001976a9147480a33f950689af511e6e84c138dbbd3c3ee41588ac00000000"
|
||||
self.assertEqual(Transaction(raw_tx).sig_hash_segwit(0, 987654321,
|
||||
"cf56210307b8ae49ac90a048e9b53357a2354b3334e9c8bee813ecb98e99a7e07e8c3ba32103b28f0c28bfab54554ae8c658ac5c3e0ce6e79ad336331f78c428dd43eea8449b21034b8113d703413d57761b8b9781957b8c0ac1dfe69f492580ca4195f50376ba4a21033400f6afecb833092a9a21cfdf1ed1376e58c5d1f47de74683123987e967a8f42103a6d48b1131e94ba04d9737d61acdaa1322008af9602b3b14862c07a1789aac162102d8b661b0b3302ee2f162b09e07a55ad5dfbe673a9f01d9f0c19617681024306b56ae",
|
||||
SIGHASH_ALL),
|
||||
"185c0be5263dce5b4bb50a047973c1b6272bfbd0103a89444597dc40b248ee7c")
|
||||
|
||||
print("P2SH-P2WSH SIGHASH_NONE")
|
||||
self.assertEqual(Transaction(raw_tx).sig_hash_segwit(0, 987654321,
|
||||
"cf56210307b8ae49ac90a048e9b53357a2354b3334e9c8bee813ecb98e99a7e07e8c3ba32103b28f0c28bfab54554ae8c658ac5c3e0ce6e79ad336331f78c428dd43eea8449b21034b8113d703413d57761b8b9781957b8c0ac1dfe69f492580ca4195f50376ba4a21033400f6afecb833092a9a21cfdf1ed1376e58c5d1f47de74683123987e967a8f42103a6d48b1131e94ba04d9737d61acdaa1322008af9602b3b14862c07a1789aac162102d8b661b0b3302ee2f162b09e07a55ad5dfbe673a9f01d9f0c19617681024306b56ae",
|
||||
SIGHASH_NONE),
|
||||
"e9733bc60ea13c95c6527066bb975a2ff29a925e80aa14c213f686cbae5d2f36")
|
||||
|
||||
print("P2SH-P2WSH SIGHASH_SINGLE")
|
||||
self.assertEqual(Transaction(raw_tx).sig_hash_segwit(0, 987654321,
|
||||
"cf56210307b8ae49ac90a048e9b53357a2354b3334e9c8bee813ecb98e99a7e07e8c3ba32103b28f0c28bfab54554ae8c658ac5c3e0ce6e79ad336331f78c428dd43eea8449b21034b8113d703413d57761b8b9781957b8c0ac1dfe69f492580ca4195f50376ba4a21033400f6afecb833092a9a21cfdf1ed1376e58c5d1f47de74683123987e967a8f42103a6d48b1131e94ba04d9737d61acdaa1322008af9602b3b14862c07a1789aac162102d8b661b0b3302ee2f162b09e07a55ad5dfbe673a9f01d9f0c19617681024306b56ae",
|
||||
SIGHASH_SINGLE),
|
||||
"1e1f1c303dc025bd664acb72e583e933fae4cff9148bf78c157d1e8f78530aea")
|
||||
|
||||
print("P2SH-P2WSH SIGHASH_ALL + SIGHASH_ANYONECANPAY")
|
||||
self.assertEqual(Transaction(raw_tx).sig_hash_segwit(0, 987654321,
|
||||
"cf56210307b8ae49ac90a048e9b53357a2354b3334e9c8bee813ecb98e99a7e07e8c3ba32103b28f0c28bfab54554ae8c658ac5c3e0ce6e79ad336331f78c428dd43eea8449b21034b8113d703413d57761b8b9781957b8c0ac1dfe69f492580ca4195f50376ba4a21033400f6afecb833092a9a21cfdf1ed1376e58c5d1f47de74683123987e967a8f42103a6d48b1131e94ba04d9737d61acdaa1322008af9602b3b14862c07a1789aac162102d8b661b0b3302ee2f162b09e07a55ad5dfbe673a9f01d9f0c19617681024306b56ae",
|
||||
SIGHASH_ALL + SIGHASH_ANYONECANPAY),
|
||||
"2a67f03e63a6a422125878b40b82da593be8d4efaafe88ee528af6e5a9955c6e")
|
||||
|
||||
print("P2SH-P2WSH SIGHASH_NONE + SIGHASH_ANYONECANPAY")
|
||||
|
||||
self.assertEqual(Transaction(raw_tx).sig_hash_segwit(0, 987654321,
|
||||
"cf56210307b8ae49ac90a048e9b53357a2354b3334e9c8bee813ecb98e99a7e07e8c3ba32103b28f0c28bfab54554ae8c658ac5c3e0ce6e79ad336331f78c428dd43eea8449b21034b8113d703413d57761b8b9781957b8c0ac1dfe69f492580ca4195f50376ba4a21033400f6afecb833092a9a21cfdf1ed1376e58c5d1f47de74683123987e967a8f42103a6d48b1131e94ba04d9737d61acdaa1322008af9602b3b14862c07a1789aac162102d8b661b0b3302ee2f162b09e07a55ad5dfbe673a9f01d9f0c19617681024306b56ae",
|
||||
SIGHASH_NONE + SIGHASH_ANYONECANPAY),
|
||||
"781ba15f3779d5542ce8ecb5c18716733a5ee42a6f51488ec96154934e2c890a")
|
||||
|
||||
print("P2SH-P2WSH SIGHASH_SINGLE + SIGHASH_ANYONECANPAY")
|
||||
self.assertEqual(Transaction(raw_tx).sig_hash_segwit(0, 987654321,
|
||||
"cf56210307b8ae49ac90a048e9b53357a2354b3334e9c8bee813ecb98e99a7e07e8c3ba32103b28f0c28bfab54554ae8c658ac5c3e0ce6e79ad336331f78c428dd43eea8449b21034b8113d703413d57761b8b9781957b8c0ac1dfe69f492580ca4195f50376ba4a21033400f6afecb833092a9a21cfdf1ed1376e58c5d1f47de74683123987e967a8f42103a6d48b1131e94ba04d9737d61acdaa1322008af9602b3b14862c07a1789aac162102d8b661b0b3302ee2f162b09e07a55ad5dfbe673a9f01d9f0c19617681024306b56ae",
|
||||
SIGHASH_SINGLE + SIGHASH_ANYONECANPAY),
|
||||
"511e8e52ed574121fc1b654970395502128263f62662e076dc6baf05c2e6a99b")
|
||||
|
||||
|
||||
|
||||
File diff suppressed because one or more lines are too long
@ -16,7 +16,7 @@ from pybtc import address_to_hash as address2hash160
|
||||
def decode_block_tx(block):
|
||||
stream = get_stream(block)
|
||||
stream.seek(80)
|
||||
return {i: Transaction(stream) for i in range(var_int_to_int(read_var_int(stream)))}
|
||||
return {i: Transaction(stream, tx_format="raw") for i in range(var_int_to_int(read_var_int(stream)))}
|
||||
|
||||
|
||||
class TransactionDeserializeTests(unittest.TestCase):
|
||||
@ -137,7 +137,7 @@ class TransactionDeserializeTests(unittest.TestCase):
|
||||
"c0b7cdf67d16b00f6a20dda7159a49f20aa493a7889b2851b2fea30147522103b09ac1fa65a55fa4" \
|
||||
"feadea57c4cf417d7490065d8b844ada60c242a441e0e3a42103c0625169b46dbbde3492db7c62f1" \
|
||||
"be8f582131467620cef17335306bad7ef88a52aebe810700"
|
||||
print("Deserialize Segwit transaction")
|
||||
print("Deserialize Segwit transaction 2")
|
||||
ns = Transaction(non_segwit_view)
|
||||
s = Transaction(segwit_view)
|
||||
self.assertEqual(s.serialize(segwit=False,hex = True), non_segwit_view)
|
||||
@ -188,11 +188,107 @@ class TransactionDeserializeTests(unittest.TestCase):
|
||||
"20202020202020202020202069202b3d20310a200a2020202020202020206966206f70636f6465203c3d206f7" \
|
||||
"0636f6465732e4f505f5055534844415441343a0a202020202020202020202020206e53697a65203d206f7063" \
|
||||
"6f64650a2d2d200a312e372e392e340a0a6800000000"
|
||||
Transaction(tx)
|
||||
t= Transaction(tx)
|
||||
tx = "0100000001c86c4ddc01f59b748e6a55a6d09c5bce7574fbdec721ca468768b5d6d9e3fb00000000006b48304" \
|
||||
"5022076b5504ad7aff614e32159ac055362a1197c9a5e50de48cf4f05c7547b39c0b5022100ea67efb2585aae" \
|
||||
"40a53363f48e3e38dfc7387b238f8716fa53a5f0ed51b7c314012102452928340bc618777d217a52f30d8e144" \
|
||||
"0d98f561c523a31834a1614106f3c15ffffffff025cf5352f0d0000001976a9141855d5890b8aec536ffc3e59" \
|
||||
"cb586e98b34b5b9288ac0bd32204000000001976a9146f3f6845da01e856a426c31dfeef188c06bf574d88ac0" \
|
||||
"0000000"
|
||||
Transaction(tx)
|
||||
# Transaction(tx)
|
||||
|
||||
tx = "02000000000117096abdf1191fc4e1aa92e66b0dcc04241cd3949d7cb8f6e3f8b7d2867f9cf80900000000171" \
|
||||
"600146ec7cb98e540f2d0b39bed94511d44a24be7f2f0feffffff146e022c0a8b94bb0b38ae93a3cda7265db7" \
|
||||
"3d4f658d10634acb4816c4131fcb01000000171600141d48006f03cdc922da829c479feecf3d6bc7d4d8fefff" \
|
||||
"fff290d1b0ff9d2eb2c3e09c23f05eb1edce4493d0722b9c6d677692f749ab1b6a50000000017160014acb529" \
|
||||
"ba2f57150b6c52781bbd82d224fcda9a33feffffff3b1ad0e2198759c7157c837af79351161630e7b389f43bc" \
|
||||
"2db501781a1562a850000000017160014116ba1a4ffec3012cd009de84db9a10a88169ecdfeffffff3b7d62e6" \
|
||||
"750593892af6f2cd789db8db3b8d5ec40d3a604aa50ef17010a05e7200000000171600140a2ecd45ea98ff976" \
|
||||
"641f11cfd65b489c2931e2efeffffff52f17014e779d564173ecb38e5911e5b43f2d593529729a62cb4768f3d" \
|
||||
"4acc39eb0000001716001410c090b35e7d62334c0aab64fd9459e58d2aace1feffffff52f17014e779d564173" \
|
||||
"ecb38e5911e5b43f2d593529729a62cb4768f3d4acc396501000017160014eba3843f4d612cd5f73b44d2d2b2" \
|
||||
"0a14bc402afffeffffff52f17014e779d564173ecb38e5911e5b43f2d593529729a62cb4768f3d4acc397c010" \
|
||||
"00017160014436e3e8e328425e04929c7624534405a1a8ec87efeffffff7987375451a860c131f5661ecfd6ac" \
|
||||
"f2206b9eeba90f6d7e2e2bf828fc74000701000000171600149bc9b2c23b4d3aaee5c206de8eb88f64e37d8f8" \
|
||||
"cfeffffff867a8c3c48e7995d70b7d39c25cd7b21749b2756f0aa5b0140a32e545baa1f100100000017160014" \
|
||||
"8698b478bcd14c7f12d5f43f9f566ba6cfe44172feffffff9790a339ebd0a0caa802cb9168635d738e075032c" \
|
||||
"1619f556b7634b2985ee4ce0000000017160014770cc4796bab516455a6e1f3b75343888050f1b2feffffff9c" \
|
||||
"bc483b0e911190880e48cb0fad167a33c8e73ecdded9f63e5001a54e0d9c460300000017160014d02d35e9276" \
|
||||
"4caf590cb0b309f40bf6ee0673de5feffffffa219e1f09e7c168ed469a9948d88248d7d2561514f22d6e47661" \
|
||||
"9fce90876c4b01000000171600144c9d756273fa839887413d8e57429a09263f7757feffffffbb99d3c6a586e" \
|
||||
"40ed80e782a0584febb15daf1622e2717daaed4c71e224a5745000000001716001429a23327092f771825a0d4" \
|
||||
"3c7c2187865df4d01ffeffffffbf4932f21c4bee27918fa0e400e4fa5e53dbc7893b334980ea5dd9044c6baf6" \
|
||||
"d01000000171600144b7063ed9a8f3d7fd14f18a399269256c5e6cbc1feffffffcba7ccd697116c1a259f1292" \
|
||||
"0334ec62c54e42fab865ebc1cbcbbabe42d20ab2010000001716001432d881b6893d2360a6cb65732829cfe45" \
|
||||
"292d642feffffffddcd78811d2b73feca247c787105c362a23f32da01472fd504579cb0e64c70a70100000017" \
|
||||
"160014e4e03eba879ef2f13abb38647767b4e8cbc94356feffffffe9a166d7e4b8372886160893f376084b9f0" \
|
||||
"c5b289d06774315cf7a15a0b95cc80000000017160014f3f1e21efa1acc3c6ca1786fe6a38462a38b5855feff" \
|
||||
"fffff0707a5ad2c3e052badcc40236b12fb866d203b73b6b7df1e8d5a5a60eece8f9030000001716001416b40" \
|
||||
"0b1168b387284c2925c3789700027a83932fefffffff0ff68934c0cd40d10ba612346f26c72fa4a67ea0b0b84" \
|
||||
"578729dca540a285e731000000171600140afb8e8d46deabffaeffe3402fd57537a445fa57fefffffff0ff689" \
|
||||
"34c0cd40d10ba612346f26c72fa4a67ea0b0b84578729dca540a285e70302000017160014d29b4da896e24b81" \
|
||||
"980f3dc5319302a3dec6a6f4fefffffffb6e1c56c1243d038bfdcab451a701e8766baf787aa8d74e6aeb87713" \
|
||||
"f67c0120100000017160014725752b632549054dbf0bedaaa091e12dabcc8f0feffffffffaf40d3cfbeefdecf" \
|
||||
"14db8bd5ec7ae6f8d1e69c222f951600d6b514ebf3e9420100000017160014330624c35e0e371c15acdcc6325" \
|
||||
"7dae5b1930088feffffff021cb81c00000000001976a914ce5cd304c7ba6f89e96aa6c4e92b7455b5359e4e88" \
|
||||
"ac51420f00000000001976a9142c997b4e8951e7b3e863bbb439b1050bf0fcdd1d88ac0247304402201f4c1c9" \
|
||||
"0d25365fa146106edf11416459b02d4d6d5f4537b37fe5cc523f3a63002206748a144f4012e838705edb505a5" \
|
||||
"ef556ecc91df615cab12786369c3d8ab6d3c012102b4323697c2fa1ff13e696f6bc5fe5f67c989cb91b8755e1" \
|
||||
"1a7c37213c94e957902483045022100dfe620ca3167e75fac002448069fbface366ee7c57f7f86e9a77113127" \
|
||||
"7c91b20220108a436df211fc21909c450e270c765c2c20814643f3804173be88d6863d51260121032522bbee5" \
|
||||
"1b2ccad81c4255e2d4eb516ea7943aa8656eaa8ad7b7cd6abcc97370247304402206a4a1836d79004b3430bd6" \
|
||||
"1d73e938f0bcc1a56c655b52444d4e047464db0592022067bd8d4965d55e261d1e4e38462f20a8a2610f5ac78" \
|
||||
"d551fc95a522b7144589a0121026baf81f20d6a50e6262f433875651e7b192c304105c6911276541e45a67f96" \
|
||||
"9402473044022057741ff3470fa4b70b204d621ed737097d3f6cec4a2e43d39c5d6c650117b28d02205b6c3b2" \
|
||||
"c92ec047c1c4d3fd7b785474345a038f9842d6a30048737cd471117ea012102fbf1d98a34bd3f1283c9f258f8" \
|
||||
"7a6baff2b65710d4f3b77d5589dacc155b6f8d02483045022100bc07cccf6ac51626147ccb0c1ffd91d0bbedb" \
|
||||
"6e5df3c798fd8035112bc92070c022034eb7a9658d9ed7b56256155151f8280e871e00e3aefa9b6ea8ae35a27" \
|
||||
"0c3b8d0121032004240c860bd92ebcf6c834cdc1d9d28fefe757245d61fe86a02c04994697cd0248304502210" \
|
||||
"0c62ecdebd1728f18a746cf1575cdf29cdf6b03dd86d9b7ead96c9a7341c8ad1702205cd92ace00bf53254e1d" \
|
||||
"bed3d10f675540dc3a1b1b3dc353ffe3901508bbbb0101210242ff69abeaea31b6fc6e1ea1625179003b9d0d8" \
|
||||
"2c729ec78df8ef5fb378e6bc002473044022026217dec2bbc97afbfeba833cf9fa323206c26037a5dce5221cb" \
|
||||
"323af142cb1e02206e2ef15be6da7b99e50339a8924de232693494154f792018b6cca4f9f307192e012103ea5" \
|
||||
"0f77697dd3467f4876382a447372cd03e5ec567385152e4e91c573c54cf49024730440220256d9ab9ce4c8efb" \
|
||||
"7628f7f56e0a59b81c0f973d6c9b89b3ac5c018c54d61a58022064f7c7084c3fb30f118187956e624ce4d4eef" \
|
||||
"7acee81a52be1ccd5683e661f6c0121024d812e6254577bdf98d2b52b36d548dfcf03c994b159309839d30c38" \
|
||||
"73ec15d5024830450221009618e1427a53dc66e26178416afe6465feb6882d6c4b4a0a3f6b6ce70965a40f022" \
|
||||
"03d1b0bdee921bb733674d5b373244c4676982eec20c0f7069917b0e2c1d20f6c012103f8c70a3b0a1bdd9ab4" \
|
||||
"0770a1532a2d0f2eb046e4eb56434ba1a9b214e19ed47a0247304402205e8d08cdae61f6c8ba2d17a18b6575e" \
|
||||
"4d5e2511f491621d4fa1bebbe89b7794e02200c565ab9379b57b731821e0c9172c65e3339e5a83dbc24d3ecff" \
|
||||
"79dc8879edc0012102d4c245cb72bc520be55959df9faea82c470a51942907ad83339ae70c5e2a8efa0247304" \
|
||||
"402207bc8e60dbf3ed02d9b08df09572716cf486e1f49927467131b05487f376eede4022040fd95d42a11456a" \
|
||||
"2a49eda376edcb0b71baa21cdd562236162806ad9e5d4a4701210287cd827827140bbd304b5feaa9a8c9e36d4" \
|
||||
"f5a1da292e16e207039b1fadc488402473044022052e177e94353f03a2bb8aed3a3cbc14cb1095b36d972b356" \
|
||||
"dd2e9ef12a38cb95022055624ef65618144c4ffc9125bedfd625594f2926d5c14f5805cf26d278e802f101210" \
|
||||
"25493a9da73c46838c6bad1414d1497a8216fbc8e0f46d981167d004b2cc4a6b802483045022100c09f346d36" \
|
||||
"af2ab4915e96f1088f431cea41854e6a605dfb86b0f87764269203022000fb0354e7d3d6b42ca8b2c59736a0c" \
|
||||
"a9c3f2cc5263c056abc84c7be62bd6184012103f86036ceb2bd6a57b9f39f5aa986e7fc6a0dd1f379e9549396" \
|
||||
"2aaf88b228b0b70247304402205be7111758fa4670778571af558ad85c802b9292503df389cd47cd063936185" \
|
||||
"f0220481965e1ba34cbf6e7b548af01a34c6185921a6120f07cfe437f33071c83c625012102414eb9f4393b9a" \
|
||||
"5f30f9d4ab2612a9782b062ec0a6b13dbbc5037b185ad8f72002483045022100db73b46fd12fbb17663750417" \
|
||||
"8f0aa784749b9cd20e7cbfc23586ad7e06fe7fc022038512998ce23ed4b1aff7d07e1654344bc11720976ac0a" \
|
||||
"3aeece7018999a35ee01210292e1e3b2079ce6ef363f633cffa07f9a0d316e67c0c8d50eea2da026d3cfc6070" \
|
||||
"2473044022000cd297f5b9aaa94e40210bfc47d10d9156be8ba3db665741d7c77c29118f355022033aa9c328e" \
|
||||
"90a12bf701167659db4cddbb091af7bb8ae4dc83fd0833667123a4012103c45c84d80cd594a9d014935248622" \
|
||||
"a33b8ee1c597334586273aab9a9ef1784d502483045022100a152152ee871ac06bd0f0e385b0e281188504ae9" \
|
||||
"40f54c86760ca0bc1bde6e8902207578d03e42670d5172fb589974853402e00136d2e07c9285171ad79435a94" \
|
||||
"17e012102cbd3cfc675393c20d9acc51086d8faff48621a216531446ac7c388dcd88decc40247304402200e64" \
|
||||
"ece9d74242f638db43fa600af34df9289ce93d1756bc5c3be77973b28d7a02205608d5a304efd41c8024a60bc" \
|
||||
"0f1ed44413941fa80239d01a1e95f15499c2bca0121028447cfc8b84edc759eace6dfbbd6138ebeb470da7819" \
|
||||
"5a96caf192750487c0c30247304402207244b3a176cf0a7203fbcab9e0f3be5eea21b9ce701a07140b7d591ec" \
|
||||
"19234f302205e5c6cc861576a871d55609a52f0895710812cb6a2aaa1279a5e01f2d1874779012102bd77789c" \
|
||||
"af99127c39f22ff5432be6c285c9c5bbbebc86cb35d4f1d5f6fa652302483045022100dbad3f4038a81323d97" \
|
||||
"f6f6347e31739b7f8d6331ca1fce17ee46f1c9d0b97da022005678968ff1946e1e368a04e87e8954ff5606c42" \
|
||||
"57c9a114940d32f39f6fbd1f01210322f53e7d73d997c1875db26464875ad797c6cffe80ba548ff524c360495" \
|
||||
"78fae02473044022075aec794771d9d133e9de71bf89e24227c08bf58dec8cdfff0cd781fa3bf9bed02200d26" \
|
||||
"e2b9535b9ea8e6aed0ba41aff6dd9f0181418679305c67b5bb888e526df40121020eb887a39d202928ba2abf1" \
|
||||
"d16df73aaa17daf9922fd3a3bf6554e730f9c88eb02483045022100dd2d2187fd37e5bf333c1bf0b4dae9f42d" \
|
||||
"ef626458bc9283fe6bdf991e9abcab02207e1954eaadbeed240e577aa0f7d329d53b5934edd1da0320964aace" \
|
||||
"da09af35f012102ff5bdd1e69f2363d95d80eeeced34bc0de8fc5df9f819cce6ed1d6805beff8ec0247304402" \
|
||||
"205ec43c7d919216ad16ed85d75f9d98d1695dddc5810ad0c5635d96b47588eeda02201d71c85602169a109e9" \
|
||||
"0e558125033075237d9177553bac1d1d24d8610cb9d0a012103f50abc70096bb6f6f8742e73c5bf0f1bd4d475" \
|
||||
"9c1dd2e4486b6fec52b3c8eda6daf10700"
|
||||
|
||||
tx = Transaction(tx)
|
||||
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user