@agirails/sdk 2.0.1-beta → 2.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +190 -0
- package/README.md +116 -108
- package/bin/actp +10 -0
- package/dist/ACTPClient.d.ts +456 -33
- package/dist/ACTPClient.d.ts.map +1 -1
- package/dist/ACTPClient.js +477 -93
- package/dist/ACTPClient.js.map +1 -1
- package/dist/abi/AgentRegistry.json +782 -0
- package/dist/abi/EscrowVault.json +106 -38
- package/dist/abi/IdentityRegistry.json +316 -0
- package/dist/adapters/BaseAdapter.d.ts +231 -0
- package/dist/adapters/BaseAdapter.d.ts.map +1 -0
- package/dist/adapters/BaseAdapter.js +393 -0
- package/dist/adapters/BaseAdapter.js.map +1 -0
- package/dist/adapters/BeginnerAdapter.d.ts +152 -0
- package/dist/adapters/BeginnerAdapter.d.ts.map +1 -0
- package/dist/adapters/BeginnerAdapter.js +168 -0
- package/dist/adapters/BeginnerAdapter.js.map +1 -0
- package/dist/adapters/IntermediateAdapter.d.ts +211 -0
- package/dist/adapters/IntermediateAdapter.d.ts.map +1 -0
- package/dist/adapters/IntermediateAdapter.js +260 -0
- package/dist/adapters/IntermediateAdapter.js.map +1 -0
- package/dist/adapters/index.d.ts +15 -0
- package/dist/adapters/index.d.ts.map +1 -0
- package/dist/adapters/index.js +26 -0
- package/dist/adapters/index.js.map +1 -0
- package/dist/builders/DeliveryProofBuilder.d.ts +60 -1
- package/dist/builders/DeliveryProofBuilder.d.ts.map +1 -1
- package/dist/builders/DeliveryProofBuilder.js +81 -5
- package/dist/builders/DeliveryProofBuilder.js.map +1 -1
- package/dist/builders/QuoteBuilder.d.ts +101 -0
- package/dist/builders/QuoteBuilder.d.ts.map +1 -1
- package/dist/builders/QuoteBuilder.js +120 -3
- package/dist/builders/QuoteBuilder.js.map +1 -1
- package/dist/builders/index.d.ts +4 -0
- package/dist/builders/index.d.ts.map +1 -1
- package/dist/builders/index.js +4 -0
- package/dist/builders/index.js.map +1 -1
- package/dist/cli/commands/balance.d.ts +13 -0
- package/dist/cli/commands/balance.d.ts.map +1 -0
- package/dist/cli/commands/balance.js +89 -0
- package/dist/cli/commands/balance.js.map +1 -0
- package/dist/cli/commands/batch.d.ts +24 -0
- package/dist/cli/commands/batch.d.ts.map +1 -0
- package/dist/cli/commands/batch.js +424 -0
- package/dist/cli/commands/batch.js.map +1 -0
- package/dist/cli/commands/config.d.ts +13 -0
- package/dist/cli/commands/config.d.ts.map +1 -0
- package/dist/cli/commands/config.js +192 -0
- package/dist/cli/commands/config.js.map +1 -0
- package/dist/cli/commands/init.d.ts +19 -0
- package/dist/cli/commands/init.d.ts.map +1 -0
- package/dist/cli/commands/init.js +143 -0
- package/dist/cli/commands/init.js.map +1 -0
- package/dist/cli/commands/mint.d.ts +13 -0
- package/dist/cli/commands/mint.d.ts.map +1 -0
- package/dist/cli/commands/mint.js +91 -0
- package/dist/cli/commands/mint.js.map +1 -0
- package/dist/cli/commands/pay.d.ts +18 -0
- package/dist/cli/commands/pay.d.ts.map +1 -0
- package/dist/cli/commands/pay.js +87 -0
- package/dist/cli/commands/pay.js.map +1 -0
- package/dist/cli/commands/simulate.d.ts +32 -0
- package/dist/cli/commands/simulate.d.ts.map +1 -0
- package/dist/cli/commands/simulate.js +290 -0
- package/dist/cli/commands/simulate.js.map +1 -0
- package/dist/cli/commands/time.d.ts +29 -0
- package/dist/cli/commands/time.d.ts.map +1 -0
- package/dist/cli/commands/time.js +252 -0
- package/dist/cli/commands/time.js.map +1 -0
- package/dist/cli/commands/tx.d.ts +16 -0
- package/dist/cli/commands/tx.d.ts.map +1 -0
- package/dist/cli/commands/tx.js +379 -0
- package/dist/cli/commands/tx.js.map +1 -0
- package/dist/cli/commands/watch.d.ts +20 -0
- package/dist/cli/commands/watch.d.ts.map +1 -0
- package/dist/cli/commands/watch.js +160 -0
- package/dist/cli/commands/watch.js.map +1 -0
- package/dist/cli/index.d.ts +17 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +104 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/utils/client.d.ts +70 -0
- package/dist/cli/utils/client.d.ts.map +1 -0
- package/dist/cli/utils/client.js +240 -0
- package/dist/cli/utils/client.js.map +1 -0
- package/dist/cli/utils/config.d.ts +91 -0
- package/dist/cli/utils/config.d.ts.map +1 -0
- package/dist/cli/utils/config.js +240 -0
- package/dist/cli/utils/config.js.map +1 -0
- package/dist/cli/utils/output.d.ts +174 -0
- package/dist/cli/utils/output.d.ts.map +1 -0
- package/dist/cli/utils/output.js +380 -0
- package/dist/cli/utils/output.js.map +1 -0
- package/dist/config/networks.d.ts +28 -0
- package/dist/config/networks.d.ts.map +1 -1
- package/dist/config/networks.js +60 -12
- package/dist/config/networks.js.map +1 -1
- package/dist/errors/index.d.ts +165 -2
- package/dist/errors/index.d.ts.map +1 -1
- package/dist/errors/index.js +260 -2
- package/dist/errors/index.js.map +1 -1
- package/dist/index.d.ts +61 -13
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +141 -36
- package/dist/index.js.map +1 -1
- package/dist/level0/Provider.d.ts +106 -0
- package/dist/level0/Provider.d.ts.map +1 -0
- package/dist/level0/Provider.js +10 -0
- package/dist/level0/Provider.js.map +1 -0
- package/dist/level0/ServiceDirectory.d.ts +74 -0
- package/dist/level0/ServiceDirectory.d.ts.map +1 -0
- package/dist/level0/ServiceDirectory.js +122 -0
- package/dist/level0/ServiceDirectory.js.map +1 -0
- package/dist/level0/index.d.ts +10 -0
- package/dist/level0/index.d.ts.map +1 -0
- package/dist/level0/index.js +15 -0
- package/dist/level0/index.js.map +1 -0
- package/dist/level0/provide.d.ts +51 -0
- package/dist/level0/provide.d.ts.map +1 -0
- package/dist/level0/provide.js +113 -0
- package/dist/level0/provide.js.map +1 -0
- package/dist/level0/request.d.ts +53 -0
- package/dist/level0/request.d.ts.map +1 -0
- package/dist/level0/request.js +462 -0
- package/dist/level0/request.js.map +1 -0
- package/dist/level1/Agent.d.ts +472 -0
- package/dist/level1/Agent.d.ts.map +1 -0
- package/dist/level1/Agent.js +1091 -0
- package/dist/level1/Agent.js.map +1 -0
- package/dist/level1/index.d.ts +10 -0
- package/dist/level1/index.d.ts.map +1 -0
- package/dist/level1/index.js +30 -0
- package/dist/level1/index.js.map +1 -0
- package/dist/level1/pricing/PriceCalculator.d.ts +62 -0
- package/dist/level1/pricing/PriceCalculator.d.ts.map +1 -0
- package/dist/level1/pricing/PriceCalculator.js +237 -0
- package/dist/level1/pricing/PriceCalculator.js.map +1 -0
- package/dist/level1/pricing/PricingStrategy.d.ts +179 -0
- package/dist/level1/pricing/PricingStrategy.d.ts.map +1 -0
- package/dist/level1/pricing/PricingStrategy.js +11 -0
- package/dist/level1/pricing/PricingStrategy.js.map +1 -0
- package/dist/level1/types/Job.d.ts +166 -0
- package/dist/level1/types/Job.d.ts.map +1 -0
- package/dist/level1/types/Job.js +11 -0
- package/dist/level1/types/Job.js.map +1 -0
- package/dist/level1/types/Options.d.ts +258 -0
- package/dist/level1/types/Options.d.ts.map +1 -0
- package/dist/level1/types/Options.js +8 -0
- package/dist/level1/types/Options.js.map +1 -0
- package/dist/level1/types/index.d.ts +8 -0
- package/dist/level1/types/index.d.ts.map +1 -0
- package/dist/level1/types/index.js +8 -0
- package/dist/level1/types/index.js.map +1 -0
- package/dist/protocol/ACTPKernel.d.ts +229 -2
- package/dist/protocol/ACTPKernel.d.ts.map +1 -1
- package/dist/protocol/ACTPKernel.js +367 -33
- package/dist/protocol/ACTPKernel.js.map +1 -1
- package/dist/protocol/AgentRegistry.d.ts +177 -0
- package/dist/protocol/AgentRegistry.d.ts.map +1 -0
- package/dist/protocol/AgentRegistry.js +449 -0
- package/dist/protocol/AgentRegistry.js.map +1 -0
- package/dist/protocol/DIDManager.d.ts +289 -0
- package/dist/protocol/DIDManager.d.ts.map +1 -0
- package/dist/protocol/DIDManager.js +481 -0
- package/dist/protocol/DIDManager.js.map +1 -0
- package/dist/protocol/DIDResolver.d.ts +236 -0
- package/dist/protocol/DIDResolver.d.ts.map +1 -0
- package/dist/protocol/DIDResolver.js +495 -0
- package/dist/protocol/DIDResolver.js.map +1 -0
- package/dist/protocol/EASHelper.d.ts +57 -2
- package/dist/protocol/EASHelper.d.ts.map +1 -1
- package/dist/protocol/EASHelper.js +230 -37
- package/dist/protocol/EASHelper.js.map +1 -1
- package/dist/protocol/EscrowVault.d.ts +93 -2
- package/dist/protocol/EscrowVault.d.ts.map +1 -1
- package/dist/protocol/EscrowVault.js +122 -33
- package/dist/protocol/EscrowVault.js.map +1 -1
- package/dist/protocol/EventMonitor.d.ts +45 -1
- package/dist/protocol/EventMonitor.d.ts.map +1 -1
- package/dist/protocol/EventMonitor.js +64 -8
- package/dist/protocol/EventMonitor.js.map +1 -1
- package/dist/protocol/MessageSigner.d.ts +116 -2
- package/dist/protocol/MessageSigner.d.ts.map +1 -1
- package/dist/protocol/MessageSigner.js +215 -9
- package/dist/protocol/MessageSigner.js.map +1 -1
- package/dist/protocol/ProofGenerator.d.ts +93 -0
- package/dist/protocol/ProofGenerator.d.ts.map +1 -1
- package/dist/protocol/ProofGenerator.js +194 -9
- package/dist/protocol/ProofGenerator.js.map +1 -1
- package/dist/protocol/QuoteBuilder.d.ts +8 -0
- package/dist/protocol/QuoteBuilder.d.ts.map +1 -1
- package/dist/protocol/QuoteBuilder.js +8 -0
- package/dist/protocol/QuoteBuilder.js.map +1 -1
- package/dist/runtime/BlockchainRuntime.d.ts +360 -0
- package/dist/runtime/BlockchainRuntime.d.ts.map +1 -0
- package/dist/runtime/BlockchainRuntime.js +767 -0
- package/dist/runtime/BlockchainRuntime.js.map +1 -0
- package/dist/runtime/IACTPRuntime.d.ts +271 -0
- package/dist/runtime/IACTPRuntime.d.ts.map +1 -0
- package/dist/runtime/IACTPRuntime.js +15 -0
- package/dist/runtime/IACTPRuntime.js.map +1 -0
- package/dist/runtime/MockRuntime.d.ts +445 -0
- package/dist/runtime/MockRuntime.d.ts.map +1 -0
- package/dist/runtime/MockRuntime.js +1065 -0
- package/dist/runtime/MockRuntime.js.map +1 -0
- package/dist/runtime/MockStateManager.d.ts +233 -0
- package/dist/runtime/MockStateManager.d.ts.map +1 -0
- package/dist/runtime/MockStateManager.js +533 -0
- package/dist/runtime/MockStateManager.js.map +1 -0
- package/dist/runtime/index.d.ts +14 -0
- package/dist/runtime/index.d.ts.map +1 -0
- package/dist/runtime/index.js +42 -0
- package/dist/runtime/index.js.map +1 -0
- package/dist/runtime/types/MockState.d.ts +167 -0
- package/dist/runtime/types/MockState.d.ts.map +1 -0
- package/dist/runtime/types/MockState.js +43 -0
- package/dist/runtime/types/MockState.js.map +1 -0
- package/dist/types/agent.d.ts +76 -0
- package/dist/types/agent.d.ts.map +1 -0
- package/dist/types/agent.js +8 -0
- package/dist/types/agent.js.map +1 -0
- package/dist/types/did.d.ts +192 -0
- package/dist/types/did.d.ts.map +1 -0
- package/dist/types/did.js +38 -0
- package/dist/types/did.js.map +1 -0
- package/dist/types/eip712.d.ts +34 -0
- package/dist/types/eip712.d.ts.map +1 -1
- package/dist/types/eip712.js +31 -5
- package/dist/types/eip712.js.map +1 -1
- package/dist/types/escrow.d.ts +17 -10
- package/dist/types/escrow.d.ts.map +1 -1
- package/dist/types/index.d.ts +5 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +8 -0
- package/dist/types/index.js.map +1 -1
- package/dist/types/message.d.ts +32 -0
- package/dist/types/message.d.ts.map +1 -1
- package/dist/types/message.js +4 -0
- package/dist/types/message.js.map +1 -1
- package/dist/types/state.d.ts +28 -0
- package/dist/types/state.d.ts.map +1 -1
- package/dist/types/state.js +37 -6
- package/dist/types/state.js.map +1 -1
- package/dist/types/transaction.d.ts +17 -0
- package/dist/types/transaction.d.ts.map +1 -1
- package/dist/utils/ErrorRecoveryGuide.d.ts +125 -0
- package/dist/utils/ErrorRecoveryGuide.d.ts.map +1 -0
- package/dist/utils/ErrorRecoveryGuide.js +579 -0
- package/dist/utils/ErrorRecoveryGuide.js.map +1 -0
- package/dist/utils/Helpers.d.ts +453 -0
- package/dist/utils/Helpers.d.ts.map +1 -0
- package/dist/utils/Helpers.js +623 -0
- package/dist/utils/Helpers.js.map +1 -0
- package/dist/utils/IPFSClient.d.ts +113 -0
- package/dist/utils/IPFSClient.d.ts.map +1 -1
- package/dist/utils/IPFSClient.js +128 -7
- package/dist/utils/IPFSClient.js.map +1 -1
- package/dist/utils/Logger.d.ts +195 -0
- package/dist/utils/Logger.d.ts.map +1 -0
- package/dist/utils/Logger.js +382 -0
- package/dist/utils/Logger.js.map +1 -0
- package/dist/utils/NonceManager.d.ts +234 -1
- package/dist/utils/NonceManager.d.ts.map +1 -1
- package/dist/utils/NonceManager.js +372 -7
- package/dist/utils/NonceManager.js.map +1 -1
- package/dist/utils/RateLimiter.d.ts +253 -0
- package/dist/utils/RateLimiter.d.ts.map +1 -0
- package/dist/utils/RateLimiter.js +424 -0
- package/dist/utils/RateLimiter.js.map +1 -0
- package/dist/utils/ReceivedNonceTracker.d.ts +175 -0
- package/dist/utils/ReceivedNonceTracker.d.ts.map +1 -1
- package/dist/utils/ReceivedNonceTracker.js +261 -5
- package/dist/utils/ReceivedNonceTracker.js.map +1 -1
- package/dist/utils/SDKLifecycle.d.ts +156 -0
- package/dist/utils/SDKLifecycle.d.ts.map +1 -0
- package/dist/utils/SDKLifecycle.js +347 -0
- package/dist/utils/SDKLifecycle.js.map +1 -0
- package/dist/utils/SecureNonce.d.ts +57 -0
- package/dist/utils/SecureNonce.d.ts.map +1 -0
- package/dist/utils/SecureNonce.js +80 -0
- package/dist/utils/SecureNonce.js.map +1 -0
- package/dist/utils/Semaphore.d.ts +123 -0
- package/dist/utils/Semaphore.d.ts.map +1 -0
- package/dist/utils/Semaphore.js +247 -0
- package/dist/utils/Semaphore.js.map +1 -0
- package/dist/utils/UsedAttestationTracker.d.ts +167 -0
- package/dist/utils/UsedAttestationTracker.d.ts.map +1 -0
- package/dist/utils/UsedAttestationTracker.js +309 -0
- package/dist/utils/UsedAttestationTracker.js.map +1 -0
- package/dist/utils/canonicalJson.d.ts +22 -0
- package/dist/utils/canonicalJson.d.ts.map +1 -1
- package/dist/utils/canonicalJson.js +26 -3
- package/dist/utils/canonicalJson.js.map +1 -1
- package/dist/utils/computeTypeHash.d.ts +14 -0
- package/dist/utils/computeTypeHash.d.ts.map +1 -1
- package/dist/utils/computeTypeHash.js +19 -2
- package/dist/utils/computeTypeHash.js.map +1 -1
- package/dist/utils/fsSafe.d.ts +14 -0
- package/dist/utils/fsSafe.d.ts.map +1 -0
- package/dist/utils/fsSafe.js +89 -0
- package/dist/utils/fsSafe.js.map +1 -0
- package/dist/utils/index.d.ts +15 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +51 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/security.d.ts +147 -0
- package/dist/utils/security.d.ts.map +1 -0
- package/dist/utils/security.js +391 -0
- package/dist/utils/security.js.map +1 -0
- package/dist/utils/validation.d.ts +40 -0
- package/dist/utils/validation.d.ts.map +1 -1
- package/dist/utils/validation.js +184 -7
- package/dist/utils/validation.js.map +1 -1
- package/package.json +54 -37
- package/src/ACTPClient.ts +692 -178
- package/src/abi/AgentRegistry.json +782 -0
- package/src/abi/EscrowVault.json +106 -38
- package/src/abi/IdentityRegistry.json +316 -0
- package/src/adapters/BaseAdapter.ts +473 -0
- package/src/adapters/BeginnerAdapter.ts +232 -0
- package/src/adapters/IntermediateAdapter.ts +316 -0
- package/src/adapters/index.ts +25 -0
- package/src/builders/DeliveryProofBuilder.ts +3 -2
- package/src/cli/commands/balance.ts +110 -0
- package/src/cli/commands/batch.ts +487 -0
- package/src/cli/commands/config.ts +231 -0
- package/src/cli/commands/init.ts +161 -0
- package/src/cli/commands/mint.ts +116 -0
- package/src/cli/commands/pay.ts +113 -0
- package/src/cli/commands/simulate.ts +345 -0
- package/src/cli/commands/time.ts +303 -0
- package/src/cli/commands/tx.ts +448 -0
- package/src/cli/commands/watch.ts +211 -0
- package/src/cli/index.ts +116 -0
- package/src/cli/utils/client.ts +249 -0
- package/src/cli/utils/config.ts +282 -0
- package/src/cli/utils/output.ts +465 -0
- package/src/config/networks.ts +32 -9
- package/src/errors/index.ts +298 -1
- package/src/index.ts +207 -71
- package/src/level0/Provider.ts +117 -0
- package/src/level0/ServiceDirectory.ts +131 -0
- package/src/level0/index.ts +10 -0
- package/src/level0/provide.ts +131 -0
- package/src/level0/request.ts +494 -0
- package/src/level1/Agent.ts +1432 -0
- package/src/level1/index.ts +10 -0
- package/src/level1/pricing/PriceCalculator.ts +255 -0
- package/src/level1/pricing/PricingStrategy.ts +198 -0
- package/src/level1/types/Job.ts +179 -0
- package/src/level1/types/Options.ts +291 -0
- package/src/level1/types/index.ts +8 -0
- package/src/protocol/ACTPKernel.ts +175 -23
- package/src/protocol/AgentRegistry.ts +559 -0
- package/src/protocol/DIDManager.ts +629 -0
- package/src/protocol/DIDResolver.ts +554 -0
- package/src/protocol/EASHelper.ts +230 -46
- package/src/protocol/EscrowVault.ts +68 -50
- package/src/protocol/EventMonitor.ts +44 -15
- package/src/protocol/MessageSigner.ts +193 -13
- package/src/protocol/ProofGenerator.ts +223 -4
- package/src/runtime/BlockchainRuntime.ts +993 -0
- package/src/runtime/IACTPRuntime.ts +284 -0
- package/src/runtime/MockRuntime.ts +1244 -0
- package/src/runtime/MockStateManager.ts +576 -0
- package/src/runtime/index.ts +25 -0
- package/src/runtime/types/MockState.ts +227 -0
- package/src/types/agent.ts +79 -0
- package/src/types/did.ts +223 -0
- package/src/types/escrow.ts +12 -11
- package/src/types/index.ts +5 -1
- package/src/types/state.ts +12 -3
- package/src/types/transaction.ts +4 -1
- package/src/utils/ErrorRecoveryGuide.ts +675 -0
- package/src/utils/Helpers.ts +688 -0
- package/src/utils/IPFSClient.ts +122 -5
- package/src/utils/Logger.ts +484 -0
- package/src/utils/NonceManager.ts +305 -8
- package/src/utils/RateLimiter.ts +534 -0
- package/src/utils/ReceivedNonceTracker.ts +170 -0
- package/src/utils/SDKLifecycle.ts +416 -0
- package/src/utils/SecureNonce.ts +78 -0
- package/src/utils/Semaphore.ts +276 -0
- package/src/utils/UsedAttestationTracker.ts +387 -0
- package/src/utils/fsSafe.ts +75 -0
- package/src/utils/index.ts +80 -0
- package/src/utils/security.ts +418 -0
- package/src/utils/validation.ts +164 -0
- package/src/__tests__/ProofGenerator.test.ts +0 -124
- package/src/__tests__/QuoteBuilder.test.ts +0 -516
- package/src/__tests__/StateMachine.test.ts +0 -82
- package/src/__tests__/builders/DeliveryProofBuilder.test.ts +0 -581
- package/src/__tests__/integration/ACTPClient.test.ts +0 -263
- package/src/__tests__/integration.test.ts +0 -289
- package/src/__tests__/protocol/EASHelper.test.ts +0 -472
- package/src/__tests__/protocol/EventMonitor.test.ts +0 -382
- package/src/__tests__/security/ACTPKernel.security.test.ts +0 -1167
- package/src/__tests__/security/EscrowVault.security.test.ts +0 -570
- package/src/__tests__/security/MessageSigner.security.test.ts +0 -286
- package/src/__tests__/security/NonceReplay.security.test.ts +0 -501
- package/src/__tests__/security/validation.security.test.ts +0 -376
- package/src/__tests__/utils/IPFSClient.test.ts +0 -262
- package/src/__tests__/utils/NonceManager.test.ts +0 -205
- package/src/__tests__/utils/canonicalJson.test.ts +0 -153
|
@@ -1,35 +1,210 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ReceivedNonceTracker - Replay Attack Prevention for Message Receivers
|
|
3
|
+
*
|
|
4
|
+
* This utility tracks nonces of received messages to prevent replay attacks.
|
|
5
|
+
* It works in conjunction with NonceManager (for senders) but serves the receiver side.
|
|
6
|
+
*
|
|
7
|
+
* Reference: V4 Security Vulnerability (EIP-712 Replay Attack)
|
|
8
|
+
*
|
|
9
|
+
* Usage Pattern:
|
|
10
|
+
* - Sender: Uses NonceManager to generate monotonically increasing nonces
|
|
11
|
+
* - Receiver: Uses ReceivedNonceTracker to validate and track received nonces
|
|
12
|
+
*
|
|
13
|
+
* Security Properties:
|
|
14
|
+
* 1. Nonces must be monotonically increasing per sender + message type
|
|
15
|
+
* 2. Duplicate nonces are rejected (replay attack prevention)
|
|
16
|
+
* 3. Nonces that are lower than the highest seen are rejected (old replay prevention)
|
|
17
|
+
*
|
|
18
|
+
* ⚠️ WARNING: In-memory tracking only. For production:
|
|
19
|
+
* - Use persistent storage (Redis, PostgreSQL, etc.)
|
|
20
|
+
* - Implement nonce recovery from transaction history
|
|
21
|
+
* - Consider nonce expiry for long-running processes
|
|
22
|
+
*/
|
|
23
|
+
/**
|
|
24
|
+
* Nonce validation result
|
|
25
|
+
*/
|
|
1
26
|
export interface NonceValidationResult {
|
|
2
27
|
valid: boolean;
|
|
3
28
|
reason?: string;
|
|
4
29
|
expectedMinimum?: string;
|
|
5
30
|
receivedNonce?: string;
|
|
6
31
|
}
|
|
32
|
+
/**
|
|
33
|
+
* Interface for tracking received nonces
|
|
34
|
+
*/
|
|
7
35
|
export interface IReceivedNonceTracker {
|
|
36
|
+
/**
|
|
37
|
+
* Validate and record a received nonce
|
|
38
|
+
* @param sender - Sender DID (e.g., "did:ethr:0x...")
|
|
39
|
+
* @param messageType - Message type (e.g., "agirails.delivery.v1")
|
|
40
|
+
* @param nonce - Nonce value (bytes32 format: "0x...")
|
|
41
|
+
* @returns Validation result
|
|
42
|
+
*/
|
|
8
43
|
validateAndRecord(sender: string, messageType: string, nonce: string): NonceValidationResult;
|
|
44
|
+
/**
|
|
45
|
+
* Check if a nonce has been used (without recording)
|
|
46
|
+
* @param sender - Sender DID
|
|
47
|
+
* @param messageType - Message type
|
|
48
|
+
* @param nonce - Nonce value (bytes32 format)
|
|
49
|
+
* @returns true if nonce was already used
|
|
50
|
+
*/
|
|
9
51
|
hasBeenUsed(sender: string, messageType: string, nonce: string): boolean;
|
|
52
|
+
/**
|
|
53
|
+
* Get highest nonce seen for sender + message type
|
|
54
|
+
* @param sender - Sender DID
|
|
55
|
+
* @param messageType - Message type
|
|
56
|
+
* @returns Highest nonce (bytes32 format) or null if none seen
|
|
57
|
+
*/
|
|
10
58
|
getHighestNonce(sender: string, messageType: string): string | null;
|
|
59
|
+
/**
|
|
60
|
+
* Reset tracking for a specific sender + message type
|
|
61
|
+
* @param sender - Sender DID
|
|
62
|
+
* @param messageType - Message type
|
|
63
|
+
*/
|
|
11
64
|
reset(sender: string, messageType: string): void;
|
|
65
|
+
/**
|
|
66
|
+
* Clear all tracked nonces
|
|
67
|
+
*/
|
|
12
68
|
clearAll(): void;
|
|
13
69
|
}
|
|
70
|
+
/**
|
|
71
|
+
* In-Memory Received Nonce Tracker
|
|
72
|
+
*
|
|
73
|
+
* Strategy: Track highest nonce seen per sender + message type
|
|
74
|
+
* - Accept nonces that are strictly greater than the highest seen
|
|
75
|
+
* - Reject nonces that are <= highest seen (replay attack)
|
|
76
|
+
*
|
|
77
|
+
* Trade-off:
|
|
78
|
+
* - Memory efficient (one value per sender + type)
|
|
79
|
+
* - Requires ordered nonce sequences
|
|
80
|
+
* - Cannot skip nonces (nonce gaps are rejected)
|
|
81
|
+
*/
|
|
14
82
|
export declare class InMemoryReceivedNonceTracker implements IReceivedNonceTracker {
|
|
15
83
|
private highestNonces;
|
|
84
|
+
/**
|
|
85
|
+
* Validate and record a received nonce
|
|
86
|
+
*/
|
|
16
87
|
validateAndRecord(sender: string, messageType: string, nonce: string): NonceValidationResult;
|
|
88
|
+
/**
|
|
89
|
+
* Check if a nonce has been used (non-mutating)
|
|
90
|
+
*/
|
|
17
91
|
hasBeenUsed(sender: string, messageType: string, nonce: string): boolean;
|
|
92
|
+
/**
|
|
93
|
+
* Get highest nonce seen
|
|
94
|
+
*/
|
|
18
95
|
getHighestNonce(sender: string, messageType: string): string | null;
|
|
96
|
+
/**
|
|
97
|
+
* Reset tracking for sender + message type
|
|
98
|
+
*/
|
|
19
99
|
reset(sender: string, messageType: string): void;
|
|
100
|
+
/**
|
|
101
|
+
* Clear all tracked nonces
|
|
102
|
+
*/
|
|
20
103
|
clearAll(): void;
|
|
104
|
+
/**
|
|
105
|
+
* Convert BigInt to bytes32 hex string
|
|
106
|
+
*/
|
|
21
107
|
private bigintToBytes32;
|
|
108
|
+
/**
|
|
109
|
+
* Get all nonces (for debugging/persistence)
|
|
110
|
+
*/
|
|
22
111
|
getAllNonces(): Record<string, Record<string, string>>;
|
|
23
112
|
}
|
|
113
|
+
/**
|
|
114
|
+
* Set-Based Received Nonce Tracker
|
|
115
|
+
*
|
|
116
|
+
* Strategy: Track exact set of used nonces per sender + message type
|
|
117
|
+
* - Accept nonces that haven't been seen before
|
|
118
|
+
* - Reject duplicate nonces (replay attack)
|
|
119
|
+
* - Allows non-sequential nonces (nonce gaps are OK)
|
|
120
|
+
*
|
|
121
|
+
* SECURITY FIX (NEW-H-2): Max size enforcement to prevent memory exhaustion
|
|
122
|
+
* SECURITY FIX (HIGH-2): Global total entries limit to prevent DoS via many sender combinations
|
|
123
|
+
* SECURITY FIX (H-2): Rate limiting per sender to prevent flood attacks
|
|
124
|
+
*
|
|
125
|
+
* Trade-off:
|
|
126
|
+
* - Higher memory usage (stores every nonce)
|
|
127
|
+
* - More flexible (allows out-of-order delivery)
|
|
128
|
+
* - Requires periodic cleanup to prevent unbounded growth
|
|
129
|
+
*/
|
|
24
130
|
export declare class SetBasedReceivedNonceTracker implements IReceivedNonceTracker {
|
|
25
131
|
private usedNonces;
|
|
132
|
+
private readonly maxSizePerType;
|
|
133
|
+
private readonly maxTotalEntries;
|
|
134
|
+
private totalEntries;
|
|
135
|
+
private rateLimitState;
|
|
136
|
+
private readonly maxNoncesPerMinute;
|
|
137
|
+
private readonly rateLimitWindowMs;
|
|
138
|
+
/**
|
|
139
|
+
* Create set-based tracker with optional max size
|
|
140
|
+
* @param maxSizePerType - Maximum nonces per sender+messageType (default: 10,000)
|
|
141
|
+
* @param maxTotalEntries - Maximum total nonces across all combinations (default: 100,000)
|
|
142
|
+
* @param maxNoncesPerMinute - Maximum nonces per sender per minute (default: 100)
|
|
143
|
+
*/
|
|
144
|
+
constructor(maxSizePerType?: number, maxTotalEntries?: number, maxNoncesPerMinute?: number);
|
|
145
|
+
/**
|
|
146
|
+
* SECURITY FIX (H-2): Check rate limit for sender
|
|
147
|
+
* @param sender - Sender DID
|
|
148
|
+
* @returns true if rate limit exceeded
|
|
149
|
+
*/
|
|
150
|
+
private checkRateLimit;
|
|
151
|
+
/**
|
|
152
|
+
* SECURITY FIX (H-2): Periodic cleanup of rate limit state
|
|
153
|
+
* Removes expired rate limit entries (older than 5 minutes)
|
|
154
|
+
*/
|
|
155
|
+
private cleanupRateLimitState;
|
|
156
|
+
/**
|
|
157
|
+
* Validate and record a received nonce
|
|
158
|
+
*
|
|
159
|
+
* SECURITY FIX (NEW-H-2): Automatic cleanup when max size reached
|
|
160
|
+
* SECURITY FIX (HIGH-2): Global limit check to prevent DoS
|
|
161
|
+
* SECURITY FIX (H-2): Rate limiting per sender (max 100 nonces/minute)
|
|
162
|
+
*/
|
|
26
163
|
validateAndRecord(sender: string, messageType: string, nonce: string): NonceValidationResult;
|
|
164
|
+
/**
|
|
165
|
+
* Get number of sender+messageType combinations (for monitoring)
|
|
166
|
+
* SECURITY FIX (HIGH-2): Monitoring method
|
|
167
|
+
*/
|
|
168
|
+
private getCombinationCount;
|
|
169
|
+
/**
|
|
170
|
+
* Get memory usage statistics
|
|
171
|
+
* SECURITY FIX (HIGH-2): Monitoring method for DoS detection
|
|
172
|
+
*/
|
|
173
|
+
getMemoryUsage(): {
|
|
174
|
+
totalEntries: number;
|
|
175
|
+
combinations: number;
|
|
176
|
+
maxTotalEntries: number;
|
|
177
|
+
};
|
|
178
|
+
/**
|
|
179
|
+
* Check if a nonce has been used
|
|
180
|
+
*/
|
|
27
181
|
hasBeenUsed(sender: string, messageType: string, nonce: string): boolean;
|
|
182
|
+
/**
|
|
183
|
+
* Get highest nonce seen (for this strategy, compute from set)
|
|
184
|
+
*/
|
|
28
185
|
getHighestNonce(sender: string, messageType: string): string | null;
|
|
186
|
+
/**
|
|
187
|
+
* Reset tracking for sender + message type
|
|
188
|
+
*/
|
|
29
189
|
reset(sender: string, messageType: string): void;
|
|
190
|
+
/**
|
|
191
|
+
* Clear all tracked nonces
|
|
192
|
+
*/
|
|
30
193
|
clearAll(): void;
|
|
194
|
+
/**
|
|
195
|
+
* Get nonce count for sender + message type (for monitoring)
|
|
196
|
+
*/
|
|
31
197
|
getNonceCount(sender: string, messageType: string): number;
|
|
198
|
+
/**
|
|
199
|
+
* Cleanup old nonces (keep only last N)
|
|
200
|
+
* This prevents unbounded memory growth
|
|
201
|
+
*/
|
|
32
202
|
cleanup(sender: string, messageType: string, keepLast?: number): void;
|
|
33
203
|
}
|
|
204
|
+
/**
|
|
205
|
+
* Factory function to create a nonce tracker
|
|
206
|
+
* @param strategy - 'memory-efficient' (highest nonce) or 'set-based' (all nonces)
|
|
207
|
+
* @returns IReceivedNonceTracker instance
|
|
208
|
+
*/
|
|
34
209
|
export declare function createReceivedNonceTracker(strategy?: 'memory-efficient' | 'set-based'): IReceivedNonceTracker;
|
|
35
210
|
//# sourceMappingURL=ReceivedNonceTracker.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ReceivedNonceTracker.d.ts","sourceRoot":"","sources":["../../src/utils/ReceivedNonceTracker.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ReceivedNonceTracker.d.ts","sourceRoot":"","sources":["../../src/utils/ReceivedNonceTracker.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,12 +1,50 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* ReceivedNonceTracker - Replay Attack Prevention for Message Receivers
|
|
4
|
+
*
|
|
5
|
+
* This utility tracks nonces of received messages to prevent replay attacks.
|
|
6
|
+
* It works in conjunction with NonceManager (for senders) but serves the receiver side.
|
|
7
|
+
*
|
|
8
|
+
* Reference: V4 Security Vulnerability (EIP-712 Replay Attack)
|
|
9
|
+
*
|
|
10
|
+
* Usage Pattern:
|
|
11
|
+
* - Sender: Uses NonceManager to generate monotonically increasing nonces
|
|
12
|
+
* - Receiver: Uses ReceivedNonceTracker to validate and track received nonces
|
|
13
|
+
*
|
|
14
|
+
* Security Properties:
|
|
15
|
+
* 1. Nonces must be monotonically increasing per sender + message type
|
|
16
|
+
* 2. Duplicate nonces are rejected (replay attack prevention)
|
|
17
|
+
* 3. Nonces that are lower than the highest seen are rejected (old replay prevention)
|
|
18
|
+
*
|
|
19
|
+
* ⚠️ WARNING: In-memory tracking only. For production:
|
|
20
|
+
* - Use persistent storage (Redis, PostgreSQL, etc.)
|
|
21
|
+
* - Implement nonce recovery from transaction history
|
|
22
|
+
* - Consider nonce expiry for long-running processes
|
|
23
|
+
*/
|
|
2
24
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.SetBasedReceivedNonceTracker = exports.InMemoryReceivedNonceTracker = void 0;
|
|
4
|
-
|
|
25
|
+
exports.createReceivedNonceTracker = exports.SetBasedReceivedNonceTracker = exports.InMemoryReceivedNonceTracker = void 0;
|
|
26
|
+
/**
|
|
27
|
+
* In-Memory Received Nonce Tracker
|
|
28
|
+
*
|
|
29
|
+
* Strategy: Track highest nonce seen per sender + message type
|
|
30
|
+
* - Accept nonces that are strictly greater than the highest seen
|
|
31
|
+
* - Reject nonces that are <= highest seen (replay attack)
|
|
32
|
+
*
|
|
33
|
+
* Trade-off:
|
|
34
|
+
* - Memory efficient (one value per sender + type)
|
|
35
|
+
* - Requires ordered nonce sequences
|
|
36
|
+
* - Cannot skip nonces (nonce gaps are rejected)
|
|
37
|
+
*/
|
|
5
38
|
class InMemoryReceivedNonceTracker {
|
|
6
39
|
constructor() {
|
|
40
|
+
// Map: sender -> messageType -> highest nonce (as BigInt for comparison)
|
|
7
41
|
this.highestNonces = new Map();
|
|
8
42
|
}
|
|
43
|
+
/**
|
|
44
|
+
* Validate and record a received nonce
|
|
45
|
+
*/
|
|
9
46
|
validateAndRecord(sender, messageType, nonce) {
|
|
47
|
+
// Validate nonce format (must be bytes32: 0x + 64 hex chars)
|
|
10
48
|
if (!/^0x[a-fA-F0-9]{64}$/.test(nonce)) {
|
|
11
49
|
return {
|
|
12
50
|
valid: false,
|
|
@@ -14,17 +52,22 @@ class InMemoryReceivedNonceTracker {
|
|
|
14
52
|
receivedNonce: nonce
|
|
15
53
|
};
|
|
16
54
|
}
|
|
55
|
+
// Convert nonce to BigInt for comparison
|
|
17
56
|
const nonceValue = BigInt(nonce);
|
|
57
|
+
// Get sender's nonce map
|
|
18
58
|
let senderNonces = this.highestNonces.get(sender);
|
|
19
59
|
if (!senderNonces) {
|
|
20
60
|
senderNonces = new Map();
|
|
21
61
|
this.highestNonces.set(sender, senderNonces);
|
|
22
62
|
}
|
|
63
|
+
// Get highest nonce for this message type
|
|
23
64
|
const highestNonce = senderNonces.get(messageType);
|
|
24
65
|
if (highestNonce === undefined) {
|
|
66
|
+
// First message from this sender for this type
|
|
25
67
|
senderNonces.set(messageType, nonceValue);
|
|
26
68
|
return { valid: true };
|
|
27
69
|
}
|
|
70
|
+
// Nonce must be strictly greater than highest seen
|
|
28
71
|
if (nonceValue <= highestNonce) {
|
|
29
72
|
const expectedMinimum = '0x' + (highestNonce + BigInt(1)).toString(16).padStart(64, '0');
|
|
30
73
|
return {
|
|
@@ -34,21 +77,29 @@ class InMemoryReceivedNonceTracker {
|
|
|
34
77
|
receivedNonce: nonce
|
|
35
78
|
};
|
|
36
79
|
}
|
|
80
|
+
// Valid nonce - record it
|
|
37
81
|
senderNonces.set(messageType, nonceValue);
|
|
38
82
|
return { valid: true };
|
|
39
83
|
}
|
|
84
|
+
/**
|
|
85
|
+
* Check if a nonce has been used (non-mutating)
|
|
86
|
+
*/
|
|
40
87
|
hasBeenUsed(sender, messageType, nonce) {
|
|
41
88
|
const nonceValue = BigInt(nonce);
|
|
42
89
|
const senderNonces = this.highestNonces.get(sender);
|
|
43
90
|
if (!senderNonces) {
|
|
44
|
-
return false;
|
|
91
|
+
return false; // No nonces seen from this sender
|
|
45
92
|
}
|
|
46
93
|
const highestNonce = senderNonces.get(messageType);
|
|
47
94
|
if (highestNonce === undefined) {
|
|
48
|
-
return false;
|
|
95
|
+
return false; // No nonces seen for this message type
|
|
49
96
|
}
|
|
97
|
+
// If the provided nonce is <= highest seen, it's been "used"
|
|
50
98
|
return nonceValue <= highestNonce;
|
|
51
99
|
}
|
|
100
|
+
/**
|
|
101
|
+
* Get highest nonce seen
|
|
102
|
+
*/
|
|
52
103
|
getHighestNonce(sender, messageType) {
|
|
53
104
|
const senderNonces = this.highestNonces.get(sender);
|
|
54
105
|
if (!senderNonces) {
|
|
@@ -60,21 +111,34 @@ class InMemoryReceivedNonceTracker {
|
|
|
60
111
|
}
|
|
61
112
|
return this.bigintToBytes32(highestNonce);
|
|
62
113
|
}
|
|
114
|
+
/**
|
|
115
|
+
* Reset tracking for sender + message type
|
|
116
|
+
*/
|
|
63
117
|
reset(sender, messageType) {
|
|
64
118
|
const senderNonces = this.highestNonces.get(sender);
|
|
65
119
|
if (senderNonces) {
|
|
66
120
|
senderNonces.delete(messageType);
|
|
121
|
+
// Clean up sender map if empty
|
|
67
122
|
if (senderNonces.size === 0) {
|
|
68
123
|
this.highestNonces.delete(sender);
|
|
69
124
|
}
|
|
70
125
|
}
|
|
71
126
|
}
|
|
127
|
+
/**
|
|
128
|
+
* Clear all tracked nonces
|
|
129
|
+
*/
|
|
72
130
|
clearAll() {
|
|
73
131
|
this.highestNonces.clear();
|
|
74
132
|
}
|
|
133
|
+
/**
|
|
134
|
+
* Convert BigInt to bytes32 hex string
|
|
135
|
+
*/
|
|
75
136
|
bigintToBytes32(value) {
|
|
76
137
|
return '0x' + value.toString(16).padStart(64, '0');
|
|
77
138
|
}
|
|
139
|
+
/**
|
|
140
|
+
* Get all nonces (for debugging/persistence)
|
|
141
|
+
*/
|
|
78
142
|
getAllNonces() {
|
|
79
143
|
const result = {};
|
|
80
144
|
this.highestNonces.forEach((senderNonces, sender) => {
|
|
@@ -87,11 +151,97 @@ class InMemoryReceivedNonceTracker {
|
|
|
87
151
|
}
|
|
88
152
|
}
|
|
89
153
|
exports.InMemoryReceivedNonceTracker = InMemoryReceivedNonceTracker;
|
|
154
|
+
/**
|
|
155
|
+
* Set-Based Received Nonce Tracker
|
|
156
|
+
*
|
|
157
|
+
* Strategy: Track exact set of used nonces per sender + message type
|
|
158
|
+
* - Accept nonces that haven't been seen before
|
|
159
|
+
* - Reject duplicate nonces (replay attack)
|
|
160
|
+
* - Allows non-sequential nonces (nonce gaps are OK)
|
|
161
|
+
*
|
|
162
|
+
* SECURITY FIX (NEW-H-2): Max size enforcement to prevent memory exhaustion
|
|
163
|
+
* SECURITY FIX (HIGH-2): Global total entries limit to prevent DoS via many sender combinations
|
|
164
|
+
* SECURITY FIX (H-2): Rate limiting per sender to prevent flood attacks
|
|
165
|
+
*
|
|
166
|
+
* Trade-off:
|
|
167
|
+
* - Higher memory usage (stores every nonce)
|
|
168
|
+
* - More flexible (allows out-of-order delivery)
|
|
169
|
+
* - Requires periodic cleanup to prevent unbounded growth
|
|
170
|
+
*/
|
|
90
171
|
class SetBasedReceivedNonceTracker {
|
|
91
|
-
|
|
172
|
+
/**
|
|
173
|
+
* Create set-based tracker with optional max size
|
|
174
|
+
* @param maxSizePerType - Maximum nonces per sender+messageType (default: 10,000)
|
|
175
|
+
* @param maxTotalEntries - Maximum total nonces across all combinations (default: 100,000)
|
|
176
|
+
* @param maxNoncesPerMinute - Maximum nonces per sender per minute (default: 100)
|
|
177
|
+
*/
|
|
178
|
+
constructor(maxSizePerType = 10000, maxTotalEntries = 100000, maxNoncesPerMinute = 100) {
|
|
179
|
+
// Map: sender -> messageType -> Set of used nonces
|
|
92
180
|
this.usedNonces = new Map();
|
|
181
|
+
this.totalEntries = 0;
|
|
182
|
+
// SECURITY FIX (H-2): Rate limiting per sender
|
|
183
|
+
// Map: sender -> { count: number, windowStart: number }
|
|
184
|
+
this.rateLimitState = new Map();
|
|
185
|
+
this.rateLimitWindowMs = 60000; // 1 minute window
|
|
186
|
+
if (maxSizePerType <= 0) {
|
|
187
|
+
throw new Error('maxSizePerType must be positive');
|
|
188
|
+
}
|
|
189
|
+
if (maxTotalEntries <= 0) {
|
|
190
|
+
throw new Error('maxTotalEntries must be positive');
|
|
191
|
+
}
|
|
192
|
+
if (maxNoncesPerMinute <= 0) {
|
|
193
|
+
throw new Error('maxNoncesPerMinute must be positive');
|
|
194
|
+
}
|
|
195
|
+
this.maxSizePerType = maxSizePerType;
|
|
196
|
+
this.maxTotalEntries = maxTotalEntries;
|
|
197
|
+
this.maxNoncesPerMinute = maxNoncesPerMinute;
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* SECURITY FIX (H-2): Check rate limit for sender
|
|
201
|
+
* @param sender - Sender DID
|
|
202
|
+
* @returns true if rate limit exceeded
|
|
203
|
+
*/
|
|
204
|
+
checkRateLimit(sender) {
|
|
205
|
+
const now = Date.now();
|
|
206
|
+
const state = this.rateLimitState.get(sender);
|
|
207
|
+
if (!state) {
|
|
208
|
+
// First nonce from this sender
|
|
209
|
+
this.rateLimitState.set(sender, { count: 1, windowStart: now });
|
|
210
|
+
return false; // Not rate limited
|
|
211
|
+
}
|
|
212
|
+
// Check if window expired (reset counter)
|
|
213
|
+
if (now - state.windowStart >= this.rateLimitWindowMs) {
|
|
214
|
+
state.count = 1;
|
|
215
|
+
state.windowStart = now;
|
|
216
|
+
return false; // Not rate limited
|
|
217
|
+
}
|
|
218
|
+
// Increment counter
|
|
219
|
+
state.count++;
|
|
220
|
+
// Check if rate limit exceeded
|
|
221
|
+
return state.count > this.maxNoncesPerMinute;
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* SECURITY FIX (H-2): Periodic cleanup of rate limit state
|
|
225
|
+
* Removes expired rate limit entries (older than 5 minutes)
|
|
226
|
+
*/
|
|
227
|
+
cleanupRateLimitState() {
|
|
228
|
+
const now = Date.now();
|
|
229
|
+
const expiryThreshold = 5 * 60 * 1000; // 5 minutes
|
|
230
|
+
for (const [sender, state] of this.rateLimitState.entries()) {
|
|
231
|
+
if (now - state.windowStart > expiryThreshold) {
|
|
232
|
+
this.rateLimitState.delete(sender);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
93
235
|
}
|
|
236
|
+
/**
|
|
237
|
+
* Validate and record a received nonce
|
|
238
|
+
*
|
|
239
|
+
* SECURITY FIX (NEW-H-2): Automatic cleanup when max size reached
|
|
240
|
+
* SECURITY FIX (HIGH-2): Global limit check to prevent DoS
|
|
241
|
+
* SECURITY FIX (H-2): Rate limiting per sender (max 100 nonces/minute)
|
|
242
|
+
*/
|
|
94
243
|
validateAndRecord(sender, messageType, nonce) {
|
|
244
|
+
// Validate nonce format
|
|
95
245
|
if (!/^0x[a-fA-F0-9]{64}$/.test(nonce)) {
|
|
96
246
|
return {
|
|
97
247
|
valid: false,
|
|
@@ -99,16 +249,44 @@ class SetBasedReceivedNonceTracker {
|
|
|
99
249
|
receivedNonce: nonce
|
|
100
250
|
};
|
|
101
251
|
}
|
|
252
|
+
// SECURITY FIX (H-2): Rate limit check (BEFORE global limit to avoid unnecessary work)
|
|
253
|
+
if (this.checkRateLimit(sender)) {
|
|
254
|
+
return {
|
|
255
|
+
valid: false,
|
|
256
|
+
reason: `Rate limit exceeded for sender ${sender}: ` +
|
|
257
|
+
`Maximum ${this.maxNoncesPerMinute} nonces per minute allowed. ` +
|
|
258
|
+
`This may indicate a flood attack or misconfigured client. ` +
|
|
259
|
+
`Wait 1 minute before retrying.`,
|
|
260
|
+
receivedNonce: nonce
|
|
261
|
+
};
|
|
262
|
+
}
|
|
263
|
+
// SECURITY FIX (H-2): Periodic cleanup every 100 validations (amortized cost)
|
|
264
|
+
if (this.totalEntries % 100 === 0) {
|
|
265
|
+
this.cleanupRateLimitState();
|
|
266
|
+
}
|
|
267
|
+
// SECURITY FIX (HIGH-2): Check global limit BEFORE adding
|
|
268
|
+
if (this.totalEntries >= this.maxTotalEntries) {
|
|
269
|
+
return {
|
|
270
|
+
valid: false,
|
|
271
|
+
reason: `Global nonce tracker limit reached (${this.maxTotalEntries} entries). ` +
|
|
272
|
+
`This may indicate a DoS attack or need for cleanup. ` +
|
|
273
|
+
`Current usage: ${this.totalEntries} entries across ${this.getCombinationCount()} sender+type combinations.`,
|
|
274
|
+
receivedNonce: nonce
|
|
275
|
+
};
|
|
276
|
+
}
|
|
277
|
+
// Get sender's nonce map
|
|
102
278
|
let senderNonces = this.usedNonces.get(sender);
|
|
103
279
|
if (!senderNonces) {
|
|
104
280
|
senderNonces = new Map();
|
|
105
281
|
this.usedNonces.set(sender, senderNonces);
|
|
106
282
|
}
|
|
283
|
+
// Get set of used nonces for this message type
|
|
107
284
|
let usedSet = senderNonces.get(messageType);
|
|
108
285
|
if (!usedSet) {
|
|
109
286
|
usedSet = new Set();
|
|
110
287
|
senderNonces.set(messageType, usedSet);
|
|
111
288
|
}
|
|
289
|
+
// Check if nonce was already used
|
|
112
290
|
if (usedSet.has(nonce)) {
|
|
113
291
|
return {
|
|
114
292
|
valid: false,
|
|
@@ -116,9 +294,52 @@ class SetBasedReceivedNonceTracker {
|
|
|
116
294
|
receivedNonce: nonce
|
|
117
295
|
};
|
|
118
296
|
}
|
|
297
|
+
// SECURITY FIX (NEW-H-2): Auto-cleanup if max size per type reached
|
|
298
|
+
if (usedSet.size >= this.maxSizePerType) {
|
|
299
|
+
// Keep only last 80% of entries (sorted by nonce value)
|
|
300
|
+
const keepCount = Math.floor(this.maxSizePerType * 0.8);
|
|
301
|
+
const sortedNonces = Array.from(usedSet).sort((a, b) => {
|
|
302
|
+
const aVal = BigInt(a);
|
|
303
|
+
const bVal = BigInt(b);
|
|
304
|
+
return aVal < bVal ? -1 : aVal > bVal ? 1 : 0;
|
|
305
|
+
});
|
|
306
|
+
const removedCount = usedSet.size - keepCount;
|
|
307
|
+
usedSet = new Set(sortedNonces.slice(-keepCount));
|
|
308
|
+
senderNonces.set(messageType, usedSet);
|
|
309
|
+
// SECURITY FIX (HIGH-2): Update global counter
|
|
310
|
+
this.totalEntries -= removedCount;
|
|
311
|
+
}
|
|
312
|
+
// Valid nonce - record it
|
|
119
313
|
usedSet.add(nonce);
|
|
314
|
+
// SECURITY FIX (HIGH-2): Update global counter
|
|
315
|
+
this.totalEntries++;
|
|
120
316
|
return { valid: true };
|
|
121
317
|
}
|
|
318
|
+
/**
|
|
319
|
+
* Get number of sender+messageType combinations (for monitoring)
|
|
320
|
+
* SECURITY FIX (HIGH-2): Monitoring method
|
|
321
|
+
*/
|
|
322
|
+
getCombinationCount() {
|
|
323
|
+
let count = 0;
|
|
324
|
+
this.usedNonces.forEach(senderMap => {
|
|
325
|
+
count += senderMap.size;
|
|
326
|
+
});
|
|
327
|
+
return count;
|
|
328
|
+
}
|
|
329
|
+
/**
|
|
330
|
+
* Get memory usage statistics
|
|
331
|
+
* SECURITY FIX (HIGH-2): Monitoring method for DoS detection
|
|
332
|
+
*/
|
|
333
|
+
getMemoryUsage() {
|
|
334
|
+
return {
|
|
335
|
+
totalEntries: this.totalEntries,
|
|
336
|
+
combinations: this.getCombinationCount(),
|
|
337
|
+
maxTotalEntries: this.maxTotalEntries
|
|
338
|
+
};
|
|
339
|
+
}
|
|
340
|
+
/**
|
|
341
|
+
* Check if a nonce has been used
|
|
342
|
+
*/
|
|
122
343
|
hasBeenUsed(sender, messageType, nonce) {
|
|
123
344
|
const senderNonces = this.usedNonces.get(sender);
|
|
124
345
|
if (!senderNonces) {
|
|
@@ -130,6 +351,9 @@ class SetBasedReceivedNonceTracker {
|
|
|
130
351
|
}
|
|
131
352
|
return usedSet.has(nonce);
|
|
132
353
|
}
|
|
354
|
+
/**
|
|
355
|
+
* Get highest nonce seen (for this strategy, compute from set)
|
|
356
|
+
*/
|
|
133
357
|
getHighestNonce(sender, messageType) {
|
|
134
358
|
const senderNonces = this.usedNonces.get(sender);
|
|
135
359
|
if (!senderNonces) {
|
|
@@ -139,6 +363,7 @@ class SetBasedReceivedNonceTracker {
|
|
|
139
363
|
if (!usedSet || usedSet.size === 0) {
|
|
140
364
|
return null;
|
|
141
365
|
}
|
|
366
|
+
// Find maximum nonce in set
|
|
142
367
|
let maxNonce = BigInt(0);
|
|
143
368
|
usedSet.forEach(nonce => {
|
|
144
369
|
const value = BigInt(nonce);
|
|
@@ -148,18 +373,34 @@ class SetBasedReceivedNonceTracker {
|
|
|
148
373
|
});
|
|
149
374
|
return '0x' + maxNonce.toString(16).padStart(64, '0');
|
|
150
375
|
}
|
|
376
|
+
/**
|
|
377
|
+
* Reset tracking for sender + message type
|
|
378
|
+
*/
|
|
151
379
|
reset(sender, messageType) {
|
|
152
380
|
const senderNonces = this.usedNonces.get(sender);
|
|
153
381
|
if (senderNonces) {
|
|
382
|
+
const usedSet = senderNonces.get(messageType);
|
|
383
|
+
if (usedSet) {
|
|
384
|
+
// SECURITY FIX (HIGH-2): Update global counter
|
|
385
|
+
this.totalEntries -= usedSet.size;
|
|
386
|
+
}
|
|
154
387
|
senderNonces.delete(messageType);
|
|
155
388
|
if (senderNonces.size === 0) {
|
|
156
389
|
this.usedNonces.delete(sender);
|
|
157
390
|
}
|
|
158
391
|
}
|
|
159
392
|
}
|
|
393
|
+
/**
|
|
394
|
+
* Clear all tracked nonces
|
|
395
|
+
*/
|
|
160
396
|
clearAll() {
|
|
161
397
|
this.usedNonces.clear();
|
|
398
|
+
// SECURITY FIX (HIGH-2): Reset global counter
|
|
399
|
+
this.totalEntries = 0;
|
|
162
400
|
}
|
|
401
|
+
/**
|
|
402
|
+
* Get nonce count for sender + message type (for monitoring)
|
|
403
|
+
*/
|
|
163
404
|
getNonceCount(sender, messageType) {
|
|
164
405
|
const senderNonces = this.usedNonces.get(sender);
|
|
165
406
|
if (!senderNonces) {
|
|
@@ -168,6 +409,10 @@ class SetBasedReceivedNonceTracker {
|
|
|
168
409
|
const usedSet = senderNonces.get(messageType);
|
|
169
410
|
return usedSet ? usedSet.size : 0;
|
|
170
411
|
}
|
|
412
|
+
/**
|
|
413
|
+
* Cleanup old nonces (keep only last N)
|
|
414
|
+
* This prevents unbounded memory growth
|
|
415
|
+
*/
|
|
171
416
|
cleanup(sender, messageType, keepLast = 1000) {
|
|
172
417
|
const senderNonces = this.usedNonces.get(sender);
|
|
173
418
|
if (!senderNonces) {
|
|
@@ -177,20 +422,31 @@ class SetBasedReceivedNonceTracker {
|
|
|
177
422
|
if (!usedSet || usedSet.size <= keepLast) {
|
|
178
423
|
return;
|
|
179
424
|
}
|
|
425
|
+
// Convert to array and sort by nonce value
|
|
180
426
|
const sortedNonces = Array.from(usedSet).sort((a, b) => {
|
|
181
427
|
const aVal = BigInt(a);
|
|
182
428
|
const bVal = BigInt(b);
|
|
183
429
|
return aVal < bVal ? -1 : aVal > bVal ? 1 : 0;
|
|
184
430
|
});
|
|
431
|
+
// Keep only the last N nonces
|
|
432
|
+
const removedCount = usedSet.size - keepLast;
|
|
185
433
|
const toKeep = new Set(sortedNonces.slice(-keepLast));
|
|
186
434
|
senderNonces.set(messageType, toKeep);
|
|
435
|
+
// SECURITY FIX (HIGH-2): Update global counter
|
|
436
|
+
this.totalEntries -= removedCount;
|
|
187
437
|
}
|
|
188
438
|
}
|
|
189
439
|
exports.SetBasedReceivedNonceTracker = SetBasedReceivedNonceTracker;
|
|
440
|
+
/**
|
|
441
|
+
* Factory function to create a nonce tracker
|
|
442
|
+
* @param strategy - 'memory-efficient' (highest nonce) or 'set-based' (all nonces)
|
|
443
|
+
* @returns IReceivedNonceTracker instance
|
|
444
|
+
*/
|
|
190
445
|
function createReceivedNonceTracker(strategy = 'memory-efficient') {
|
|
191
446
|
if (strategy === 'set-based') {
|
|
192
447
|
return new SetBasedReceivedNonceTracker();
|
|
193
448
|
}
|
|
194
449
|
return new InMemoryReceivedNonceTracker();
|
|
195
450
|
}
|
|
451
|
+
exports.createReceivedNonceTracker = createReceivedNonceTracker;
|
|
196
452
|
//# sourceMappingURL=ReceivedNonceTracker.js.map
|