Lightweight unique kernels

I have a simple idea following the proposal Idea to fix both play and replay attacks.

As it appears (see the corresponding thread), this proposal enables to link outputs and inputs to kernels, which is something that we don’t want for Grin. Nonetheless, I want to use an idea from it, and directly apply it to the previous kernel uniqueness constructions.

The idea is to “funnel” signature_block_height: live validating nodes only accept fresh transactions entering the network that have a signature_block_height contained between current_block_height - 1 and current_block_height + 1, and treat the others as invalid.

Similarly to the other kernel uniqueness methods, the miner joins relative_height = inclusion_block_height - signature_block_height to the kernel when he includes it in the blockchain, which allows users to verify the signature of the historical kernels.

Verifying kernel uniqueness is insured by live validators, and they can do it using a small moving window of 3 blocks. Uniqueness check should not be performed at ibd.

The proposal disables all play and replay attacks wthout using mempool expiry because once in there, kernels can wait in it as long as they wish. Output uniqueness doesn’t need to be verified. Pruning nodes can prune the historical kernels. It is scalable and it provides essentially the same privacy and the same UX guarantees as today, plus an optimal security for the blockchain users since no play attacks can be performed on them due to the short validity of signature_block_height and no replay attacks can be performed due to the uniqueness check.

Then how do you know you’re on a valid chain?

Just validating some parts of a transaction by “live nodes”, ie. as part of the mempool validation but not block validation is not how blockchains work. You cannot assume that old transactions followed those rules, because at any time, a miner could’ve included an old transaction with a signature_block_height from years ago. Which would mean all validating nodes would need to store and index all kernels.

We should stop trying to satisfy this notion of tx monotonicity. Any unique kernel approach that allows transactions to never expire, also requires all validating nodes to store and index all kernels forever - an unscalable solution. Kernel expiration is likely the only way we can provide unique kernels in a scalable way without radically weakening the chain.

Yes indeed, but only if he does a reorg. And largest than one block.

Just validating some parts of a transaction by “live nodes”, ie. as part of the mempool validation but not block validation is not how blockchains work.

That’s what we do with output check for example. They are pruned, we cannot verify uniqueness for them. But it would not be safe here to require uniqueness for ibd, since uniqueness might not be achieved.

We should stop trying to satisfy this notion of tx monotonicity. Any unique kernel approach that allows transactions to never expire, also requires all validating nodes to store and index all kernels forever - an unscalable solution. Kernel expiration is likely the only way we can provide unique kernels in a scalable way without radically weakening the chain.

Yes, I remain to see why it is not scalable. Less scalable, sure, but not scalable i would not go up to that (see my proposal). I am all for doing the kernel expiry if we can make this DOS attack vector pointless (I quite think it is, but other people seem to disagree).

So the cost to attack is about $30?

What DOS attack!?! I’ve asked this dozens of times but nobody can explain any real attack to me that isn’t obviously defeated, or that doesn’t already apply today.

Let’s do kernel expiry! I am all for this, you know ; )

1 Like

When you get time, I would love if you could carefully and thoroughly detail how this DoS attack works.

Please try to think about:

  • Who benefits and what the benefits are?
  • Who suffers and what the costs are?
  • What are the risks involved for the attacker?
  • How is that different than today?

I’ve asked previously but got handwavy claims about filling the mempool with transactions that never get confirmed, which seems nonsensical, since mempools shouldn’t be accepting transactions that they don’t believe will be included in a block. A detailed description of this attack is required, and then I’m confident I can describe a preventative measure (assuming a dynamic fee market and basic mempool acceptance criteria aren’t already enough).

1 Like

Ask to the people that don’t want kernel expiry. Again I am all for it and I fully agree with you that the risk to do it is big and that the attacker may lose all his money with a high probability.

Gotcha. I was asking you since so far, you’re the only one I’ve heard claim it causes DoS attacks :slight_smile:

@tromp Are you of the belief that kernel expiration opens us up for DoS attacks, even with basic, sane mempool acceptance criteria like:

  • Don’t accept txs that expire in less than, say, 1 hour
  • Don’t accept txs with fees too low to be accepted before they expire
2 Likes

If i would rephrase my claim, i would say that there is very very low probability that he does not pay the attack as much as expensive as without kernel expiry, but i dont have other technical details to add i think given my knowledge in those things. But as I can understand it, that does not go much beyondd that.

and the probability becomes immensely low if you do a relative_max equal to 6 months for example…

Again, what attack?

Attack attempt? If you do not want to call it attack, I am fine too!

What attack attempt? Even stating this suggests there’s some kind of general idea of how to achieve some malicious goal. What is the “general idea” and what is the “malicious goal” of this attack attempt?

People may try to crack Satoshi keys in what they would call (hopeless) attack attempt. Some would call it gentle joke instead. I don’t care that much about the vocabulary here, and I agree with you that I think with a large enough relative_max it should not be a problem.

In Replay Attacks and possible mitigations I wrote:

[tx monotonicity] also prevents having to deal with certain unwanted complexities. Currently the tx fees protect against spamming of the network. For a tx to be broadcast worldwide, it cannot escape paying tx fees. But if you could publish txs that are about to expire, then the spammer reduces the odds of having to pay any fees (to nearly zero if they are a miner that just found a new block). This problem would be magnified once blocks fill up.

So yes, you can minimize such attacks by adding some complexity to mempool acceptance rules. This involves making some choices that for best effect should be coordinated network wide. And leaves some edge cases. Like if nodes don’t accept tx expiring in 1 hour, then someone could end up with a tx expiring in slightly less time, and having to figure out how to transmit it directly to a miner (who will accept whatever pays a good fee). You get these slight misalignment of incentives.

Necessity of anti-spamming measures is just one of several downsides of sacrificing tx monotonicity.
I’d rather preserve it, and add some complexity to wallets to protect their owners from (re)play attacks.

Solving problems by adding consensus rules should be a measure of last resort, as complexity added there can never be undone.

1 Like

This you just make them refuse by the network, same as the network refuses invalid signatues. And countless similar examples where people add rules for certain behaviors (like outputs uniqueness or whatever).

it is true that complexity of wallet behavior can be undone.Complexity that you will do to fix replay attacks and try to mitigate play attacks. But people will loose coins. And even if you don’t undo it, how do you address the concerns left by edge cases such as recreational users (a majority of blockchain users) fail to take the additional complexity measures that you will require them to do to not lose coin?

Do those people belong to a class of not enough sophisticated users? maybe are they too dumb to use blockchain ? How will you fix the play attacks if the user turns off his wallet after he sent coins ?

Help me understand this some more. How is it any different than just publishing with a low transaction fee, and waiting for the transaction to be included at a later point?

I’m assuming you’re just operating under the assumption that miners are going to be more likely to include soon-to-be-expired transactions, to avoid missing out on the fees? But I’m not convinced that’s the case at all, as it operates directly against basic economic incentives. When blocks are full, as long as mining is somewhat decentralized (more than 1 or 2 miners/pools), it’s always going to be in the miner’s best interests to only include transactions whose fee-to-weight ratio is the highest. They’ll leave the lower fee transactions for whoever mines the next block.

The difference is that grin nodes enforce a minimum tx fee. The assumption is that this fee is large enough to deter spamming.

Of course, miners don’t care whether txs are close to expiring; as you note they’ll just select for max-fee-per-weight.

So the concern is just that they could broadcast transactions that never get confirmed? I don’t see what the “attacker” gains by doing this, but do you agree a basic check for preventing transactions from being included in the mempool if they expire in less than a few hours would be sufficient to prevent this from becoming an issue?

that would prevent it until grin attracts nearly as much usage as bitcoin does today.