Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add replay protection to transactions #1203

Closed
evgenykuzyakov opened this issue Aug 20, 2019 · 0 comments
Closed

Add replay protection to transactions #1203

evgenykuzyakov opened this issue Aug 20, 2019 · 0 comments

Comments

@evgenykuzyakov
Copy link
Collaborator

Traditionally transactions are protected from replaying based on UTXO and nonce. Nonce is used to uniquely identify the transaction and to prevent replaying.

When dealing with state based accounts instead of UTXO, you can't be sure the given input is available. E.g., if in one fork of the chain you receive 1M tokens and decide to spend 1K of them, the same transaction can be valid in another fork. But, let's say, in that fork you didn't receive 1M tokens, and you just spent 1K of your last tokens and your account was nuked.

To prevent this from happening we introduce an additional fields in the transaction. The hash of the block on which this transaction is based (let's call it block_hash). So if you base your transaction in the given fork, then this transaction can't be replayed in any other fork that doesn't contain given block hash.

This change protects from forks, but doesn't protect from delaying a transaction for infinite amount of time and later replaying it (assuming the nonce didn't change). To resolve this we introduce an additional field that indicates transaction expiration. It's the number of blocks from the block_hash during which the transaction is considered valid. E.g. if the transaction is based on the block hash ABC and the validity period is set to 3 blocks. Then only the next 3 blocks after block ABC can include the given transaction.

We should also consider limitations of the given approach. If we allow a validity period to be very large, then we'll need to maintain a large history of previous block hashes to verify if the given transaction is still valid. Instead we should limit the validity period to a small number, e.g. 60 blocks which would indicate that the given transaction has to be taken into a block in about 1 minute.

Fields to add:

/// The hash of the block in the blockchain on top of which the given transaction is valid.  
pub block_hash: CryptoHash;
/// The number of blocks from the given block hash the given transaction is valid
pub validity_period: BlockIndex;

Constant to introduce in the genesis config:

pub MAX_TRANSACTION_VALIDITY_PERIOD: BlockIndex;  // default can be 60

For all of this to work, the Runtime should receive the block hash history up to the MAX_TRANSACTION_VALIDITY_PERIOD blocks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants