Skip to content

Commit 855ba79

Browse files
authored
Merge pull request #1639 from input-output-hk/fix/use-actual-address-size-for-min-value
fix: use actual address size for min value computation
2 parents 694c50c + 42bb1c7 commit 855ba79

File tree

4 files changed

+108
-99
lines changed

4 files changed

+108
-99
lines changed

packages/e2e/test/wallet_epoch_0/PersonalWallet/metadata.test.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,12 @@ describe('PersonalWallet/metadata', () => {
2222
test('can submit tx with metadata and then query it', async () => {
2323
const metadata: Cardano.TxMetadata = new Map([[123n, '1234']]);
2424
const walletUtil = createWalletUtil(wallet);
25-
const { minimumCoin } = await walletUtil.validateValue({ coins: 0n });
25+
const { minimumCoin } = await walletUtil.validateOutput({
26+
address: Cardano.PaymentAddress(
27+
'addr_test1qqydn46r6mhge0kfpqmt36m6q43knzsd9ga32n96m89px3nuzcjqw982pcftgx53fu5527z2cj2tkx2h8ux2vxsg475qypp3m9'
28+
),
29+
value: { coins: 0n }
30+
});
2631

2732
// Make sure the wallet has sufficient funds to run this test
2833
await walletReady(wallet, minimumCoin);

packages/tx-construction/src/output-validation/outputValidator.ts

Lines changed: 5 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,12 @@ import { computeMinimumCoinQuantity, tokenBundleSizeExceedsLimit } from '../inpu
1212
export const createOutputValidator = ({
1313
protocolParameters: protocolParametersGetter
1414
}: OutputValidatorContext): OutputValidator => {
15-
const validateValue = async (
16-
value: Cardano.Value,
15+
const validateOutput = async (
16+
{ address, value }: Cardano.TxOut,
1717
protocolParameters?: ProtocolParametersRequiredByOutputValidator
18-
): Promise<OutputValidation> => {
18+
) => {
1919
const { coinsPerUtxoByte, maxValueSize } = protocolParameters || (await protocolParametersGetter());
20-
const stubMaxSizeAddress = Cardano.PaymentAddress(
21-
'addr_test1qqydn46r6mhge0kfpqmt36m6q43knzsd9ga32n96m89px3nuzcjqw982pcftgx53fu5527z2cj2tkx2h8ux2vxsg475qypp3m9'
22-
);
23-
const stubTxOut: Cardano.TxOut = { address: stubMaxSizeAddress, value };
20+
const stubTxOut: Cardano.TxOut = { address, value };
2421
const negativeAssetQty = value.assets ? [...value.assets.values()].some((qty) => qty <= 0) : false;
2522
if (negativeAssetQty) {
2623
// return early, otherwise 'minimumCoin/maxValueSize' will fail with error: "ParseIntError { kind: InvalidDigit }"
@@ -39,18 +36,6 @@ export const createOutputValidator = ({
3936
tokenBundleSizeExceedsLimit: tokenBundleSizeExceedsLimit(maxValueSize)(value.assets)
4037
};
4138
};
42-
const validateValues = async (values: Iterable<Cardano.Value>) => {
43-
const protocolParameters = await protocolParametersGetter();
44-
const validations = new Map<Cardano.Value, OutputValidation>();
45-
for (const value of values) {
46-
validations.set(value, await validateValue(value, protocolParameters));
47-
}
48-
return validations;
49-
};
50-
const validateOutput = async (
51-
output: Cardano.TxOut,
52-
protocolParameters?: ProtocolParametersRequiredByOutputValidator
53-
) => validateValue(output.value, protocolParameters);
5439

5540
return {
5641
validateOutput,
@@ -61,8 +46,6 @@ export const createOutputValidator = ({
6146
validations.set(output, await validateOutput(output, protocolParameters));
6247
}
6348
return validations;
64-
},
65-
validateValue,
66-
validateValues
49+
}
6750
};
6851
};

packages/tx-construction/src/output-validation/types.ts

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -17,22 +17,6 @@ export interface OutputValidation {
1717
}
1818

1919
export interface OutputValidator {
20-
/**
21-
* Assumes that value will be used with an output that has:
22-
* - no datum
23-
* - grouped address (Shelley era+)
24-
*
25-
* @returns Validates that token bundle size is within limits and computes minimum coin quantity
26-
*/
27-
validateValue(output: Cardano.Value): Promise<OutputValidation>;
28-
/**
29-
* Assumes that values will be used with outputs that have:
30-
* - no datum
31-
* - grouped address (Shelley era+)
32-
*
33-
* @returns For every value, validates that token bundle size is within limits and computes minimum coin quantity
34-
*/
35-
validateValues(outputs: Iterable<Cardano.Value>): Promise<Map<Cardano.Value, OutputValidation>>;
3620
/**
3721
* @returns Validates that token bundle size is within limits and computes minimum coin quantity
3822
*/

packages/tx-construction/test/output-validation/outputValidator.test.ts

Lines changed: 97 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@ import { Cardano } from '@cardano-sdk/core';
33
import { OutputValidator, createOutputValidator } from '../../src';
44

55
describe('createOutputValidator', () => {
6+
const address = Cardano.PaymentAddress(
7+
'addr_test1qqydn46r6mhge0kfpqmt36m6q43knzsd9ga32n96m89px3nuzcjqw982pcftgx53fu5527z2cj2tkx2h8ux2vxsg475qypp3m9'
8+
);
69
let validator: OutputValidator;
710

811
beforeAll(() => {
@@ -14,67 +17,101 @@ describe('createOutputValidator', () => {
1417
});
1518
});
1619

17-
it('validateValue validates minimum coin quantity', async () => {
18-
expect((await validator.validateValue({ coins: 2_000_000n })).coinMissing).toBe(0n);
19-
expect((await validator.validateValue({ coins: 500_000n })).coinMissing).toBeGreaterThan(0n);
20-
});
20+
describe('validateOutput', () => {
21+
it('validates minimum coin quantity', async () => {
22+
expect((await validator.validateOutput({ address, value: { coins: 2_000_000n } })).coinMissing).toBe(0n);
23+
expect((await validator.validateOutput({ address, value: { coins: 500_000n } })).coinMissing).toBeGreaterThan(0n);
24+
});
2125

22-
it('validateValue validates bundle size', async () => {
23-
expect(
24-
(
25-
await validator.validateValue({
26-
assets: new Map([
27-
[Cardano.AssetId('b01fb3b8c3dd6b3705a5dc8bcd5a70759f70ad5d97a72005caeac3c652657675746f31333237'), 1n]
28-
]),
29-
coins: 2_000_000n
30-
})
31-
).tokenBundleSizeExceedsLimit
32-
).toBe(false);
33-
expect(
34-
(
35-
await validator.validateValue({
36-
assets: new Map([
37-
[Cardano.AssetId('b01fb3b8c3dd6b3705a5dc8bcd5a70759f70ad5d97a72005caeac3c652657675746f31333237'), 1n],
38-
[Cardano.AssetId('c01fb3b8c3dd6b3705a5dc8bcd5a70759f70ad5d97a72005caeac3c652657675746f31333237'), 2n]
39-
]),
40-
coins: 2_000_000n
41-
})
42-
).tokenBundleSizeExceedsLimit
43-
).toBe(true);
44-
});
26+
it('validates bundle size', async () => {
27+
expect(
28+
(
29+
await validator.validateOutput({
30+
address,
31+
value: {
32+
assets: new Map([
33+
[Cardano.AssetId('b01fb3b8c3dd6b3705a5dc8bcd5a70759f70ad5d97a72005caeac3c652657675746f31333237'), 1n]
34+
]),
35+
coins: 2_000_000n
36+
}
37+
})
38+
).tokenBundleSizeExceedsLimit
39+
).toBe(false);
40+
expect(
41+
(
42+
await validator.validateOutput({
43+
address,
44+
value: {
45+
assets: new Map([
46+
[Cardano.AssetId('b01fb3b8c3dd6b3705a5dc8bcd5a70759f70ad5d97a72005caeac3c652657675746f31333237'), 1n],
47+
[Cardano.AssetId('c01fb3b8c3dd6b3705a5dc8bcd5a70759f70ad5d97a72005caeac3c652657675746f31333237'), 2n]
48+
]),
49+
coins: 2_000_000n
50+
}
51+
})
52+
).tokenBundleSizeExceedsLimit
53+
).toBe(true);
54+
});
4555

46-
it('validateValue validates negative asset quantity', async () => {
47-
expect(
48-
(
49-
await validator.validateValue({
50-
assets: new Map([
51-
[Cardano.AssetId('b01fb3b8c3dd6b3705a5dc8bcd5a70759f70ad5d97a72005caeac3c652657675746f31333237'), 1n]
52-
]),
53-
coins: 2_000_000n
54-
})
55-
).negativeAssetQty
56-
).toBe(false);
57-
expect(
58-
(
59-
await validator.validateValue({
60-
assets: new Map([
61-
[Cardano.AssetId('b01fb3b8c3dd6b3705a5dc8bcd5a70759f70ad5d97a72005caeac3c652657675746f31333237'), 1n],
62-
[Cardano.AssetId('c01fb3b8c3dd6b3705a5dc8bcd5a70759f70ad5d97a72005caeac3c652657675746f31333237'), -2n]
63-
]),
64-
coins: 2_000_000n
65-
})
66-
).negativeAssetQty
67-
).toBe(true);
68-
expect(
69-
(
70-
await validator.validateValue({
71-
assets: new Map([
72-
[Cardano.AssetId('b01fb3b8c3dd6b3705a5dc8bcd5a70759f70ad5d97a72005caeac3c652657675746f31333237'), 1n],
73-
[Cardano.AssetId('c01fb3b8c3dd6b3705a5dc8bcd5a70759f70ad5d97a72005caeac3c652657675746f31333237'), 0n]
74-
]),
75-
coins: 2_000_000n
76-
})
77-
).negativeAssetQty
78-
).toBe(true);
56+
it('validates negative asset quantity', async () => {
57+
expect(
58+
(
59+
await validator.validateOutput({
60+
address,
61+
value: {
62+
assets: new Map([
63+
[Cardano.AssetId('b01fb3b8c3dd6b3705a5dc8bcd5a70759f70ad5d97a72005caeac3c652657675746f31333237'), 1n]
64+
]),
65+
coins: 2_000_000n
66+
}
67+
})
68+
).negativeAssetQty
69+
).toBe(false);
70+
expect(
71+
(
72+
await validator.validateOutput({
73+
address,
74+
value: {
75+
assets: new Map([
76+
[Cardano.AssetId('b01fb3b8c3dd6b3705a5dc8bcd5a70759f70ad5d97a72005caeac3c652657675746f31333237'), 1n],
77+
[Cardano.AssetId('c01fb3b8c3dd6b3705a5dc8bcd5a70759f70ad5d97a72005caeac3c652657675746f31333237'), -2n]
78+
]),
79+
coins: 2_000_000n
80+
}
81+
})
82+
).negativeAssetQty
83+
).toBe(true);
84+
expect(
85+
(
86+
await validator.validateOutput({
87+
address,
88+
value: {
89+
assets: new Map([
90+
[Cardano.AssetId('b01fb3b8c3dd6b3705a5dc8bcd5a70759f70ad5d97a72005caeac3c652657675746f31333237'), 1n],
91+
[Cardano.AssetId('c01fb3b8c3dd6b3705a5dc8bcd5a70759f70ad5d97a72005caeac3c652657675746f31333237'), 0n]
92+
]),
93+
coins: 2_000_000n
94+
}
95+
})
96+
).negativeAssetQty
97+
).toBe(true);
98+
});
99+
100+
it('uses output address size as minimum coin computation parameter', async () => {
101+
const value: Cardano.Value = { coins: 123n };
102+
const { minimumCoin: byronAddressMinimumCoin } = await validator.validateOutput({
103+
address: Cardano.PaymentAddress(
104+
'DdzFFzCqrht4PWfBGtmrQz4x1GkZHYLVGbK7aaBkjWxujxzz3L5GxCgPiTsks5RjUr3yX9KvwKjNJBt7ZzPCmS3fUQrGeRvo9Y1YBQKQ'
105+
),
106+
value
107+
});
108+
const { minimumCoin: shelleyAddressMinimumCoin } = await validator.validateOutput({
109+
address: Cardano.PaymentAddress(
110+
'addr_test1qqydn46r6mhge0kfpqmt36m6q43knzsd9ga32n96m89px3nuzcjqw982pcftgx53fu5527z2cj2tkx2h8ux2vxsg475qypp3m9'
111+
),
112+
value
113+
});
114+
expect(byronAddressMinimumCoin).toBeGreaterThan(shelleyAddressMinimumCoin);
115+
});
79116
});
80117
});

0 commit comments

Comments
 (0)