Skip to content

Commit deda3f9

Browse files
TinyChain --> validateContent --> gas limit script updated / block size limit support added.
1 parent c41b638 commit deda3f9

1 file changed

Lines changed: 63 additions & 8 deletions

File tree

src/TinyChain/Instance.mjs

Lines changed: 63 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { Buffer } from 'buffer';
2-
import { formatBytes, TinyPromiseQueue } from 'tiny-essentials';
2+
import { TinyPromiseQueue } from 'tiny-essentials';
33
import { EventEmitter } from 'events';
44
import TinyCryptoParser from '../lib/TinyCryptoParser.mjs';
55

@@ -66,6 +66,7 @@ class TinyChainInstance {
6666
#blockSizeLimit;
6767
#payloadSizeLimit;
6868
#blockContentSizeLimit;
69+
#textEncoder = new TextEncoder();
6970

7071
/**
7172
* Important instance used to make event emitter.
@@ -271,7 +272,7 @@ class TinyChainInstance {
271272
* @param {Balances} [options.initialBalances={}] - Optional mapping of initial addresses to balances.
272273
* @param {string[]} [options.admins=[]] - List of admin public keys granted elevated permissions.
273274
*
274-
* @param {number} [options.blockContentSizeLimit=-1] - Defines the maximum number of items allowed inside a single block's content.
275+
* @param {number} [options.blockContentSizeLimit=-1] - Defines the maximum size (in bytes) allowed inside a single block's content.
275276
* A value of -1 disables the limit entirely.
276277
*
277278
* @param {number} [options.blockSizeLimit=-1] - Defines the total maximum size (in bytes) for an entire block.
@@ -635,14 +636,33 @@ class TinyChainInstance {
635636
*
636637
*/
637638
#createBlockInstance(options) {
638-
return new TinyChainBlock({
639+
const blockConfig = {
639640
baseFeePerGas: this.isCurrencyMode() ? this.getBaseFeePerGas() : 0n,
640641
payloadString: this.#payloadString,
641642
parser: this.#parser,
642643
signer: this.#signer,
643644
chainId: this.getChainId(),
644645
...options,
645-
});
646+
};
647+
648+
if (this.#blockSizeLimit >= 0) {
649+
const blockSize = this.#textEncoder.encode(
650+
this.#parser.serializeDeep(
651+
Object.fromEntries(
652+
Object.entries(blockConfig).filter(
653+
([key, value]) => typeof value !== 'function' && !['parser', 'signer'].includes(key),
654+
),
655+
),
656+
),
657+
).length;
658+
659+
if (blockSize > this.#blockSizeLimit)
660+
throw new Error(
661+
`Block size exceeded: block is ${blockSize} bytes, limit is ${this.#blockSizeLimit} bytes`,
662+
);
663+
}
664+
665+
return new TinyChainBlock(blockConfig);
646666
}
647667

648668
/**
@@ -800,12 +820,14 @@ class TinyChainInstance {
800820
* @param {string} [options.address] - Sender address of the transaction.
801821
* @param {string} [options.addressType] - Type of address (e.g., 'user', 'contract'). Must be a non-empty string.
802822
*
803-
* @throws {Error} If payload is not a string.
823+
* @throws {Error} If payload is not a string when required.
804824
* @throws {Error} If transfers is not an array.
805825
* @throws {Error} If any gas parameter is not a BigInt.
806826
* @throws {Error} If address is not a string.
807827
* @throws {Error} If addressType is invalid.
808828
* @throws {Error} If gas used exceeds the provided gas limit.
829+
* @throws {Error} If block content size exceeds the defined block content size limit.
830+
* @throws {Error} If payload size exceeds the defined payload size limit.
809831
*
810832
* @returns {bigint} Returns the estimated gas used for the transaction.
811833
*/
@@ -818,7 +840,8 @@ class TinyChainInstance {
818840
address,
819841
addressType,
820842
} = {}) {
821-
if (typeof payload !== 'string') throw new Error('Payload must be a string');
843+
if (this.#payloadString && typeof payload !== 'string')
844+
throw new Error('Payload must be a string');
822845
if (!Array.isArray(transfers)) throw new Error('Transfers must be an array');
823846
const gasUsed = this.isCurrencyMode() ? this.estimateGasUsed(transfers, payload) : 0n;
824847

@@ -833,9 +856,41 @@ class TinyChainInstance {
833856
if (typeof addressType !== 'string' || addressType.length === 0)
834857
throw new Error('Invalid address type');
835858

836-
if (gasUsed > gasLimit)
837-
throw new Error(`Gas limit exceeded: used ${gasUsed} > limit ${gasLimit}`);
859+
const totalGas = gasUsed + this.getBaseFeePerGas();
860+
if (totalGas > gasLimit)
861+
throw new Error(`Gas limit exceeded: used ${totalGas} > limit ${gasLimit}`);
838862
if (Array.isArray(transfers)) this.validateTransfers(address, addressType, transfers);
863+
864+
if (this.#payloadSizeLimit >= 0) {
865+
const payloadSize = this.#textEncoder.encode(
866+
this.#payloadString ? payload : this.#parser.serializeDeep(payload),
867+
).length;
868+
869+
if (payloadSize > this.#payloadSizeLimit)
870+
throw new Error(
871+
`Payload size exceeded: payload is ${payloadSize} bytes, limit is ${this.#payloadSizeLimit} bytes`,
872+
);
873+
}
874+
875+
if (this.#blockContentSizeLimit >= 0) {
876+
const blockContentSize = this.#textEncoder.encode(
877+
this.#parser.serializeDeep({
878+
payload,
879+
transfers,
880+
gasLimit,
881+
maxFeePerGas,
882+
maxPriorityFeePerGas,
883+
address,
884+
addressType,
885+
}),
886+
).length;
887+
888+
if (blockContentSize > this.#blockContentSizeLimit)
889+
throw new Error(
890+
`Block content size exceeded: content is ${blockContentSize} bytes, limit is ${this.#blockContentSizeLimit} bytes`,
891+
);
892+
}
893+
839894
return gasUsed;
840895
}
841896

0 commit comments

Comments
 (0)