Skip to content

Commit

Permalink
Merge pull request #376 from trustlines-protocol/feature/nonce-mechan…
Browse files Browse the repository at this point in the history
…ism-option

Extend configuration to set nonce mechanism
  • Loading branch information
weilbith authored May 15, 2020
2 parents 5e9c2fe + 7a390f3 commit bf78d4d
Show file tree
Hide file tree
Showing 6 changed files with 98 additions and 26 deletions.
12 changes: 7 additions & 5 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/).
### Changed

- Use `feeRecipient` as given by the provider instead of zeroAddress for meta-tx
- Use random none generation at the identity wallet for meta transactions

### Added

Expand All @@ -17,13 +18,14 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/).
where the fee payer is the loaded user
- Add `extraData` to `TransferDetails`, it contains the raw `extraData` that was present in the transfer
for which details are returned
- Add `paymentRequestId` and `transferId` to `TransferDetails` corresponding to the decoded `extraData`
- Add option to `Payment.preparePayment` function `options.addTransferId: boolean = true` that signals whether
a `transferId` should be generated and added to the payment's extraData.
- Add `transferId` to the returned values of `Payment.preparePayment`
- Add `paymentRequestId` and `messageId` to `TransferDetails` corresponding to the decoded `extraData`
- Add option to `Payment.preparePayment` function `options.addMessageId: boolean = true` that signals whether
a messageId should be generated and added to the payment's extraData.
- Add `messageId` to the returned values of `Payment.preparePayment`
- Add function `Payment.confirmPayment` to confirm any `PaymentTxObject` returned by `prepare`
and potentially send a payment message along with the payment
- Add function `Messaging.paymentMessage` to send a payment message for a `transferId` to a counterparty address
- Add function `Messaging.paymentMessage` to send a payment message for a messageId to a counterparty address
- Add optional field to the `TLNetworkConfig` for the nonce mechanism to use

### Deprecated

Expand Down
28 changes: 19 additions & 9 deletions src/TLNetwork.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import {

import utils from './utils'

import { ProviderUrl, TLNetworkConfig } from './typings'
import { NonceMechanism, ProviderUrl, TLNetworkConfig } from './typings'
import { IdentityWallet } from './wallets/IdentityWallet'

/**
Expand Down Expand Up @@ -141,7 +141,8 @@ export class TLNetwork {
identityFactoryAddress,
identityImplementationAddress,
walletType = WALLET_TYPE_ETHERS,
chainId
chainId,
nonceMechanism = NonceMechanism.Random
} = config

const defaultUrlParameters: ProviderUrl = {
Expand All @@ -162,10 +163,14 @@ export class TLNetwork {
)
)

this.setWallet(walletType, this.relayProvider, chainId, {
this.setWallet(
walletType,
this.relayProvider,
chainId,
identityFactoryAddress,
identityImplementationAddress
})
identityImplementationAddress,
nonceMechanism
)
this.setSigner(web3Provider, this.wallet)

this.currencyNetwork = new CurrencyNetwork(this.relayProvider)
Expand Down Expand Up @@ -264,15 +269,20 @@ export class TLNetwork {
walletType: string,
provider: TLProvider,
chainId: number,
{ identityFactoryAddress, identityImplementationAddress }
identityFactoryAddress: string,
identityImplementationAddress: string,
nonceMechanism: NonceMechanism
): void {
let wallet: TLWallet

if (walletType === WALLET_TYPE_IDENTITY) {
wallet = new IdentityWallet(provider, chainId, {
wallet = new IdentityWallet(
provider,
chainId,
identityFactoryAddress,
identityImplementationAddress
})
identityImplementationAddress,
nonceMechanism
)
} else if (walletType === WALLET_TYPE_ETHERS) {
wallet = new EthersWallet(provider)
} else {
Expand Down
9 changes: 9 additions & 0 deletions src/typings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ export interface TLNetworkConfig {
* Chain id used in the signature of meta-tx
*/
chainId?: number
/**
* Mechanism how to generate nonces for identity meta-tx
*/
nonceMechanism?: NonceMechanism
}

export interface ProviderUrl {
Expand Down Expand Up @@ -586,6 +590,11 @@ export interface IdentityWalletData extends TLWalletData {
meta: TLWalletDataMeta
}

export enum NonceMechanism {
Random = 'random',
Counting = 'counting'
}

// TRUSTLINE
export interface TrustlineObject {
id: string
Expand Down
25 changes: 23 additions & 2 deletions src/wallets/IdentityWallet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import {
IdentityWalletData,
MetaTransaction,
MetaTransactionFees,
NonceMechanism,
RawTxObject,
Signature,
TransactionStatusObject,
Expand Down Expand Up @@ -43,16 +44,20 @@ export class IdentityWallet implements TLWallet {
private identityAddress: string
private identityFactoryAddress: string
private identityImplementationAddress: string
private nonceMechanism: NonceMechanism
private chainId: number
private identityVersion = 1

constructor(
provider: TLProvider,
chainId: number,
{ identityFactoryAddress, identityImplementationAddress }
identityFactoryAddress: string,
identityImplementationAddress: string,
nonceMechanism: NonceMechanism
) {
this.identityFactoryAddress = identityFactoryAddress
this.identityImplementationAddress = identityImplementationAddress
this.nonceMechanism = nonceMechanism
this.provider = provider
this.chainId = chainId
}
Expand Down Expand Up @@ -337,7 +342,7 @@ export class IdentityWallet implements TLWallet {
}

public async prepareTransaction(rawTx: RawTxObject): Promise<TxObjectRaw> {
rawTx.nonce = getRandomNonce()
rawTx.nonce = await this.getNonce() // Must take place before the fee calculation!

const metaTxFees = await this.getMetaTxFees(rawTx)

Expand Down Expand Up @@ -425,6 +430,22 @@ export class IdentityWallet implements TLWallet {
}
}

public async getNonce(): Promise<string> {
switch (this.nonceMechanism) {
case NonceMechanism.Random:
return getRandomNonce()

case NonceMechanism.Counting:
const nonce = await this.provider.getIdentityNonce(this.address)
return nonce.toString()

default:
throw new Error(
`Can not generate nonce for unknown mechanism: ${this.nonceMechanism}`
)
}
}

/**
* Takes a string hash and signs it using the loaded wallet without appending `\x19Ethereum Signed Message:\n` to it
* and hashing it again, contrary to what ethers.sign or ethers.signMessage does.
Expand Down
9 changes: 4 additions & 5 deletions tests/e2e/Identity.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import {
wait
} from '../Fixtures'

import { FeePayer, RawTxObject } from '../../src/typings'
import { FeePayer, NonceMechanism, RawTxObject } from '../../src/typings'

import { TLNetwork } from '../../src/TLNetwork'

Expand Down Expand Up @@ -141,10 +141,9 @@ describe('e2e', () => {
const secondWallet = new IdentityWallet(
relayProvider,
tlNetworkConfigIdentity.chainId,
{
identityFactoryAddress,
identityImplementationAddress
}
identityFactoryAddress,
identityImplementationAddress,
NonceMechanism.Random
)
const walletData = await secondWallet.create()
await secondWallet.loadFrom(walletData)
Expand Down
41 changes: 36 additions & 5 deletions tests/unit/IdentityWallet.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import {
USER_1_IDENTITY_WALLET_V1
} from '../Fixtures'

import { MetaTransaction } from '../../src/typings'
import { MetaTransaction, NonceMechanism } from '../../src/typings'
import {
calculateIdentityAddress,
getRandomNonce,
Expand All @@ -43,10 +43,13 @@ describe('unit', () => {

const init = () => {
fakeTLProvider = new FakeTLProvider()
identityWallet = new IdentityWallet(fakeTLProvider, FAKE_CHAIN_ID, {
identityFactoryAddress: IDENTITY_FACTORY_ADDRESS,
identityImplementationAddress: IDENTITY_IMPLEMENTATION_ADDRESS
})
identityWallet = new IdentityWallet(
fakeTLProvider,
FAKE_CHAIN_ID,
IDENTITY_FACTORY_ADDRESS,
IDENTITY_IMPLEMENTATION_ADDRESS,
NonceMechanism.Random
)
}

describe('#create()', () => {
Expand Down Expand Up @@ -230,6 +233,34 @@ describe('unit', () => {
)
})
})

describe('#getNonce', () => {
beforeEach(() => init())

it('should generate nonce with random mechanism', async () => {
const randomIdentityWallet = new IdentityWallet(
fakeTLProvider,
FAKE_CHAIN_ID,
IDENTITY_FACTORY_ADDRESS,
IDENTITY_IMPLEMENTATION_ADDRESS,
NonceMechanism.Random
)
assert.isString(await randomIdentityWallet.getNonce())
})

it('should generate nonce with counting mechanism', async () => {
const countingIdentityWallet = new IdentityWallet(
fakeTLProvider,
FAKE_CHAIN_ID,
IDENTITY_FACTORY_ADDRESS,
IDENTITY_IMPLEMENTATION_ADDRESS,
NonceMechanism.Counting
)
const walletData = await countingIdentityWallet.create()
await countingIdentityWallet.loadFrom(walletData)
assert.isString(await countingIdentityWallet.getNonce())
})
})
})

describe('#getRandomNonce', () => {
Expand Down

0 comments on commit bf78d4d

Please sign in to comment.