-
Notifications
You must be signed in to change notification settings - Fork 19
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Feature Passkey Proxy v2, Simple Param Shift (#2242)
# Goal The goal of this PR is to shift the `accountOwnershipProof` out of the signature payload. For reasons why, see #2241 with @aramikm Closes #2241 # Discussion - Added `proxy_v2` - Deprecated `proxy` - Duplicated tests, as eventually we'll remove v1 --------- Co-authored-by: Aramik <[email protected]>
- Loading branch information
Showing
11 changed files
with
917 additions
and
31 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
import '@frequency-chain/api-augment'; | ||
import assert from 'assert'; | ||
import { | ||
createAndFundKeypair, | ||
EcdsaSignature, | ||
getBlockNumber, | ||
getNonce, | ||
Sr25519Signature, | ||
} from '../scaffolding/helpers'; | ||
import { KeyringPair } from '@polkadot/keyring/types'; | ||
import { ExtrinsicHelper } from '../scaffolding/extrinsicHelpers'; | ||
import { getFundingSource } from '../scaffolding/funding'; | ||
import { getUnifiedPublicKey, getUnifiedAddress } from '../scaffolding/ethereum'; | ||
import { createPassKeyAndSignAccount, createPassKeyCallV2, createPasskeyPayloadV2 } from '../scaffolding/P256'; | ||
import { u8aToHex, u8aWrapBytes } from '@polkadot/util'; | ||
const fundingSource = getFundingSource(import.meta.url); | ||
|
||
describe('Passkey Pallet Proxy V2 Ethereum Tests', function () { | ||
describe('passkey ethereum tests', function () { | ||
let fundedSr25519Keys: KeyringPair; | ||
let fundedEthereumKeys: KeyringPair; | ||
let receiverKeys: KeyringPair; | ||
|
||
before(async function () { | ||
fundedSr25519Keys = await createAndFundKeypair(fundingSource, 300_000_000n); | ||
fundedEthereumKeys = await createAndFundKeypair(fundingSource, 300_000_000n, undefined, undefined, 'ethereum'); | ||
receiverKeys = await createAndFundKeypair(fundingSource); | ||
}); | ||
|
||
it('should transfer via passkeys with root sr25519 key into an ethereum style account', async function () { | ||
const accountPKey = getUnifiedPublicKey(fundedSr25519Keys); | ||
const nonce = await getNonce(fundedSr25519Keys); | ||
const transferCalls = ExtrinsicHelper.api.tx.balances.transferKeepAlive( | ||
getUnifiedAddress(receiverKeys), | ||
55_000_000n | ||
); | ||
const { passKeyPrivateKey, passKeyPublicKey } = createPassKeyAndSignAccount(accountPKey); | ||
const accountSignature = fundedSr25519Keys.sign(u8aWrapBytes(passKeyPublicKey)); | ||
const multiSignature: Sr25519Signature = { Sr25519: u8aToHex(accountSignature) }; | ||
const passkeyCall = await createPassKeyCallV2(accountPKey, nonce, transferCalls); | ||
const passkeyPayload = await createPasskeyPayloadV2( | ||
multiSignature, | ||
passKeyPrivateKey, | ||
passKeyPublicKey, | ||
passkeyCall, | ||
false | ||
); | ||
const passkeyProxy = ExtrinsicHelper.executePassKeyProxyV2(fundedSr25519Keys, passkeyPayload); | ||
await assert.doesNotReject(passkeyProxy.fundAndSendUnsigned(fundingSource)); | ||
await ExtrinsicHelper.waitForFinalization((await getBlockNumber()) + 2); | ||
// adding some delay before fetching the nonce to ensure it is updated | ||
await new Promise((resolve) => setTimeout(resolve, 1000)); | ||
const nonceAfter = (await ExtrinsicHelper.getAccountInfo(fundedSr25519Keys)).nonce.toNumber(); | ||
assert.equal(nonce + 1, nonceAfter); | ||
}); | ||
|
||
it('should transfer via passkeys with root ethereum style key into another one', async function () { | ||
const accountPKey = getUnifiedPublicKey(fundedEthereumKeys); | ||
console.log(`accountPKey ${u8aToHex(accountPKey)}`); | ||
const nonce = await getNonce(fundedEthereumKeys); | ||
const transferCalls = ExtrinsicHelper.api.tx.balances.transferKeepAlive( | ||
getUnifiedAddress(receiverKeys), | ||
66_000_000n | ||
); | ||
const { passKeyPrivateKey, passKeyPublicKey } = createPassKeyAndSignAccount(accountPKey); | ||
// ethereum keys should not have wrapping | ||
const accountSignature = fundedEthereumKeys.sign(passKeyPublicKey); | ||
console.log(`accountSignature ${u8aToHex(accountSignature)}`); | ||
const multiSignature: EcdsaSignature = { Ecdsa: u8aToHex(accountSignature) }; | ||
const passkeyCall = await createPassKeyCallV2(accountPKey, nonce, transferCalls); | ||
const passkeyPayload = await createPasskeyPayloadV2( | ||
multiSignature, | ||
passKeyPrivateKey, | ||
passKeyPublicKey, | ||
passkeyCall, | ||
false | ||
); | ||
const passkeyProxy = ExtrinsicHelper.executePassKeyProxyV2(fundingSource, passkeyPayload); | ||
await assert.doesNotReject(passkeyProxy.sendUnsigned()); | ||
await ExtrinsicHelper.waitForFinalization((await getBlockNumber()) + 2); | ||
// adding some delay before fetching the nonce to ensure it is updated | ||
await new Promise((resolve) => setTimeout(resolve, 1000)); | ||
const nonceAfter = (await ExtrinsicHelper.getAccountInfo(fundedEthereumKeys)).nonce.toNumber(); | ||
assert.equal(nonce + 1, nonceAfter); | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
import '@frequency-chain/api-augment'; | ||
import assert from 'assert'; | ||
import { createAndFundKeypair, getBlockNumber, getNonce, Sr25519Signature } from '../scaffolding/helpers'; | ||
import { KeyringPair } from '@polkadot/keyring/types'; | ||
import { ExtrinsicHelper } from '../scaffolding/extrinsicHelpers'; | ||
import { getFundingSource } from '../scaffolding/funding'; | ||
import { u8aToHex, u8aWrapBytes } from '@polkadot/util'; | ||
import { createPassKeyAndSignAccount, createPassKeyCallV2, createPasskeyPayloadV2 } from '../scaffolding/P256'; | ||
import { getUnifiedPublicKey } from '../scaffolding/ethereum'; | ||
const fundingSource = getFundingSource(import.meta.url); | ||
|
||
describe('Passkey Pallet Proxy V2 Tests', function () { | ||
describe('proxy basic tests', function () { | ||
let fundedKeys: KeyringPair; | ||
let receiverKeys: KeyringPair; | ||
|
||
before(async function () { | ||
fundedKeys = await createAndFundKeypair(fundingSource, 300_000_000n); | ||
receiverKeys = await createAndFundKeypair(fundingSource); | ||
}); | ||
|
||
it('should fail due to unsupported call', async function () { | ||
const accountPKey = getUnifiedPublicKey(fundedKeys); | ||
const nonce = await getNonce(fundedKeys); | ||
|
||
const remarksCalls = ExtrinsicHelper.api.tx.system.remark('passkey-test'); | ||
const { passKeyPrivateKey, passKeyPublicKey, passkeySignature } = createPassKeyAndSignAccount(accountPKey); | ||
const accountSignature = fundedKeys.sign(u8aWrapBytes(passKeyPublicKey)); | ||
const multiSignature: Sr25519Signature = { Sr25519: u8aToHex(accountSignature) }; | ||
const passkeyCall = await createPassKeyCallV2(accountPKey, nonce, remarksCalls); | ||
const passkeyPayload = await createPasskeyPayloadV2( | ||
multiSignature, | ||
passKeyPrivateKey, | ||
passKeyPublicKey, | ||
passkeyCall, | ||
false | ||
); | ||
|
||
const passkeyProxy = ExtrinsicHelper.executePassKeyProxyV2(fundedKeys, passkeyPayload); | ||
await assert.rejects(passkeyProxy.fundAndSendUnsigned(fundingSource)); | ||
}); | ||
|
||
it('should fail to transfer balance due to bad account ownership proof', async function () { | ||
const accountPKey = getUnifiedPublicKey(fundedKeys); | ||
const nonce = await getNonce(fundedKeys); | ||
const transferCalls = ExtrinsicHelper.api.tx.balances.transferKeepAlive(getUnifiedPublicKey(receiverKeys), 0n); | ||
const { passKeyPrivateKey, passKeyPublicKey, passkeySignature } = createPassKeyAndSignAccount(accountPKey); | ||
const accountSignature = fundedKeys.sign('badPasskeyPublicKey'); | ||
const multiSignature: Sr25519Signature = { Sr25519: u8aToHex(accountSignature) }; | ||
const passkeyCall = await createPassKeyCallV2(accountPKey, nonce, transferCalls); | ||
const passkeyPayload = await createPasskeyPayloadV2( | ||
multiSignature, | ||
passKeyPrivateKey, | ||
passKeyPublicKey, | ||
passkeyCall, | ||
false | ||
); | ||
|
||
const passkeyProxy = ExtrinsicHelper.executePassKeyProxyV2(fundedKeys, passkeyPayload); | ||
await assert.rejects(passkeyProxy.fundAndSendUnsigned(fundingSource)); | ||
}); | ||
|
||
it('should fail to transfer balance due to bad passkey signature', async function () { | ||
const accountPKey = getUnifiedPublicKey(fundedKeys); | ||
const nonce = await getNonce(fundedKeys); | ||
const transferCalls = ExtrinsicHelper.api.tx.balances.transferKeepAlive(getUnifiedPublicKey(receiverKeys), 0n); | ||
const { passKeyPrivateKey, passKeyPublicKey, passkeySignature } = createPassKeyAndSignAccount(accountPKey); | ||
const accountSignature = fundedKeys.sign(u8aWrapBytes(passKeyPublicKey)); | ||
const multiSignature: Sr25519Signature = { Sr25519: u8aToHex(accountSignature) }; | ||
const passkeyCall = await createPassKeyCallV2(accountPKey, nonce, transferCalls); | ||
const passkeyPayload = await createPasskeyPayloadV2( | ||
multiSignature, | ||
passKeyPrivateKey, | ||
passKeyPublicKey, | ||
passkeyCall, | ||
true | ||
); | ||
|
||
const passkeyProxy = ExtrinsicHelper.executePassKeyProxyV2(fundedKeys, passkeyPayload); | ||
await assert.rejects(passkeyProxy.fundAndSendUnsigned(fundingSource)); | ||
}); | ||
|
||
it('should transfer small balance from fundedKeys to receiverKeys', async function () { | ||
const accountPKey = getUnifiedPublicKey(fundedKeys); | ||
const nonce = await getNonce(fundedKeys); | ||
const transferCalls = ExtrinsicHelper.api.tx.balances.transferKeepAlive( | ||
getUnifiedPublicKey(receiverKeys), | ||
100_000_000n | ||
); | ||
const { passKeyPrivateKey, passKeyPublicKey } = createPassKeyAndSignAccount(accountPKey); | ||
const accountSignature = fundedKeys.sign(u8aWrapBytes(passKeyPublicKey)); | ||
const multiSignature: Sr25519Signature = { Sr25519: u8aToHex(accountSignature) }; | ||
const passkeyCall = await createPassKeyCallV2(accountPKey, nonce, transferCalls); | ||
const passkeyPayload = await createPasskeyPayloadV2( | ||
multiSignature, | ||
passKeyPrivateKey, | ||
passKeyPublicKey, | ||
passkeyCall, | ||
false | ||
); | ||
const passkeyProxy = ExtrinsicHelper.executePassKeyProxyV2(fundedKeys, passkeyPayload); | ||
await assert.doesNotReject(passkeyProxy.fundAndSendUnsigned(fundingSource)); | ||
await ExtrinsicHelper.waitForFinalization((await getBlockNumber()) + 2); | ||
const receiverBalance = await ExtrinsicHelper.getAccountInfo(receiverKeys); | ||
// adding some delay before fetching the nonce to ensure it is updated | ||
await new Promise((resolve) => setTimeout(resolve, 2000)); | ||
const nonceAfter = (await ExtrinsicHelper.getAccountInfo(fundedKeys)).nonce.toNumber(); | ||
assert.equal(nonce + 1, nonceAfter); | ||
assert(receiverBalance.data.free.toBigInt() > 0n); | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.