Bind replay claims to challenge expiry. Ex. tryClaim(key, expiresAt).
Background
Store.tryClaim(key) (added in #24) retains transaction-hash claims forever. Every verified payment leaves a permanent entry, so any durable store grows without bound.
The typescript mppx SDK solved this by storing a marker that lapses at the challenge's expiry. One a challenge has expired, there's no reason to keep a cache entry for its associated transaction as it can no longer be claimed by an agent.
Using an expiry/TTL is safe in the typescript SDK because it cryptographically binds on-chain transaction memos to to a specific challenge. Therefore, a settled transaction can only satisfy exactly one challenge.
The mpp-java SDK has no such binding. TempoChargeIntent.matchTransferLogs compares only
currency, recipient, amount, and sender. Adding claim expiry would be a regression and make servers susceptible to replay attacks.
Proposed change
Implement memo binding between on-chain transactions and challenges. Then, once memo binding is in place, update the Store interface:
@FunctionalInterface
public interface Store {
boolean tryClaim(String key);
/** Claims {@code key} until {@code expiresAt}, after which the claim may be dropped. */
default boolean tryClaim(String key, Instant expiresAt) {
return tryClaim(key);
}
}
TempoChargeIntent should pass the verified challenge's expires as expiresAt.
Why?
- Prevents unbound growth in MemoryStore
- Achieves parity with other SDKs
Bind replay claims to challenge expiry. Ex.
tryClaim(key, expiresAt).Background
Store.tryClaim(key)(added in #24) retains transaction-hash claims forever. Every verified payment leaves a permanent entry, so any durable store grows without bound.The typescript
mppxSDK solved this by storing a marker that lapses at the challenge's expiry. One a challenge has expired, there's no reason to keep a cache entry for its associated transaction as it can no longer be claimed by an agent.Using an expiry/TTL is safe in the typescript SDK because it cryptographically binds on-chain transaction memos to to a specific challenge. Therefore, a settled transaction can only satisfy exactly one challenge.
The
mpp-javaSDK has no such binding.TempoChargeIntent.matchTransferLogscompares onlycurrency, recipient, amount, and sender. Adding claim expiry would be a regression and make servers susceptible to replay attacks.
Proposed change
Implement memo binding between on-chain transactions and challenges. Then, once memo binding is in place, update the Store interface:
TempoChargeIntentshould pass the verified challenge'sexpiresasexpiresAt.Why?