Skip to content

Commit

Permalink
[multikey] Allow variable length bitmaps
Browse files Browse the repository at this point in the history
  • Loading branch information
gregnazario committed Nov 14, 2024
1 parent 281ab0b commit 69be6bb
Show file tree
Hide file tree
Showing 4 changed files with 124 additions and 4 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ All notable changes to the Aptos TypeScript SDK will be captured in this file. T

# Unreleased

- [`fix`] Allow variable length bitmaps in Multikey accounts, allowing for compatibility between SDKs properly

# 1.33.0 (2024-11-13)
- Allow optional provision of public keys in transaction simulation
- Update the multisig v2 example to demonstrate a new way to pre-check a multisig payload before it is created on-chain
Expand Down
2 changes: 1 addition & 1 deletion src/core/crypto/multiKey.ts
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ export class MultiKey extends AccountPublicKey {
// Extend by required number of bytes
if (bitmap.length < byteOffset) {
for (let i = bitmap.length; i < byteOffset; i += 1) {
bitmap.push(0)
bitmap.push(0);
}
}

Expand Down
110 changes: 110 additions & 0 deletions tests/e2e/transaction/transactionSubmission.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import {
TransactionPayloadEntryFunction,
Bool,
MoveString,
Ed25519PublicKey,
AnyPublicKey,
} from "../../../src";
import { MAX_U64_BIG_INT } from "../../../src/bcs/consts";
import { longTestTimeout } from "../../unit/helper";
Expand Down Expand Up @@ -662,6 +664,114 @@ describe("transaction submission", () => {
});
expect(response.signature?.type).toBe("single_sender");
});
test("it submits a multi key transaction with lots of signers", async () => {
const subAccounts = [];
for (let i = 0; i < 32; i += 1) {
switch (i % 3) {
case 0:
subAccounts.push(Account.generate({ scheme: SigningSchemeInput.Ed25519, legacy: false }));
break;
case 1:
subAccounts.push(Account.generate({ scheme: SigningSchemeInput.Ed25519, legacy: true }));
break;
case 2:
subAccounts.push(Account.generate({ scheme: SigningSchemeInput.Secp256k1Ecdsa }));
break;
default:
break;
}
}
const publicKeys = subAccounts.map((account) => {
if (account.publicKey instanceof Ed25519PublicKey) {
return new AnyPublicKey(account.publicKey);
}
return account.publicKey;
});

const multiKey = new MultiKey({
publicKeys,
signaturesRequired: 1,
});

const account = new MultiKeyAccount({
multiKey,
signers: subAccounts,
});

await aptos.fundAccount({ accountAddress: account.accountAddress, amount: 100_000_000 });

const transaction = await aptos.transaction.build.simple({
sender: account.accountAddress,
data: {
function: `0x${contractPublisherAccount.accountAddress.toStringWithoutPrefix()}::transfer::transfer`,
functionArguments: [1, receiverAccounts[0].accountAddress],
},
});

const senderAuthenticator = aptos.transaction.sign({ signer: account, transaction });

const response = await aptos.transaction.submit.simple({ transaction, senderAuthenticator });
await aptos.waitForTransaction({
transactionHash: response.hash,
});
expect(response.signature?.type).toBe("single_sender");

// Sign with only one of them now
const account2 = new MultiKeyAccount({
multiKey,
signers: [subAccounts[0]],
});
expect(account2.accountAddress).toEqual(account.accountAddress);

await aptos.fundAccount({ accountAddress: account2.accountAddress, amount: 100_000_000 });

const transaction2 = await aptos.transaction.build.simple({
sender: account2.accountAddress,
data: {
function: `0x${contractPublisherAccount.accountAddress.toStringWithoutPrefix()}::transfer::transfer`,
functionArguments: [1, receiverAccounts[0].accountAddress],
},
});

const senderAuthenticator2 = aptos.transaction.sign({ signer: account2, transaction: transaction2 });

const response2 = await aptos.transaction.submit.simple({
transaction: transaction2,
senderAuthenticator: senderAuthenticator2,
});
await aptos.waitForTransaction({
transactionHash: response2.hash,
});
expect(response2.signature?.type).toBe("single_sender");

// Sign with the last one now
const account3 = new MultiKeyAccount({
multiKey,
signers: [subAccounts[31]],
});
expect(account3.accountAddress).toEqual(account.accountAddress);

await aptos.fundAccount({ accountAddress: account3.accountAddress, amount: 100_000_000 });

const transaction3 = await aptos.transaction.build.simple({
sender: account3.accountAddress,
data: {
function: `0x${contractPublisherAccount.accountAddress.toStringWithoutPrefix()}::transfer::transfer`,
functionArguments: [1, receiverAccounts[0].accountAddress],
},
});

const senderAuthenticator3 = aptos.transaction.sign({ signer: account3, transaction: transaction3 });

const response3 = await aptos.transaction.submit.simple({
transaction: transaction3,
senderAuthenticator: senderAuthenticator3,
});
await aptos.waitForTransaction({
transactionHash: response3.hash,
});
expect(response3.signature?.type).toBe("single_sender");
});
});
describe("publish move module", () => {
const account = Account.generate();
Expand Down
14 changes: 11 additions & 3 deletions tests/unit/multiKey.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,15 @@
// Copyright © Aptos Foundation
// SPDX-License-Identifier: Apache-2.0

import { Deserializer, Ed25519PublicKey, Secp256k1PublicKey, MultiKey, Hex, MultiKeySignature, Serializer } from "../../src";
import {
Deserializer,
Ed25519PublicKey,
Secp256k1PublicKey,
MultiKey,
Hex,
MultiKeySignature,
Serializer,
} from "../../src";
import { multiKeyTestObject } from "./helper";

describe("MultiKey", () => {
Expand Down Expand Up @@ -125,9 +133,9 @@ describe("MultiKey", () => {
).toUint8Array();
const deserializer = new Deserializer(serializedBytes);
const multiKeySig = MultiKeySignature.deserialize(deserializer);
const serializer = new Serializer()
const serializer = new Serializer();
multiKeySig.serialize(serializer);
const outBytes = serializer.toUint8Array();
expect(outBytes).toEqual(serializedBytes)
expect(outBytes).toEqual(serializedBytes);
});
});

0 comments on commit 69be6bb

Please sign in to comment.