<span id="119">119</span>
<span id="120">120</span>
<span id="121">121</span>
+<span id="122">122</span>
+<span id="123">123</span>
+<span id="124">124</span>
+<span id="125">125</span>
+<span id="126">126</span>
+<span id="127">127</span>
+<span id="128">128</span>
+<span id="129">129</span>
+<span id="130">130</span>
+<span id="131">131</span>
+<span id="132">132</span>
+<span id="133">133</span>
+<span id="134">134</span>
+<span id="135">135</span>
+<span id="136">136</span>
+<span id="137">137</span>
+<span id="138">138</span>
+<span id="139">139</span>
+<span id="140">140</span>
+<span id="141">141</span>
+<span id="142">142</span>
+<span id="143">143</span>
+<span id="144">144</span>
+<span id="145">145</span>
+<span id="146">146</span>
+<span id="147">147</span>
+<span id="148">148</span>
+<span id="149">149</span>
+<span id="150">150</span>
+<span id="151">151</span>
+<span id="152">152</span>
+<span id="153">153</span>
+<span id="154">154</span>
+<span id="155">155</span>
+<span id="156">156</span>
+<span id="157">157</span>
+<span id="158">158</span>
+<span id="159">159</span>
+<span id="160">160</span>
+<span id="161">161</span>
+<span id="162">162</span>
+<span id="163">163</span>
+<span id="164">164</span>
+<span id="165">165</span>
+<span id="166">166</span>
+<span id="167">167</span>
+<span id="168">168</span>
+<span id="169">169</span>
+<span id="170">170</span>
+<span id="171">171</span>
+<span id="172">172</span>
+<span id="173">173</span>
+<span id="174">174</span>
+<span id="175">175</span>
+<span id="176">176</span>
+<span id="177">177</span>
+<span id="178">178</span>
+<span id="179">179</span>
+<span id="180">180</span>
+<span id="181">181</span>
+<span id="182">182</span>
+<span id="183">183</span>
+<span id="184">184</span>
+<span id="185">185</span>
+<span id="186">186</span>
+<span id="187">187</span>
+<span id="188">188</span>
+<span id="189">189</span>
+<span id="190">190</span>
+<span id="191">191</span>
+<span id="192">192</span>
+<span id="193">193</span>
+<span id="194">194</span>
+<span id="195">195</span>
+<span id="196">196</span>
+<span id="197">197</span>
+<span id="198">198</span>
+<span id="199">199</span>
+<span id="200">200</span>
+<span id="201">201</span>
+<span id="202">202</span>
+<span id="203">203</span>
+<span id="204">204</span>
+<span id="205">205</span>
+<span id="206">206</span>
+<span id="207">207</span>
+<span id="208">208</span>
+<span id="209">209</span>
+<span id="210">210</span>
+<span id="211">211</span>
+<span id="212">212</span>
+<span id="213">213</span>
+<span id="214">214</span>
+<span id="215">215</span>
+<span id="216">216</span>
+<span id="217">217</span>
+<span id="218">218</span>
+<span id="219">219</span>
+<span id="220">220</span>
+<span id="221">221</span>
+<span id="222">222</span>
+<span id="223">223</span>
+<span id="224">224</span>
+<span id="225">225</span>
+<span id="226">226</span>
+<span id="227">227</span>
+<span id="228">228</span>
+<span id="229">229</span>
+<span id="230">230</span>
+<span id="231">231</span>
+<span id="232">232</span>
+<span id="233">233</span>
</pre><pre class="rust"><code><span class="comment">// Bitcoin Dev Kit</span>
<span class="comment">// Written in 2020 by Alekos Filini <alekos.filini@gmail.com></span>
<span class="comment">//</span>
<span class="comment">// You may not use this file except in accordance with one or both of these</span>
<span class="comment">// licenses.</span>
+<span class="kw">use</span> <span class="ident"><span class="kw">crate</span>::FeeRate</span>;
<span class="kw">use</span> <span class="ident">bitcoin::util::psbt::PartiallySignedTransaction</span> <span class="kw">as</span> <span class="ident">Psbt</span>;
<span class="kw">use</span> <span class="ident">bitcoin::TxOut</span>;
<span class="kw">pub</span> <span class="kw">trait</span> <span class="ident">PsbtUtils</span> {
<span class="kw">fn</span> <span class="ident">get_utxo_for</span>(<span class="kw-2">&</span><span class="self">self</span>, <span class="ident">input_index</span>: <span class="ident">usize</span>) -> <span class="prelude-ty">Option</span><span class="op"><</span><span class="ident">TxOut</span><span class="op">></span>;
+
+ <span class="doccomment">/// The total transaction fee amount, sum of input amounts minus sum of output amounts, in Sats.</span>
+ <span class="doccomment">/// If the PSBT is missing a TxOut for an input returns None.</span>
+ <span class="kw">fn</span> <span class="ident">fee_amount</span>(<span class="kw-2">&</span><span class="self">self</span>) -> <span class="prelude-ty">Option</span><span class="op"><</span><span class="ident">u64</span><span class="op">></span>;
+
+ <span class="doccomment">/// The transaction's fee rate. This value will only be accurate if calculated AFTER the</span>
+ <span class="doccomment">/// `PartiallySignedTransaction` is finalized and all witness/signature data is added to the</span>
+ <span class="doccomment">/// transaction.</span>
+ <span class="doccomment">/// If the PSBT is missing a TxOut for an input returns None.</span>
+ <span class="kw">fn</span> <span class="ident">fee_rate</span>(<span class="kw-2">&</span><span class="self">self</span>) -> <span class="prelude-ty">Option</span><span class="op"><</span><span class="ident">FeeRate</span><span class="op">></span>;
}
<span class="kw">impl</span> <span class="ident">PsbtUtils</span> <span class="kw">for</span> <span class="ident">Psbt</span> {
<span class="prelude-val">None</span>
}
}
+
+ <span class="kw">fn</span> <span class="ident">fee_amount</span>(<span class="kw-2">&</span><span class="self">self</span>) -> <span class="prelude-ty">Option</span><span class="op"><</span><span class="ident">u64</span><span class="op">></span> {
+ <span class="kw">let</span> <span class="ident">tx</span> <span class="op">=</span> <span class="kw-2">&</span><span class="self">self</span>.<span class="ident">unsigned_tx</span>;
+ <span class="kw">let</span> <span class="ident">utxos</span>: <span class="prelude-ty">Option</span><span class="op"><</span><span class="ident">Vec</span><span class="op"><</span><span class="ident">TxOut</span><span class="op">></span><span class="op">></span> <span class="op">=</span> (<span class="number">0</span>..<span class="ident">tx</span>.<span class="ident">input</span>.<span class="ident">len</span>()).<span class="ident">map</span>(<span class="op">|</span><span class="ident">i</span><span class="op">|</span> <span class="self">self</span>.<span class="ident">get_utxo_for</span>(<span class="ident">i</span>)).<span class="ident">collect</span>();
+
+ <span class="ident">utxos</span>.<span class="ident">map</span>(<span class="op">|</span><span class="ident">inputs</span><span class="op">|</span> {
+ <span class="kw">let</span> <span class="ident">input_amount</span>: <span class="ident">u64</span> <span class="op">=</span> <span class="ident">inputs</span>.<span class="ident">iter</span>().<span class="ident">map</span>(<span class="op">|</span><span class="ident">i</span><span class="op">|</span> <span class="ident">i</span>.<span class="ident">value</span>).<span class="ident">sum</span>();
+ <span class="kw">let</span> <span class="ident">output_amount</span>: <span class="ident">u64</span> <span class="op">=</span> <span class="self">self</span>.<span class="ident">unsigned_tx</span>.<span class="ident">output</span>.<span class="ident">iter</span>().<span class="ident">map</span>(<span class="op">|</span><span class="ident">o</span><span class="op">|</span> <span class="ident">o</span>.<span class="ident">value</span>).<span class="ident">sum</span>();
+ <span class="ident">input_amount</span>
+ .<span class="ident">checked_sub</span>(<span class="ident">output_amount</span>)
+ .<span class="ident">expect</span>(<span class="string">"input amount must be greater than output amount"</span>)
+ })
+ }
+
+ <span class="kw">fn</span> <span class="ident">fee_rate</span>(<span class="kw-2">&</span><span class="self">self</span>) -> <span class="prelude-ty">Option</span><span class="op"><</span><span class="ident">FeeRate</span><span class="op">></span> {
+ <span class="kw">let</span> <span class="ident">fee_amount</span> <span class="op">=</span> <span class="self">self</span>.<span class="ident">fee_amount</span>();
+ <span class="ident">fee_amount</span>.<span class="ident">map</span>(<span class="op">|</span><span class="ident">fee</span><span class="op">|</span> {
+ <span class="kw">let</span> <span class="ident">weight</span> <span class="op">=</span> <span class="self">self</span>.<span class="ident">clone</span>().<span class="ident">extract_tx</span>().<span class="ident">weight</span>();
+ <span class="ident">FeeRate::from_wu</span>(<span class="ident">fee</span>, <span class="ident">weight</span>)
+ })
+ }
}
<span class="attribute">#[<span class="ident">cfg</span>(<span class="ident">test</span>)]</span>
<span class="kw">use</span> <span class="ident"><span class="kw">crate</span>::bitcoin::TxIn</span>;
<span class="kw">use</span> <span class="ident"><span class="kw">crate</span>::psbt::Psbt</span>;
<span class="kw">use</span> <span class="ident"><span class="kw">crate</span>::wallet::AddressIndex</span>;
+ <span class="kw">use</span> <span class="ident"><span class="kw">crate</span>::wallet::AddressIndex::New</span>;
<span class="kw">use</span> <span class="ident"><span class="kw">crate</span>::wallet</span>::{<span class="ident">get_funded_wallet</span>, <span class="ident">test::get_test_wpkh</span>};
- <span class="kw">use</span> <span class="ident"><span class="kw">crate</span>::SignOptions</span>;
+ <span class="kw">use</span> <span class="kw">crate</span>::{<span class="ident">psbt</span>, <span class="ident">FeeRate</span>, <span class="ident">SignOptions</span>};
<span class="kw">use</span> <span class="ident">std::str::FromStr</span>;
<span class="comment">// from bip 174</span>
<span class="kw">let</span> <span class="kw">_</span> <span class="op">=</span> <span class="ident">wallet</span>.<span class="ident">sign</span>(<span class="kw-2">&mut</span> <span class="ident">psbt</span>, <span class="ident">SignOptions::default</span>()).<span class="ident">unwrap</span>();
}
+
+ <span class="attribute">#[<span class="ident">test</span>]</span>
+ <span class="kw">fn</span> <span class="ident">test_psbt_fee_rate_with_witness_utxo</span>() {
+ <span class="kw">use</span> <span class="ident">psbt::PsbtUtils</span>;
+
+ <span class="kw">let</span> <span class="ident">expected_fee_rate</span> <span class="op">=</span> <span class="number">1.2345</span>;
+
+ <span class="kw">let</span> (<span class="ident">wallet</span>, <span class="kw">_</span>, <span class="kw">_</span>) <span class="op">=</span> <span class="ident">get_funded_wallet</span>(<span class="string">"wpkh(tprv8ZgxMBicQKsPd3EupYiPRhaMooHKUHJxNsTfYuScep13go8QFfHdtkG9nRkFGb7busX4isf6X9dURGCoKgitaApQ6MupRhZMcELAxTBRJgS/*)"</span>);
+ <span class="kw">let</span> <span class="ident">addr</span> <span class="op">=</span> <span class="ident">wallet</span>.<span class="ident">get_address</span>(<span class="ident">New</span>).<span class="ident">unwrap</span>();
+ <span class="kw">let</span> <span class="kw-2">mut</span> <span class="ident">builder</span> <span class="op">=</span> <span class="ident">wallet</span>.<span class="ident">build_tx</span>();
+ <span class="ident">builder</span>.<span class="ident">drain_to</span>(<span class="ident">addr</span>.<span class="ident">script_pubkey</span>()).<span class="ident">drain_wallet</span>();
+ <span class="ident">builder</span>.<span class="ident">fee_rate</span>(<span class="ident">FeeRate::from_sat_per_vb</span>(<span class="ident">expected_fee_rate</span>));
+ <span class="kw">let</span> (<span class="kw-2">mut</span> <span class="ident">psbt</span>, <span class="kw">_</span>) <span class="op">=</span> <span class="ident">builder</span>.<span class="ident">finish</span>().<span class="ident">unwrap</span>();
+ <span class="kw">let</span> <span class="ident">fee_amount</span> <span class="op">=</span> <span class="ident">psbt</span>.<span class="ident">fee_amount</span>();
+ <span class="macro">assert!</span>(<span class="ident">fee_amount</span>.<span class="ident">is_some</span>());
+
+ <span class="kw">let</span> <span class="ident">unfinalized_fee_rate</span> <span class="op">=</span> <span class="ident">psbt</span>.<span class="ident">fee_rate</span>().<span class="ident">unwrap</span>();
+
+ <span class="kw">let</span> <span class="ident">finalized</span> <span class="op">=</span> <span class="ident">wallet</span>.<span class="ident">sign</span>(<span class="kw-2">&mut</span> <span class="ident">psbt</span>, <span class="ident">Default::default</span>()).<span class="ident">unwrap</span>();
+ <span class="macro">assert!</span>(<span class="ident">finalized</span>);
+
+ <span class="kw">let</span> <span class="ident">finalized_fee_rate</span> <span class="op">=</span> <span class="ident">psbt</span>.<span class="ident">fee_rate</span>().<span class="ident">unwrap</span>();
+ <span class="macro">assert!</span>(<span class="ident">finalized_fee_rate</span>.<span class="ident">as_sat_per_vb</span>() <span class="op">></span><span class="op">=</span> <span class="ident">expected_fee_rate</span>);
+ <span class="macro">assert!</span>(<span class="ident">finalized_fee_rate</span>.<span class="ident">as_sat_per_vb</span>() <span class="op"><</span> <span class="ident">unfinalized_fee_rate</span>.<span class="ident">as_sat_per_vb</span>());
+ }
+
+ <span class="attribute">#[<span class="ident">test</span>]</span>
+ <span class="kw">fn</span> <span class="ident">test_psbt_fee_rate_with_nonwitness_utxo</span>() {
+ <span class="kw">use</span> <span class="ident">psbt::PsbtUtils</span>;
+
+ <span class="kw">let</span> <span class="ident">expected_fee_rate</span> <span class="op">=</span> <span class="number">1.2345</span>;
+
+ <span class="kw">let</span> (<span class="ident">wallet</span>, <span class="kw">_</span>, <span class="kw">_</span>) <span class="op">=</span> <span class="ident">get_funded_wallet</span>(<span class="string">"pkh(tprv8ZgxMBicQKsPd3EupYiPRhaMooHKUHJxNsTfYuScep13go8QFfHdtkG9nRkFGb7busX4isf6X9dURGCoKgitaApQ6MupRhZMcELAxTBRJgS/*)"</span>);
+ <span class="kw">let</span> <span class="ident">addr</span> <span class="op">=</span> <span class="ident">wallet</span>.<span class="ident">get_address</span>(<span class="ident">New</span>).<span class="ident">unwrap</span>();
+ <span class="kw">let</span> <span class="kw-2">mut</span> <span class="ident">builder</span> <span class="op">=</span> <span class="ident">wallet</span>.<span class="ident">build_tx</span>();
+ <span class="ident">builder</span>.<span class="ident">drain_to</span>(<span class="ident">addr</span>.<span class="ident">script_pubkey</span>()).<span class="ident">drain_wallet</span>();
+ <span class="ident">builder</span>.<span class="ident">fee_rate</span>(<span class="ident">FeeRate::from_sat_per_vb</span>(<span class="ident">expected_fee_rate</span>));
+ <span class="kw">let</span> (<span class="kw-2">mut</span> <span class="ident">psbt</span>, <span class="kw">_</span>) <span class="op">=</span> <span class="ident">builder</span>.<span class="ident">finish</span>().<span class="ident">unwrap</span>();
+ <span class="kw">let</span> <span class="ident">fee_amount</span> <span class="op">=</span> <span class="ident">psbt</span>.<span class="ident">fee_amount</span>();
+ <span class="macro">assert!</span>(<span class="ident">fee_amount</span>.<span class="ident">is_some</span>());
+ <span class="kw">let</span> <span class="ident">unfinalized_fee_rate</span> <span class="op">=</span> <span class="ident">psbt</span>.<span class="ident">fee_rate</span>().<span class="ident">unwrap</span>();
+
+ <span class="kw">let</span> <span class="ident">finalized</span> <span class="op">=</span> <span class="ident">wallet</span>.<span class="ident">sign</span>(<span class="kw-2">&mut</span> <span class="ident">psbt</span>, <span class="ident">Default::default</span>()).<span class="ident">unwrap</span>();
+ <span class="macro">assert!</span>(<span class="ident">finalized</span>);
+
+ <span class="kw">let</span> <span class="ident">finalized_fee_rate</span> <span class="op">=</span> <span class="ident">psbt</span>.<span class="ident">fee_rate</span>().<span class="ident">unwrap</span>();
+ <span class="macro">assert!</span>(<span class="ident">finalized_fee_rate</span>.<span class="ident">as_sat_per_vb</span>() <span class="op">></span><span class="op">=</span> <span class="ident">expected_fee_rate</span>);
+ <span class="macro">assert!</span>(<span class="ident">finalized_fee_rate</span>.<span class="ident">as_sat_per_vb</span>() <span class="op"><</span> <span class="ident">unfinalized_fee_rate</span>.<span class="ident">as_sat_per_vb</span>());
+ }
+
+ <span class="attribute">#[<span class="ident">test</span>]</span>
+ <span class="kw">fn</span> <span class="ident">test_psbt_fee_rate_with_missing_txout</span>() {
+ <span class="kw">use</span> <span class="ident">psbt::PsbtUtils</span>;
+
+ <span class="kw">let</span> <span class="ident">expected_fee_rate</span> <span class="op">=</span> <span class="number">1.2345</span>;
+
+ <span class="kw">let</span> (<span class="ident">wpkh_wallet</span>, <span class="kw">_</span>, <span class="kw">_</span>) <span class="op">=</span> <span class="ident">get_funded_wallet</span>(<span class="string">"wpkh(tprv8ZgxMBicQKsPd3EupYiPRhaMooHKUHJxNsTfYuScep13go8QFfHdtkG9nRkFGb7busX4isf6X9dURGCoKgitaApQ6MupRhZMcELAxTBRJgS/*)"</span>);
+ <span class="kw">let</span> <span class="ident">addr</span> <span class="op">=</span> <span class="ident">wpkh_wallet</span>.<span class="ident">get_address</span>(<span class="ident">New</span>).<span class="ident">unwrap</span>();
+ <span class="kw">let</span> <span class="kw-2">mut</span> <span class="ident">builder</span> <span class="op">=</span> <span class="ident">wpkh_wallet</span>.<span class="ident">build_tx</span>();
+ <span class="ident">builder</span>.<span class="ident">drain_to</span>(<span class="ident">addr</span>.<span class="ident">script_pubkey</span>()).<span class="ident">drain_wallet</span>();
+ <span class="ident">builder</span>.<span class="ident">fee_rate</span>(<span class="ident">FeeRate::from_sat_per_vb</span>(<span class="ident">expected_fee_rate</span>));
+ <span class="kw">let</span> (<span class="kw-2">mut</span> <span class="ident">wpkh_psbt</span>, <span class="kw">_</span>) <span class="op">=</span> <span class="ident">builder</span>.<span class="ident">finish</span>().<span class="ident">unwrap</span>();
+
+ <span class="ident">wpkh_psbt</span>.<span class="ident">inputs</span>[<span class="number">0</span>].<span class="ident">witness_utxo</span> <span class="op">=</span> <span class="prelude-val">None</span>;
+ <span class="ident">wpkh_psbt</span>.<span class="ident">inputs</span>[<span class="number">0</span>].<span class="ident">non_witness_utxo</span> <span class="op">=</span> <span class="prelude-val">None</span>;
+ <span class="macro">assert!</span>(<span class="ident">wpkh_psbt</span>.<span class="ident">fee_amount</span>().<span class="ident">is_none</span>());
+ <span class="macro">assert!</span>(<span class="ident">wpkh_psbt</span>.<span class="ident">fee_rate</span>().<span class="ident">is_none</span>());
+
+ <span class="kw">let</span> (<span class="ident">pkh_wallet</span>, <span class="kw">_</span>, <span class="kw">_</span>) <span class="op">=</span> <span class="ident">get_funded_wallet</span>(<span class="string">"pkh(tprv8ZgxMBicQKsPd3EupYiPRhaMooHKUHJxNsTfYuScep13go8QFfHdtkG9nRkFGb7busX4isf6X9dURGCoKgitaApQ6MupRhZMcELAxTBRJgS/*)"</span>);
+ <span class="kw">let</span> <span class="ident">addr</span> <span class="op">=</span> <span class="ident">pkh_wallet</span>.<span class="ident">get_address</span>(<span class="ident">New</span>).<span class="ident">unwrap</span>();
+ <span class="kw">let</span> <span class="kw-2">mut</span> <span class="ident">builder</span> <span class="op">=</span> <span class="ident">pkh_wallet</span>.<span class="ident">build_tx</span>();
+ <span class="ident">builder</span>.<span class="ident">drain_to</span>(<span class="ident">addr</span>.<span class="ident">script_pubkey</span>()).<span class="ident">drain_wallet</span>();
+ <span class="ident">builder</span>.<span class="ident">fee_rate</span>(<span class="ident">FeeRate::from_sat_per_vb</span>(<span class="ident">expected_fee_rate</span>));
+ <span class="kw">let</span> (<span class="kw-2">mut</span> <span class="ident">pkh_psbt</span>, <span class="kw">_</span>) <span class="op">=</span> <span class="ident">builder</span>.<span class="ident">finish</span>().<span class="ident">unwrap</span>();
+
+ <span class="ident">pkh_psbt</span>.<span class="ident">inputs</span>[<span class="number">0</span>].<span class="ident">non_witness_utxo</span> <span class="op">=</span> <span class="prelude-val">None</span>;
+ <span class="macro">assert!</span>(<span class="ident">pkh_psbt</span>.<span class="ident">fee_amount</span>().<span class="ident">is_none</span>());
+ <span class="macro">assert!</span>(<span class="ident">pkh_psbt</span>.<span class="ident">fee_rate</span>().<span class="ident">is_none</span>());
+ }
}
</code></pre></div>
</section><section id="search" class="content hidden"></section></div></main><div id="rustdoc-vars" data-root-path="../../../" data-current-crate="bdk" data-themes="ayu,dark,light" data-resource-suffix="" data-rustdoc-version="1.60.0-nightly (51126be1b 2022-01-24)" ></div>