Between July 26 and August 2, Kaspa researchers reduced a difficult wallet problem to a surprisingly small tool: repeatedly applying the same hash function.
The idea could let a wallet authorize someone to pay into a controlled coin record without signing the receiving transaction. Each permission would work once, then automatically give way to the next. The mechanism is still a design discussion, not an approved protocol feature, and the week’s debate exposed exactly where its protection ends.
The week in one minute
- Researchers proposed a finite chain of one-time permissions that could keep a wallet address available for payments without requiring the owner to sign every receipt.
- Each permission would reveal the next hidden value in a precomputed hash chain, making previously used permissions invalid for later payments.
- The design does not stop an observer from using a revealed permission first. Its proponents argued that this is acceptable for the specific payment case under discussion, but the security boundary remains important.
- SilverScript, a language for writing Kaspa transaction conditions, merged a new built-in function and received several syntax and compatibility changes.
- SilverScript’s inherited
.reverse()operation is also under scrutiny because Kaspa lacks the underlying operation needed to support it directly.
The big story: One-time payment permission, without a fresh signature
Imagine a wallet that wants to receive a payment while retaining precise control over how its existing funds can be touched. The obvious approach is to sign a new transaction whenever someone pays. That works, but it requires the wallet to be online and actively authorize every receipt.
Michael Sutton described a different goal: give a payer a one-time permission, remain available while waiting for the payment, and preserve the ability to revoke the controlled funds if the payment never arrives. In his example, the wallet wants “full control” of its coin records but does not want to sign merely to receive money (source).
Those coin records are called UTXOs, or unspent transaction outputs. A UTXO is a discrete piece of value that a future transaction can consume. “Borrowing” one in this discussion means allowing another transaction to use and recreate it under strict conditions, rather than handing its ownership away permanently.
The proposed permission behaves like an OTP, or one-time password. The wallet gives a payer a secret value that unlocks exactly one permitted use. Once that value appears in a transaction, it should never authorize another one.
That last requirement creates the real problem.
A secret stops being secret when it reaches the network
A basic hash lock is easy to understand. A hash function turns an input into a fixed-looking result, while making it impractical to work backward from the result to the original input. The wallet publishes the result and gives the payer the original secret, known as the preimage. Revealing the correct preimage proves permission.
But once a transaction reveals that secret, everyone watching the network can see it. The mempool, the network’s waiting area for transactions not yet confirmed, makes this especially relevant. A reusable secret would become public at the moment of use.
The discussion therefore focused less on creating the first permission and more on keeping the UTXO available afterward without allowing an old permission to work again. Sutton framed the challenge directly: how can the address remain borrowable while rejecting every previous OTP? (source).
One proposed answer used another permission UTXO carrying the same covenant identity. A covenant is a rule attached to a UTXO that restricts how a transaction may spend or recreate it. In this design, the owner could issue a separate permission record, and borrowing would require consuming that record alongside the protected UTXO (source).
The approach naturally represents something usable once, but it also adds another UTXO and more transaction machinery. Sutton considered that unnecessarily complicated for the intended case.
The reveal becomes the next lock
The simpler answer was a hash chain.
Start with a random seed, hash it, hash the result, and continue for a chosen number of rounds. The wallet initially commits to the value at the far end of this chain. For the first payment, it reveals the value immediately before that endpoint. Hashing the revealed value reproduces the current commitment, proving that it is valid.
Crucially, the revealed value can then become the next commitment. A later payer receives the preceding link in the chain. Old values point in the wrong direction and cannot be used to derive unrevealed links.
“Each time you reveal another layer and it becomes the next commit,” Sutton summarized (source).
This turns one precomputed sequence into many single-use permissions. The number can be large, but it is finite because the wallet must choose and calculate the chain’s length at the beginning. Once it reaches the seed, the wallet would need to reset or allocate a new chain (source).
For users, the possible payoff is a wallet that can issue a batch of lightweight receiving permissions in advance, then accept payments without producing a new signature each time.
One threat remains outside the design
The hash chain prevents old permissions from being reused after the controlled UTXO advances. It does not necessarily identify who may submit the authorized transaction.
Maxim Biryukov pointed out that anyone who sees a valid revealed value could attempt to use it instead of the intended payer (source). Earlier ideas explored binding permission to a public key or signature, but those additions moved away from the sought-after hashes-only design.
Sutton’s response narrowed the threat model: for this receiving-payment scenario, an observer using the permission to perform the permitted borrow was not considered harmful (source). That assumption may be reasonable when the transaction must recreate the owner’s controlled value and add payment, but the archive does not establish a complete transaction specification or security analysis.
For developers: The core construction is a reverse-consumed hash chain. The locking condition stores the current commitment; a valid spend provides its preimage, and the recreated output commits to that revealed value. The discussion also considered a Merkle root with indexed leaves and a counter, but settled on the hash chain as the simpler expression of the idea (source).
The result is not merged code, a finalized covenant, or a network decision. It is a compact proposed construction with a clearly stated use case and an equally clear limitation. That distinction is the week’s most useful outcome.
What else moved forward
SilverScript gained a built-in, while its surface language kept changing
SilverScript, a language intended to make transaction spending rules easier to express, received a newly merged built-in function implemented by Sutton (source). The archive does not identify the function’s behavior, so its practical capabilities cannot be assessed from this week’s messages alone.
Other changes affected how developers write SilverScript programs. The longer entrypoint function form changed to the shorter entry, explicitly to reduce verbosity (source). Another pull request was flagged as a breaking change, meaning existing code may require updates, although the archive does not describe what compatibility was broken (source).
A separate pull request addressed an issue previously raised by another contributor, but again the message contains no technical description beyond the link (source).
The practical message is clear even where details are sparse: SilverScript is moving quickly, and developers should expect source-level adjustments rather than assume today’s syntax is stable.
An inherited convenience met Kaspa’s actual instruction set
SilverScript’s .reverse() support faces possible removal for a straightforward reason: it was copied from CashScript, but Kaspa does not have the equivalent underlying OpReverse operation (source).
An opcode is a basic instruction that the transaction-execution system understands directly. A language feature without a matching opcode may need a more complicated translation, different semantics, or removal.
No final removal decision appears in the archive. The discussion establishes the motivation for the open issue, not its resolution. Still, it illustrates an important part of language maturation: borrowed syntax must eventually answer to the capabilities of the network beneath it.
What is decided, and what is not
Completed or confirmed
- A new SilverScript built-in function was reported as merged.
- SilverScript’s entry syntax changed from
entrypoint functionto the shorterentryform (source). - Another SilverScript change was explicitly flagged as breaking, though its substance is not included in the archive (source).
Proposed or under discussion
- A precomputed hash chain could provide many sequential, one-time borrowing permissions for a controlled UTXO.
- The intended wallet use case is receiving payments without signing each receiving transaction.
- A separate permission UTXO and a Merkle-tree construction were discussed as alternatives, but no team-wide selection or implementation decision was recorded.
Still unanswered
- What exact transaction rules would guarantee that using a permission cannot harm the UTXO owner?
- Is the ability of an observer to submit the same permitted action acceptable in every intended application, or only in the narrow payment scenario?
- How should wallets reset an exhausted hash chain and manage unused permissions?
- Will
.reverse()be removed from SilverScript, replaced, or compiled through another mechanism?
What happens next
- Watch for the hash-chain idea to become a concrete SilverScript example, test, or pull request. It remains a design sketch today.
- Look for a fuller security model defining what an OTP holder and a network observer can and cannot do.
- Expect wallet-oriented details, including permission generation, revocation, exhaustion, and chain replacement, if the payment use case advances.
- SilverScript users should check the linked syntax and breaking changes before updating existing programs.
- The
.reverse()issue needs a final decision that aligns SilverScript’s promises with Kaspa’s available operations.
The week began with a wish to receive payments without surrendering wallet control. It ended with an elegant answer to permission reuse, but not a complete answer to transaction safety. The next meaningful step is proof that the simple hash chain still holds up once every spending rule and adversarial case is written down.
