Skip to content

Commit

Permalink
Generate meta transaction nonces randomly
Browse files Browse the repository at this point in the history
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
  • Loading branch information
weilbith committed May 11, 2020
1 parent 76e31e5 commit 73664e1
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 2 deletions.
2 changes: 1 addition & 1 deletion src/typings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -294,7 +294,7 @@ export interface RawTxObject {
to?: string
value?: number | string | BigNumber
data?: string
nonce?: number
nonce?: number | string
baseFee?: number | string | BigNumber
gasLimit?: number | string | BigNumber
gasPrice?: number | string | BigNumber
Expand Down
23 changes: 22 additions & 1 deletion src/wallets/IdentityWallet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ import { AddressZero } from 'ethers/constants'
const initcodeWithPadding =
'0x608060405234801561001057600080fd5b506040516020806102178339810180604052602081101561003057600080fd5b50506101d6806100416000396000f3fe6080604052600436106100295760003560e01c80635c60da1b1461005c578063d784d4261461008d575b600080546040516001600160a01b0390911691369082376000803683855af43d6000833e808015610058573d83f35b3d83fd5b34801561006857600080fd5b506100716100c2565b604080516001600160a01b039092168252519081900360200190f35b34801561009957600080fd5b506100c0600480360360208110156100b057600080fd5b50356001600160a01b03166100d1565b005b6000546001600160a01b031681565b6000546001600160a01b03161561014957604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f496d706c656d656e746174696f6e20616c726561647920736574000000000000604482015290519081900360640190fd5b600080546001600160a01b03831673ffffffffffffffffffffffffffffffffffffffff19909116811790915560408051918252517f11135eea714a7c1c3b9aebf3d31bbd295f7e7262960215e086849c191d45bddc9181900360200190a15056fea165627a7a7230582009e814f2e28666ad200a2e809c1fe802a9264c378c39d6c2032706ab340c09a40029000000000000000000000000'

const MIN_RANDOM_NONCE = new BigNumber(2).pow(255).plus(1)
const MAX_RANDOM_NONCE = new BigNumber(2).pow(256)
const RANDOM_NONCE_RANGE = MAX_RANDOM_NONCE.minus(MIN_RANDOM_NONCE)

export class IdentityWallet implements TLWallet {
public provider: TLProvider

Expand Down Expand Up @@ -333,7 +337,7 @@ export class IdentityWallet implements TLWallet {
}

public async prepareTransaction(rawTx: RawTxObject): Promise<TxObjectRaw> {
rawTx.nonce = await this.provider.getIdentityNonce(this.address)
rawTx.nonce = getRandomNonce()

const metaTxFees = await this.getMetaTxFees(rawTx)

Expand Down Expand Up @@ -480,3 +484,20 @@ export function calculateIdentityAddress(
.slice(2 + 2 * 12)
return toChecksumAddress(address)
}

/**
* Generates a random nonce to use for meta transactions.
* The nonce fits into the range of ]2^255, 2^256[.
* This is an alternative to the up counting nonce (]0, 2^255[) without the need
* to query a [[TLProvider]].
*/
export function getRandomNonce(): string {
const exponentialMagnitute = MAX_RANDOM_NONCE.e + 1
const BigNumberForRandomNonces = BigNumber.clone({
EXPONENTIAL_AT: exponentialMagnitute,
ROUNDING_MODE: BigNumber.ROUND_DOWN
})
const random = BigNumberForRandomNonces.random(exponentialMagnitute)
const nonce = random.multipliedBy(RANDOM_NONCE_RANGE).plus(MIN_RANDOM_NONCE)
return nonce.integerValue().toString()
}
1 change: 1 addition & 0 deletions tests/e2e/Identity.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ describe('e2e', () => {
identityWallet.address,
0
)
rawTx.nonce = firstNonce
await trustlinesNetwork.payment.confirm(rawTx)

const secondNonce = await relayProvider.getIdentityNonce(
Expand Down
22 changes: 22 additions & 0 deletions tests/unit/IdentityWallet.test.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import BigNumber from 'bignumber.js'
import chai from 'chai'
import chaiAsPromised from 'chai-as-promised'
import 'mocha'
Expand Down Expand Up @@ -25,6 +26,7 @@ import {
import { MetaTransaction } from '../../src/typings'
import {
calculateIdentityAddress,
getRandomNonce,
IdentityWallet
} from '../../src/wallets/IdentityWallet'

Expand Down Expand Up @@ -229,4 +231,24 @@ describe('unit', () => {
})
})
})

describe('#getRandomNonce', () => {
const minNonce = new BigNumber(2).pow(255).plus(1)
const maxNonce = new BigNumber(2).pow(256)

it('should generate nonce in expected range', () => {
// TODO: how to test this properly? Define range as parameter?
for (let i = 0; i < 1000; i++) {
const nonce = getRandomNonce()
assert.isTrue(
new BigNumber(nonce).isGreaterThanOrEqualTo(minNonce),
'Random nonce is too small'
)
assert.isTrue(
new BigNumber(nonce).isLessThan(maxNonce),
'Random nonce is too big'
)
}
})
})
})

0 comments on commit 73664e1

Please sign in to comment.