Merge pull request #579 from TheBlueMatt/master

Fix Script::dust_value()'s calculation for non-P2*PKH script_pubkeys
This commit is contained in:
Andrew Poelstra 2021-05-06 16:01:36 +00:00 committed by GitHub
commit 4620c640a9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 29 additions and 10 deletions

View File

@ -406,23 +406,23 @@ impl Script {
opcodes::All::from(self.0[0]).classify() == opcodes::Class::IllegalOp) opcodes::All::from(self.0[0]).classify() == opcodes::Class::IllegalOp)
} }
/// The minimum value an output to a witness script must have in order to be
/// broadcastable on today's bitcoin network.
pub const WITNESS_OUTPUT_DUST_THRESHOLD: u64 = 294;
/// The minimum value an output to a non-witness script must have in order to be
/// broadcastable on today's bitcoin network.
pub const LEGACY_OUTPUT_DUST_THRESHOLD: u64 = 546;
/// Gets the minimum value an output with this script should have in order to be /// Gets the minimum value an output with this script should have in order to be
/// broadcastable on today's bitcoin network. /// broadcastable on today's bitcoin network.
pub fn dust_value(&self) -> u64 { pub fn dust_value(&self) -> u64 {
// This must never be lower than Bitcoin Core's GetDustThreshold() (as of v0.21) as it may
// otherwise allow users to create transactions which likely can never be
// broadcasted/confirmed.
3 * // The default dust relay fee is 3000 satoshi/kB (ie 3 sat/vByte)
if self.is_op_return() { if self.is_op_return() {
0 0
} else if self.is_witness_program() { } else if self.is_witness_program() {
Self::WITNESS_OUTPUT_DUST_THRESHOLD 32 + 4 + 1 + (107 / 4) + 4 + // The spend cost copied from Core
8 + // The serialized size of the TxOut's amount field
self.consensus_encode(&mut ::std::io::sink()).unwrap() as u64 // The serialized size of this script_pubkey
} else { } else {
Self::LEGACY_OUTPUT_DUST_THRESHOLD 32 + 4 + 1 + 107 + 4 + // The spend cost copied from Core
8 + // The serialized size of the TxOut's amount field
self.consensus_encode(&mut ::std::io::sink()).unwrap() as u64 // The serialized size of this script_pubkey
} }
} }
@ -1252,5 +1252,24 @@ mod test {
let spending = Vec::from_hex("010000000001011f97548fbbe7a0db7588a66e18d803d0089315aa7d4cc28360b6ec50ef36718a0100000000ffffffff02df1776000000000017a9146c002a686959067f4866b8fb493ad7970290ab728757d29f0000000000220020701a8d401c84fb13e6baf169d59684e17abd9fa216c8cc5b9fc63d622ff8c58d04004730440220565d170eed95ff95027a69b313758450ba84a01224e1f7f130dda46e94d13f8602207bdd20e307f062594022f12ed5017bbf4a055a06aea91c10110a0e3bb23117fc014730440220647d2dc5b15f60bc37dc42618a370b2a1490293f9e5c8464f53ec4fe1dfe067302203598773895b4b16d37485cbe21b337f4e4b650739880098c592553add7dd4355016952210375e00eb72e29da82b89367947f29ef34afb75e8654f6ea368e0acdfd92976b7c2103a1b26313f430c4b15bb1fdce663207659d8cac749a0e53d70eff01874496feff2103c96d495bfdd5ba4145e3e046fee45e84a8a48ad05bd8dbb395c011a32cf9f88053ae00000000").unwrap(); let spending = Vec::from_hex("010000000001011f97548fbbe7a0db7588a66e18d803d0089315aa7d4cc28360b6ec50ef36718a0100000000ffffffff02df1776000000000017a9146c002a686959067f4866b8fb493ad7970290ab728757d29f0000000000220020701a8d401c84fb13e6baf169d59684e17abd9fa216c8cc5b9fc63d622ff8c58d04004730440220565d170eed95ff95027a69b313758450ba84a01224e1f7f130dda46e94d13f8602207bdd20e307f062594022f12ed5017bbf4a055a06aea91c10110a0e3bb23117fc014730440220647d2dc5b15f60bc37dc42618a370b2a1490293f9e5c8464f53ec4fe1dfe067302203598773895b4b16d37485cbe21b337f4e4b650739880098c592553add7dd4355016952210375e00eb72e29da82b89367947f29ef34afb75e8654f6ea368e0acdfd92976b7c2103a1b26313f430c4b15bb1fdce663207659d8cac749a0e53d70eff01874496feff2103c96d495bfdd5ba4145e3e046fee45e84a8a48ad05bd8dbb395c011a32cf9f88053ae00000000").unwrap();
spent.verify(0, 18393430, spending.as_slice()).unwrap(); spent.verify(0, 18393430, spending.as_slice()).unwrap();
} }
#[test]
fn defult_dust_value_tests() {
// Check that our dust_value() calculator correctly calculates the dust limit on common
// well-known scriptPubKey types.
let script_p2wpkh = Builder::new().push_int(0).push_slice(&[42; 20]).into_script();
assert!(script_p2wpkh.is_v0_p2wpkh());
assert_eq!(script_p2wpkh.dust_value(), 294);
let script_p2pkh = Builder::new()
.push_opcode(opcodes::all::OP_DUP)
.push_opcode(opcodes::all::OP_HASH160)
.push_slice(&[42; 20])
.push_opcode(opcodes::all::OP_EQUALVERIFY)
.push_opcode(opcodes::all::OP_CHECKSIG)
.into_script();
assert!(script_p2pkh.is_p2pkh());
assert_eq!(script_p2pkh.dust_value(), 546);
}
} }