Skip to content

Commit 73664e1

Browse files
committed
Generate meta transaction nonces randomly
Instead of querying the TLProvider for the next nonce to use for an identity, use the alternative approach of a random nonce. According to the contract implementation such nonce must be generated within the range of ]2^255, 2^256[. Related to: #361
1 parent 76e31e5 commit 73664e1

File tree

4 files changed

+46
-2
lines changed

4 files changed

+46
-2
lines changed

src/typings.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -294,7 +294,7 @@ export interface RawTxObject {
294294
to?: string
295295
value?: number | string | BigNumber
296296
data?: string
297-
nonce?: number
297+
nonce?: number | string
298298
baseFee?: number | string | BigNumber
299299
gasLimit?: number | string | BigNumber
300300
gasPrice?: number | string | BigNumber

src/wallets/IdentityWallet.ts

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,10 @@ import { AddressZero } from 'ethers/constants'
3232
const initcodeWithPadding =
3333
'0x608060405234801561001057600080fd5b506040516020806102178339810180604052602081101561003057600080fd5b50506101d6806100416000396000f3fe6080604052600436106100295760003560e01c80635c60da1b1461005c578063d784d4261461008d575b600080546040516001600160a01b0390911691369082376000803683855af43d6000833e808015610058573d83f35b3d83fd5b34801561006857600080fd5b506100716100c2565b604080516001600160a01b039092168252519081900360200190f35b34801561009957600080fd5b506100c0600480360360208110156100b057600080fd5b50356001600160a01b03166100d1565b005b6000546001600160a01b031681565b6000546001600160a01b03161561014957604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f496d706c656d656e746174696f6e20616c726561647920736574000000000000604482015290519081900360640190fd5b600080546001600160a01b03831673ffffffffffffffffffffffffffffffffffffffff19909116811790915560408051918252517f11135eea714a7c1c3b9aebf3d31bbd295f7e7262960215e086849c191d45bddc9181900360200190a15056fea165627a7a7230582009e814f2e28666ad200a2e809c1fe802a9264c378c39d6c2032706ab340c09a40029000000000000000000000000'
3434

35+
const MIN_RANDOM_NONCE = new BigNumber(2).pow(255).plus(1)
36+
const MAX_RANDOM_NONCE = new BigNumber(2).pow(256)
37+
const RANDOM_NONCE_RANGE = MAX_RANDOM_NONCE.minus(MIN_RANDOM_NONCE)
38+
3539
export class IdentityWallet implements TLWallet {
3640
public provider: TLProvider
3741

@@ -333,7 +337,7 @@ export class IdentityWallet implements TLWallet {
333337
}
334338

335339
public async prepareTransaction(rawTx: RawTxObject): Promise<TxObjectRaw> {
336-
rawTx.nonce = await this.provider.getIdentityNonce(this.address)
340+
rawTx.nonce = getRandomNonce()
337341

338342
const metaTxFees = await this.getMetaTxFees(rawTx)
339343

@@ -480,3 +484,20 @@ export function calculateIdentityAddress(
480484
.slice(2 + 2 * 12)
481485
return toChecksumAddress(address)
482486
}
487+
488+
/**
489+
* Generates a random nonce to use for meta transactions.
490+
* The nonce fits into the range of ]2^255, 2^256[.
491+
* This is an alternative to the up counting nonce (]0, 2^255[) without the need
492+
* to query a [[TLProvider]].
493+
*/
494+
export function getRandomNonce(): string {
495+
const exponentialMagnitute = MAX_RANDOM_NONCE.e + 1
496+
const BigNumberForRandomNonces = BigNumber.clone({
497+
EXPONENTIAL_AT: exponentialMagnitute,
498+
ROUNDING_MODE: BigNumber.ROUND_DOWN
499+
})
500+
const random = BigNumberForRandomNonces.random(exponentialMagnitute)
501+
const nonce = random.multipliedBy(RANDOM_NONCE_RANGE).plus(MIN_RANDOM_NONCE)
502+
return nonce.integerValue().toString()
503+
}

tests/e2e/Identity.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ describe('e2e', () => {
8181
identityWallet.address,
8282
0
8383
)
84+
rawTx.nonce = firstNonce
8485
await trustlinesNetwork.payment.confirm(rawTx)
8586

8687
const secondNonce = await relayProvider.getIdentityNonce(

tests/unit/IdentityWallet.test.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import BigNumber from 'bignumber.js'
12
import chai from 'chai'
23
import chaiAsPromised from 'chai-as-promised'
34
import 'mocha'
@@ -25,6 +26,7 @@ import {
2526
import { MetaTransaction } from '../../src/typings'
2627
import {
2728
calculateIdentityAddress,
29+
getRandomNonce,
2830
IdentityWallet
2931
} from '../../src/wallets/IdentityWallet'
3032

@@ -229,4 +231,24 @@ describe('unit', () => {
229231
})
230232
})
231233
})
234+
235+
describe('#getRandomNonce', () => {
236+
const minNonce = new BigNumber(2).pow(255).plus(1)
237+
const maxNonce = new BigNumber(2).pow(256)
238+
239+
it('should generate nonce in expected range', () => {
240+
// TODO: how to test this properly? Define range as parameter?
241+
for (let i = 0; i < 1000; i++) {
242+
const nonce = getRandomNonce()
243+
assert.isTrue(
244+
new BigNumber(nonce).isGreaterThanOrEqualTo(minNonce),
245+
'Random nonce is too small'
246+
)
247+
assert.isTrue(
248+
new BigNumber(nonce).isLessThan(maxNonce),
249+
'Random nonce is too big'
250+
)
251+
}
252+
})
253+
})
232254
})

0 commit comments

Comments
 (0)