@@ -930,6 +930,34 @@ impl Transaction {
930930 ( weight + 4 - 1 ) / 4
931931 }
932932
933+ /// Get the "discount weight" of this transaction; this is the weight minus the output witnesses and minus the
934+ /// differences between asset and nonce commitments from their explicit values.
935+ pub fn discount_weight ( & self ) -> usize {
936+ let mut weight = self . scaled_size ( 4 ) ;
937+
938+ for out in self . output . iter ( ) {
939+ let rp_len = out. witness . rangeproof_len ( ) ;
940+ let sp_len = out. witness . surjectionproof_len ( ) ;
941+ let witness_weight = VarInt ( sp_len as u64 ) . size ( ) + sp_len + VarInt ( rp_len as u64 ) . size ( ) + rp_len;
942+ weight -= witness_weight. saturating_sub ( 2 ) ; // explicit transactions have 1 byte for each empty proof
943+ if out. value . is_confidential ( ) {
944+ weight -= 33 - 9 ;
945+ }
946+ if out. nonce . is_confidential ( ) {
947+ weight -= 33 - 1 ;
948+ }
949+ }
950+
951+ weight
952+ }
953+
954+ /// Returns the "discount virtual size" (discountvsize) of this transaction.
955+ ///
956+ /// Will be `ceil(discount weight / 4.0)`.
957+ pub fn discount_vsize ( & self ) -> usize {
958+ ( self . discount_weight ( ) + 4 - 1 ) / 4
959+ }
960+
933961 fn scaled_size ( & self , scale_factor : usize ) -> usize {
934962 let witness_flag = self . has_witness ( ) ;
935963
@@ -2399,4 +2427,88 @@ mod tests {
23992427 ") ;
24002428 assert ! ( input. pegin_data( ) . is_none( ) ) ;
24012429 }
2430+
2431+ #[ test]
2432+ fn discount_vsize ( ) {
2433+ let tx: Transaction = hex_deserialize ! ( include_str!( "../tests/data/1in2out_pegin.hex" ) ) ;
2434+ assert_eq ! ( tx. input. len( ) , 1 ) ;
2435+ assert ! ( tx. input[ 0 ] . is_pegin( ) ) ;
2436+ assert_eq ! ( tx. output. len( ) , 2 ) ;
2437+ assert_eq ! ( tx. weight( ) , 2403 ) ;
2438+ assert_eq ! ( tx. vsize( ) , 601 ) ;
2439+ assert_eq ! ( tx. discount_weight( ) , 2403 ) ;
2440+ assert_eq ! ( tx. discount_vsize( ) , 601 ) ;
2441+
2442+ let tx: Transaction = hex_deserialize ! ( include_str!( "../tests/data/1in2out_tx.hex" ) ) ;
2443+ assert_eq ! ( tx. input. len( ) , 1 ) ;
2444+ assert_eq ! ( tx. output. len( ) , 2 ) ;
2445+ assert_eq ! ( tx. weight( ) , 5330 ) ;
2446+ assert_eq ! ( tx. vsize( ) , 1333 ) ;
2447+ assert_eq ! ( tx. discount_weight( ) , 1031 ) ;
2448+ assert_eq ! ( tx. discount_vsize( ) , 258 ) ;
2449+
2450+ let tx: Transaction = hex_deserialize ! ( include_str!( "../tests/data/1in3out_tx.hex" ) ) ;
2451+ assert_eq ! ( tx. input. len( ) , 1 ) ;
2452+ assert_eq ! ( tx. output. len( ) , 3 ) ;
2453+ assert_eq ! ( tx. weight( ) , 10107 ) ;
2454+ assert_eq ! ( tx. vsize( ) , 2527 ) ;
2455+ assert_eq ! ( tx. discount_weight( ) , 1509 ) ;
2456+ assert_eq ! ( tx. discount_vsize( ) , 378 ) ;
2457+
2458+ let tx: Transaction = hex_deserialize ! ( include_str!( "../tests/data/2in3out_exp.hex" ) ) ;
2459+ assert_eq ! ( tx. input. len( ) , 2 ) ;
2460+ assert_eq ! ( tx. output. len( ) , 3 ) ;
2461+ assert_eq ! ( tx. weight( ) , 1302 ) ;
2462+ assert_eq ! ( tx. vsize( ) , 326 ) ;
2463+ assert_eq ! ( tx. discount_weight( ) , 1302 ) ;
2464+ assert_eq ! ( tx. discount_vsize( ) , 326 ) ;
2465+
2466+ let tx: Transaction = hex_deserialize ! ( include_str!( "../tests/data/2in3out_tx.hex" ) ) ;
2467+ assert_eq ! ( tx. input. len( ) , 2 ) ;
2468+ assert_eq ! ( tx. output. len( ) , 3 ) ;
2469+ assert_eq ! ( tx. weight( ) , 10300 ) ;
2470+ assert_eq ! ( tx. vsize( ) , 2575 ) ;
2471+ assert_eq ! ( tx. discount_weight( ) , 1638 ) ;
2472+ assert_eq ! ( tx. discount_vsize( ) , 410 ) ;
2473+
2474+ let tx: Transaction = hex_deserialize ! ( include_str!( "../tests/data/2in3out_tx2.hex" ) ) ;
2475+ assert_eq ! ( tx. input. len( ) , 2 ) ;
2476+ assert_eq ! ( tx. output. len( ) , 3 ) ;
2477+ assert_eq ! ( tx. weight( ) , 10536 ) ;
2478+ assert_eq ! ( tx. vsize( ) , 2634 ) ;
2479+ assert_eq ! ( tx. discount_weight( ) , 1874 ) ;
2480+ assert_eq ! ( tx. discount_vsize( ) , 469 ) ;
2481+
2482+ let tx: Transaction = hex_deserialize ! ( include_str!( "../tests/data/3in3out_tx.hex" ) ) ;
2483+ assert_eq ! ( tx. input. len( ) , 3 ) ;
2484+ assert_eq ! ( tx. output. len( ) , 3 ) ;
2485+ assert_eq ! ( tx. weight( ) , 10922 ) ;
2486+ assert_eq ! ( tx. vsize( ) , 2731 ) ;
2487+ assert_eq ! ( tx. discount_weight( ) , 2196 ) ;
2488+ assert_eq ! ( tx. discount_vsize( ) , 549 ) ;
2489+
2490+ let tx: Transaction = hex_deserialize ! ( include_str!( "../tests/data/4in3out_tx.hex" ) ) ;
2491+ assert_eq ! ( tx. input. len( ) , 4 ) ;
2492+ assert_eq ! ( tx. output. len( ) , 3 ) ;
2493+ assert_eq ! ( tx. weight( ) , 11192 ) ;
2494+ assert_eq ! ( tx. vsize( ) , 2798 ) ;
2495+ assert_eq ! ( tx. discount_weight( ) , 2466 ) ;
2496+ assert_eq ! ( tx. discount_vsize( ) , 617 ) ;
2497+
2498+ let tx: Transaction = hex_deserialize ! ( include_str!( "../tests/data/2in4out_tx.hex" ) ) ;
2499+ assert_eq ! ( tx. input. len( ) , 2 ) ;
2500+ assert_eq ! ( tx. output. len( ) , 4 ) ;
2501+ assert_eq ! ( tx. weight( ) , 15261 ) ;
2502+ assert_eq ! ( tx. vsize( ) , 3816 ) ;
2503+ assert_eq ! ( tx. discount_weight( ) , 2268 ) ;
2504+ assert_eq ! ( tx. discount_vsize( ) , 567 ) ;
2505+
2506+ let tx: Transaction = hex_deserialize ! ( include_str!( "../tests/data/2in5out_tx.hex" ) ) ;
2507+ assert_eq ! ( tx. input. len( ) , 2 ) ;
2508+ assert_eq ! ( tx. output. len( ) , 5 ) ;
2509+ assert_eq ! ( tx. weight( ) , 20030 ) ;
2510+ assert_eq ! ( tx. vsize( ) , 5008 ) ;
2511+ assert_eq ! ( tx. discount_weight( ) , 2706 ) ;
2512+ assert_eq ! ( tx. discount_vsize( ) , 677 ) ;
2513+ }
24022514}
0 commit comments