@@ -207,6 +207,116 @@ describe("Dimensions", function () {
207207 } ) ;
208208 } ) ;
209209
210+ describe ( "times" , function ( ) {
211+ it ( "should multiply dimensions by a scalar" , function ( ) {
212+ const input = Dimensions . fromInput ( { chain : 10 } ) ;
213+ const doubled = input . times ( 2 ) ;
214+
215+ assert . strictEqual ( doubled . getInputWeight ( "min" ) , input . getInputWeight ( "min" ) * 2 ) ;
216+ assert . strictEqual ( doubled . getInputWeight ( "max" ) , input . getInputWeight ( "max" ) * 2 ) ;
217+ assert . strictEqual ( doubled . hasSegwit , input . hasSegwit ) ;
218+ } ) ;
219+
220+ it ( "should return zero for times(0)" , function ( ) {
221+ const input = Dimensions . fromInput ( { chain : 10 } ) ;
222+ const zeroed = input . times ( 0 ) ;
223+
224+ assert . strictEqual ( zeroed . getInputWeight ( ) , 0 ) ;
225+ assert . strictEqual ( zeroed . getOutputWeight ( ) , 0 ) ;
226+ } ) ;
227+
228+ it ( "should multiply outputs" , function ( ) {
229+ const output = Dimensions . fromOutput ( Buffer . alloc ( 34 ) ) ;
230+ const tripled = output . times ( 3 ) ;
231+
232+ assert . strictEqual ( tripled . getOutputWeight ( ) , output . getOutputWeight ( ) * 3 ) ;
233+ } ) ;
234+
235+ it ( "times(1) should return equivalent dimensions" , function ( ) {
236+ const dim = Dimensions . fromInput ( { chain : 20 } ) . plus ( Dimensions . fromOutput ( Buffer . alloc ( 23 ) ) ) ;
237+ const same = dim . times ( 1 ) ;
238+
239+ assert . strictEqual ( same . getInputWeight ( "min" ) , dim . getInputWeight ( "min" ) ) ;
240+ assert . strictEqual ( same . getInputWeight ( "max" ) , dim . getInputWeight ( "max" ) ) ;
241+ assert . strictEqual ( same . getOutputWeight ( ) , dim . getOutputWeight ( ) ) ;
242+ } ) ;
243+ } ) ;
244+
245+ describe ( "getInputWeight and getInputVSize" , function ( ) {
246+ it ( "should return input weight only (no overhead)" , function ( ) {
247+ const input = Dimensions . fromInput ( { chain : 10 } ) ;
248+ const inputWeight = input . getInputWeight ( ) ;
249+
250+ // Input weight should be less than total weight (which includes overhead)
251+ assert . ok ( inputWeight < input . getWeight ( ) ) ;
252+ assert . ok ( inputWeight > 0 ) ;
253+ } ) ;
254+
255+ it ( "should return min/max input weights for ECDSA inputs" , function ( ) {
256+ const input = Dimensions . fromInput ( { chain : 10 } ) ;
257+
258+ // p2shP2wsh has ECDSA variance
259+ assert . ok ( input . getInputWeight ( "min" ) < input . getInputWeight ( "max" ) ) ;
260+ assert . ok ( input . getInputVSize ( "min" ) < input . getInputVSize ( "max" ) ) ;
261+ } ) ;
262+
263+ it ( "should return equal min/max for Schnorr inputs" , function ( ) {
264+ const input = Dimensions . fromInput ( { chain : 40 } ) ;
265+
266+ // p2trMusig2 keypath has no variance
267+ assert . strictEqual ( input . getInputWeight ( "min" ) , input . getInputWeight ( "max" ) ) ;
268+ assert . strictEqual ( input . getInputVSize ( "min" ) , input . getInputVSize ( "max" ) ) ;
269+ } ) ;
270+
271+ it ( "getInputVSize should be ceiling of weight/4" , function ( ) {
272+ const input = Dimensions . fromInput ( { chain : 20 } ) ;
273+
274+ assert . strictEqual ( input . getInputVSize ( "min" ) , Math . ceil ( input . getInputWeight ( "min" ) / 4 ) ) ;
275+ assert . strictEqual ( input . getInputVSize ( "max" ) , Math . ceil ( input . getInputWeight ( "max" ) / 4 ) ) ;
276+ } ) ;
277+
278+ it ( "should return zero for output-only dimensions" , function ( ) {
279+ const output = Dimensions . fromOutput ( Buffer . alloc ( 34 ) ) ;
280+
281+ assert . strictEqual ( output . getInputWeight ( ) , 0 ) ;
282+ assert . strictEqual ( output . getInputVSize ( ) , 0 ) ;
283+ } ) ;
284+ } ) ;
285+
286+ describe ( "getOutputWeight and getOutputVSize" , function ( ) {
287+ it ( "should return output weight only (no overhead)" , function ( ) {
288+ const output = Dimensions . fromOutput ( Buffer . alloc ( 23 ) ) ;
289+ const outputWeight = output . getOutputWeight ( ) ;
290+
291+ // Output weight = 4 * (8 + 1 + 23) = 128
292+ assert . strictEqual ( outputWeight , 128 ) ;
293+ } ) ;
294+
295+ it ( "getOutputVSize should be ceiling of weight/4" , function ( ) {
296+ const output = Dimensions . fromOutput ( Buffer . alloc ( 23 ) ) ;
297+
298+ assert . strictEqual ( output . getOutputVSize ( ) , Math . ceil ( output . getOutputWeight ( ) / 4 ) ) ;
299+ // 128 / 4 = 32
300+ assert . strictEqual ( output . getOutputVSize ( ) , 32 ) ;
301+ } ) ;
302+
303+ it ( "should return zero for input-only dimensions" , function ( ) {
304+ const input = Dimensions . fromInput ( { chain : 10 } ) ;
305+
306+ assert . strictEqual ( input . getOutputWeight ( ) , 0 ) ;
307+ assert . strictEqual ( input . getOutputVSize ( ) , 0 ) ;
308+ } ) ;
309+
310+ it ( "should combine correctly with plus" , function ( ) {
311+ const input = Dimensions . fromInput ( { chain : 10 } ) ;
312+ const output = Dimensions . fromOutput ( Buffer . alloc ( 34 ) ) ;
313+ const combined = input . plus ( output ) ;
314+
315+ assert . strictEqual ( combined . getInputWeight ( ) , input . getInputWeight ( ) ) ;
316+ assert . strictEqual ( combined . getOutputWeight ( ) , output . getOutputWeight ( ) ) ;
317+ } ) ;
318+ } ) ;
319+
210320 describe ( "integration tests with fixtures" , function ( ) {
211321 // Zcash has additional transaction overhead (version group, expiry height, etc.)
212322 // that we don't account for in Dimensions - skip it for now
0 commit comments