Skip to content

Commit

Permalink
1218 remove the dependency on utils for num management (#1252)
Browse files Browse the repository at this point in the history
* refactor: 1218 FPN unifies integers validation

* refactor: 1218 FPN unifies natural/integer/rational number validation

* refactor: 1122 Secp256k1 class unifies constants, docs, methods and tests

---------

Signed-off-by: Luca Nicola Debiasi <[email protected]>
Co-authored-by: Fabio Rigamonti <[email protected]>
  • Loading branch information
lucanicoladebiasi and fabiorigam authored Sep 9, 2024
1 parent 7468570 commit 148c6cb
Show file tree
Hide file tree
Showing 10 changed files with 119 additions and 231 deletions.
2 changes: 2 additions & 0 deletions docs/diagrams/architecture/vcdm.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,10 @@ classDiagram
+boolean isInteger()
+boolean isIntegerExpression(string exp)$
+boolean isNaN()
+boolean isNaturalExpression(string exp)$
+boolean isNegative()
+boolean isNegativeInfinite()
+boolean isNumberExpression(string exp)$
+boolean isPositive()
+boolean isPositiveInfinite()
+boolean isUnsignedIntegerExpression(string exp)$
Expand Down
3 changes: 1 addition & 2 deletions packages/core/src/encoding/rlp/helpers/numerickind.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,7 @@ const _validateNumericKindNumber = (num: number, context: string): void => {
*/
const _validateNumericKindString = (str: string, context: string): void => {
const isHexUInt = HexUInt.isValid0x(str);
const isDecimal = FPN.isUnsignedIntegerExpression(str);

const isDecimal = FPN.isNaturalExpression(str);
// Ensure the string is either a hex or decimal number.
if (!isHexUInt && !isDecimal) {
throw new InvalidRLP(
Expand Down
4 changes: 2 additions & 2 deletions packages/core/src/hdkey/HDKey.ts
Original file line number Diff line number Diff line change
Expand Up @@ -226,9 +226,9 @@ class HDKey extends s_bip32.HDKey {
// m
(index === 0 ? component === 'm' : false) ||
// "number"
FPN.isUnsignedIntegerExpression(component) ||
FPN.isNaturalExpression(component) ||
// "number'"
(FPN.isUnsignedIntegerExpression(component.slice(0, -1)) &&
(FPN.isNaturalExpression(component.slice(0, -1)) &&
component.endsWith("'"))
);
}
Expand Down
17 changes: 2 additions & 15 deletions packages/core/src/utils/data/data.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import * as nc_utils from '@noble/curves/abstract/utils';
import { NUMERIC_REGEX, ZERO_BYTES } from '../const';
import { Hex, Txt } from '../../vcdm';
import { InvalidDataType } from '@vechain/sdk-errors';
import { ZERO_BYTES } from '../const';

/**
* Decodes a hexadecimal string representing a bytes32 value into a string.
Expand Down Expand Up @@ -76,20 +76,7 @@ const encodeBytes32String = (
}
};

/**
* Checks whether the provided string is a valid decimal numeric string.
*
* @param {string} value - The value to check.
* @returns {boolean} - Returns true if the value is numeric, false otherwise.
*
* @see {@link NUMERIC_REGEX}
*/
const isNumeric = (value: string): boolean => {
return NUMERIC_REGEX.test(value);
};

export const dataUtils = {
decodeBytes32String,
encodeBytes32String,
isNumeric
encodeBytes32String
};
55 changes: 50 additions & 5 deletions packages/core/src/vcdm/FPN.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,12 +58,20 @@ class FPN implements VeChainDataModel<FPN> {
private static readonly REGEX_INTEGER: RegExp = /^[-+]?\d+$/;

/**
* Regular expression pattern for matching unsigned integers expressed as base 10 strings.
* Regular expression for matching numeric values expressed as base 10 strings.
*
* @constant {RegExp} NUMERIC_REGEX
*/
private static readonly REGEX_NUMBER =
/(^[-+]?\d+(\.\d+)?)$|(^[-+]?\.\d+)$/;

/**
* Regular expression pattern for matching natural numbers expressed as base 10 strings.
*
* @type {RegExp}
* @constant
*/
private static readonly REGEX_UINTEGER: RegExp = /^\d+$/;
private static readonly REGEX_NATURAL: RegExp = /^\d+$/;

/**
* Represents the zero constant.
Expand Down Expand Up @@ -421,12 +429,13 @@ class FPN implements VeChainDataModel<FPN> {
}

/**
* Checks if a given string expression is an integer,
* Checks if a given string expression is an integer in base 10 notation,
* considering `-` for negative and `+` optional for positive values.
*
* @param {string} exp - The string expression to be tested.
*
* @return {boolean} True if the expression is an integer, false otherwise.
* @return {boolean} `true` if the expression is an integer,
* `false` otherwise.
*/
public static isIntegerExpression(exp: string): boolean {
return this.REGEX_INTEGER.test(exp);
Expand All @@ -443,6 +452,19 @@ class FPN implements VeChainDataModel<FPN> {
return Number.isNaN(this.ef);
}

/**
* Checks if a given string expression is a natural (unsigned positive integer)
* number in base 10 notation.
*
* @param {string} exp - The string expression to be tested.
*
* @return {boolean} `true` if the expression is a natural number,
* `false` otherwise.
*/
public static isNaturalExpression(exp: string): boolean {
return this.REGEX_NATURAL.test(exp);
}

/**
* Returns `true` if the sign of this FPN is negative, otherwise returns `false`.
*
Expand All @@ -461,6 +483,29 @@ class FPN implements VeChainDataModel<FPN> {
return this.ef === Number.NEGATIVE_INFINITY;
}

/**
* Checks if a given string expression is a number in base 10 notation,
* considering `-` for negative and `+` optional for positive values.
*
* The method returns `true` for the following cases.
* - Whole numbers:
* - Positive whole numbers, optionally signed: 1, +2, 3, ...
* - Negative whole numbers: -1, -2, -3, ...
* - Decimal numbers:
* - Positive decimal numbers, optionally signed: 1.0, +2.5, 3.14, ...
* - Negative decimal numbers: -1.0, -2.5, -3.14, ...
* - Decimal numbers without whole part:
* - Positive decimal numbers, optionally signed: .1, +.5, .75, ...
* - Negative decimal numbers: -.1, -.5, -.75, ...
*
* @param exp - The string expression to be checked.
*
* @return `true` is `exp` represents a number, otherwise `false`.
*/
public static isNumberExpression(exp: string): boolean {
return FPN.REGEX_NUMBER.test(exp);
}

/**
* Returns `true` if the sign of this FPN is positive, otherwise returns `false`.
*
Expand Down Expand Up @@ -490,7 +535,7 @@ class FPN implements VeChainDataModel<FPN> {
* false otherwise.
*/
public static isUnsignedIntegerExpression(exp: string): boolean {
return this.REGEX_UINTEGER.test(exp);
return this.REGEX_NATURAL.test(exp);
}

/**
Expand Down
19 changes: 1 addition & 18 deletions packages/core/tests/utils/data/data.unit.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@ import {
decodeBytes32StringTestCases,
encodeBytes32StringTestCases,
invalidDecodeBytes32StringTestCases,
invalidEncodeBytes32StringTestCases,
isNumericTestCases
invalidEncodeBytes32StringTestCases
} from './fixture';
import { stringifyData } from '@vechain/sdk-errors';

Expand Down Expand Up @@ -75,20 +74,4 @@ describe('dataUtils', () => {
}
);
});

/**
* Verification of numbers in string format
*/
describe('isNumeric', () => {
/**
* Test cases for isNumeric function.
*/
isNumericTestCases.forEach(({ value, expected }) => {
test(`should return ${expected} for ${stringifyData(
value
)}`, () => {
expect(dataUtils.isNumeric(value)).toBe(expected);
});
});
});
});
87 changes: 0 additions & 87 deletions packages/core/tests/utils/data/fixture.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,92 +77,6 @@ const prefixedAndUnprefixedStrings: Array<{
}
];

/**
* Test cases for isNumeric function.
*/
const isNumericTestCases = [
{
value: '0',
expected: true
},
{
value: '1',
expected: true
},
{
value: '1.54523532463463642352342354645363',
expected: true
},
{
value: '.52434234',
expected: true
},
{
value: '32412341234.543563463',
expected: true
},
{
value: '1,6',
expected: false
},
{
value: '1.6.7',
expected: false
},
{
value: '1.6,7',
expected: false
},
{
value: '1,6,7',
expected: false
},
{
value: '1,6.7',
expected: false
},
{
value: '1.6,7.8',
expected: false
},
{
value: '1.',
expected: false
},
{
value: '.',
expected: false
},
{
value: '1.6.',
expected: false
},
{
value: '1.6.7',
expected: false
},
{
value: '1.6.7.',
expected: false
},
{
value: '-1.5',
expected: true
},
{
value: '-1.5.6',
expected: false
},
{
value: '0x152',
expected: false
},
{
value: '',
expected: false
}
];

/**
* Test cases for encodeBytes32String function.
*/
Expand Down Expand Up @@ -276,7 +190,6 @@ export {
validThorIDs,
invalidThorIDs,
prefixedAndUnprefixedStrings,
isNumericTestCases,
encodeBytes32StringTestCases,
invalidEncodeBytes32StringTestCases,
decodeBytes32StringTestCases,
Expand Down
69 changes: 0 additions & 69 deletions packages/core/tests/utils/revision/fixture.ts

This file was deleted.

28 changes: 0 additions & 28 deletions packages/core/tests/utils/revision/revision.unit.test.ts

This file was deleted.

Loading

1 comment on commit 148c6cb

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Test Coverage

Summary

Lines Statements Branches Functions
Coverage: 99%
99.41% (4073/4097) 98.23% (1278/1301) 99.75% (807/809)
Title Tests Skipped Failures Errors Time
core 794 0 💤 0 ❌ 0 🔥 1m 33s ⏱️
network 668 0 💤 0 ❌ 0 🔥 4m 0s ⏱️
errors 42 0 💤 0 ❌ 0 🔥 15.525s ⏱️

Please sign in to comment.