Skip to content

Commit

Permalink
Solana: Provide ability to resign transactions with ephemeral keys (#195
Browse files Browse the repository at this point in the history
)
  • Loading branch information
barnjamin authored Jan 3, 2024
1 parent f383a43 commit 75c7155
Show file tree
Hide file tree
Showing 12 changed files with 253 additions and 152 deletions.
4 changes: 2 additions & 2 deletions examples/src/helpers/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import {
import { getAlgorandSigner } from "@wormhole-foundation/connect-sdk-algorand/src/testing";
import { getCosmwasmSigner } from "@wormhole-foundation/connect-sdk-cosmwasm/src/testing";
import { getEvmSigner } from "@wormhole-foundation/connect-sdk-evm/src/testing";
import { getSolanaSigner } from "@wormhole-foundation/connect-sdk-solana/src/testing";
import { getSolanaSignAndSendSigner } from "@wormhole-foundation/connect-sdk-solana/src/testing";

// Use .env.example as a template for your .env file and populate it with secrets
// for funded accounts on the relevant chain+network combos to run the example
Expand Down Expand Up @@ -56,7 +56,7 @@ export async function getStuff<
const platform = chain.platform.utils()._platform;
switch (platform) {
case "Solana":
signer = await getSolanaSigner(await chain.getRpc(), getEnv("SOL_PRIVATE_KEY"));
signer = await getSolanaSignAndSendSigner(await chain.getRpc(), getEnv("SOL_PRIVATE_KEY"));
break;
case "Cosmwasm":
signer = await getCosmwasmSigner(await chain.getRpc(), getEnv("COSMOS_MNEMONIC"));
Expand Down
18 changes: 9 additions & 9 deletions platforms/solana/__tests__/integration/tokenBridge.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ describe('TokenBridge Tests', () => {
expect(attestTx.chain).toEqual(chain);

const { transaction } = attestTx;
expect(transaction.instructions).toHaveLength(2);
expect(transaction.transaction.instructions).toHaveLength(2);
});

test('Submit Attestation', async () => {
Expand All @@ -229,17 +229,17 @@ describe('TokenBridge Tests', () => {
});
const submitAttestation = tb.submitAttestation(vaa, sender);

const allTxns = [];
const allTxns: SolanaUnsignedTransaction<TNet>[] = [];
for await (const atx of submitAttestation) {
allTxns.push(atx);
}
expect(allTxns).toHaveLength(3);

const [verifySig, postVaa, create] = allTxns;
//
expect(verifySig.transaction.instructions).toHaveLength(2);
expect(postVaa.transaction.instructions).toHaveLength(1);
expect(create.transaction.instructions).toHaveLength(1);
expect(verifySig.transaction.transaction.instructions).toHaveLength(2);
expect(postVaa.transaction.transaction.instructions).toHaveLength(1);
expect(create.transaction.transaction.instructions).toHaveLength(1);
});
});

Expand All @@ -260,7 +260,7 @@ describe('TokenBridge Tests', () => {
const xfer = tb.transfer(sender, recipient, token, amount, payload);
expect(xfer).toBeTruthy();

const allTxns = [];
const allTxns: SolanaUnsignedTransaction<TNet>[] = [];
for await (const tx of xfer) {
allTxns.push(tx);
}
Expand All @@ -271,7 +271,7 @@ describe('TokenBridge Tests', () => {
expect(xferTx!.chain).toEqual(chain);

const { transaction } = xferTx;
expect(transaction.instructions).toHaveLength(6);
expect(transaction.transaction.instructions).toHaveLength(6);
// ...
});

Expand All @@ -285,7 +285,7 @@ describe('TokenBridge Tests', () => {
);
expect(xfer).toBeTruthy();

const allTxns = [];
const allTxns: SolanaUnsignedTransaction<TNet>[] = [];
for await (const tx of xfer) {
allTxns.push(tx);
}
Expand All @@ -296,7 +296,7 @@ describe('TokenBridge Tests', () => {
expect(xferTx.chain).toEqual(chain);

const { transaction } = xferTx;
expect(transaction.instructions).toHaveLength(2);
expect(transaction.transaction.instructions).toHaveLength(2);
});
});
});
Expand Down
12 changes: 4 additions & 8 deletions platforms/solana/protocols/cctp/src/circleBridge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import {
SolanaChains,
SolanaPlatform,
SolanaPlatformType,
SolanaTransaction,
SolanaUnsignedTransaction,
} from '@wormhole-foundation/connect-sdk-solana';
import { MessageTransmitter, TokenMessenger } from '.';
Expand Down Expand Up @@ -105,13 +106,10 @@ export class SolanaCircleBridge<N extends Network, C extends SolanaChains>
senderPk,
);

const { blockhash } = await SolanaPlatform.latestBlock(this.connection);
const transaction = new Transaction();
transaction.recentBlockhash = blockhash;
transaction.feePayer = senderPk;
transaction.add(ix);

yield this.createUnsignedTx(transaction, 'CircleBridge.Redeem');
yield this.createUnsignedTx({ transaction }, 'CircleBridge.Redeem');
}

async *transfer(
Expand Down Expand Up @@ -140,13 +138,11 @@ export class SolanaCircleBridge<N extends Network, C extends SolanaChains>
amount,
);

const { blockhash } = await SolanaPlatform.latestBlock(this.connection);
const transaction = new Transaction();
transaction.recentBlockhash = blockhash;
transaction.feePayer = senderPk;
transaction.add(ix);

yield this.createUnsignedTx(transaction, 'CircleBridge.Transfer');
yield this.createUnsignedTx({ transaction }, 'CircleBridge.Transfer');
}

async isTransferCompleted(message: CircleBridge.Message): Promise<boolean> {
Expand Down Expand Up @@ -216,7 +212,7 @@ export class SolanaCircleBridge<N extends Network, C extends SolanaChains>
}

private createUnsignedTx(
txReq: Transaction,
txReq: SolanaTransaction,
description: string,
parallelizable: boolean = false,
): SolanaUnsignedTransaction<N, C> {
Expand Down
34 changes: 16 additions & 18 deletions platforms/solana/protocols/core/src/core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
SolanaPlatform,
SolanaPlatformType,
SolanaUnsignedTransaction,
SolanaTransaction,
} from '@wormhole-foundation/connect-sdk-solana';
import {
ChainId,
Expand All @@ -30,14 +31,14 @@ import {
} from '@wormhole-foundation/connect-sdk';
import { Wormhole as WormholeCoreContract } from './types';
import {
BridgeData,
createBridgeFeeTransferInstruction,
createPostMessageInstruction,
createPostVaaInstruction,
createReadOnlyWormholeProgramInterface,
createVerifySignaturesInstructions,
createBridgeFeeTransferInstruction,
derivePostedVaaKey,
getWormholeBridgeData,
BridgeData,
} from './utils';

const SOLANA_SEQ_LOG = 'Program log: Sequence: ';
Expand Down Expand Up @@ -82,6 +83,7 @@ export class SolanaWormholeCore<N extends Network, C extends SolanaChains>
throw new Error(
`Network mismatch for chain ${chain}: ${conf.network} != ${network}`,
);

return new SolanaWormholeCore(
network as N,
chain,
Expand Down Expand Up @@ -126,24 +128,20 @@ export class SolanaWormholeCore<N extends Network, C extends SolanaChains>
fee,
);

const { blockhash } = await SolanaPlatform.latestBlock(this.connection);
const transaction = new Transaction();
transaction.recentBlockhash = blockhash;
transaction.feePayer = payer;
transaction.add(feeTransferIx, postMsgIx);
transaction.partialSign(messageAccount);

yield this.createUnsignedTx(transaction, 'Core.PublishMessage');
yield this.createUnsignedTx(
{ transaction, signers: [messageAccount] },
'Core.PublishMessage',
);
}

async *verifyMessage(sender: AnySolanaAddress, vaa: VAA) {
yield* this.postVaa(sender, vaa);
}

async *postVaa(sender: AnySolanaAddress, vaa: VAA, blockhash?: string) {
if (!blockhash)
({ blockhash } = await SolanaPlatform.latestBlock(this.connection));

async *postVaa(sender: AnySolanaAddress, vaa: VAA) {
const postedVaaAddress = derivePostedVaaKey(
this.coreBridge.programId,
Buffer.from(vaa.hash),
Expand All @@ -170,11 +168,12 @@ export class SolanaWormholeCore<N extends Network, C extends SolanaChains>
const verifySigTx = new Transaction().add(
...verifySignaturesInstructions.slice(i, i + 2),
);
verifySigTx.recentBlockhash = blockhash;
verifySigTx.feePayer = senderAddr;
verifySigTx.partialSign(signatureSet);

yield this.createUnsignedTx(verifySigTx, 'Core.VerifySignature', true);
yield this.createUnsignedTx(
{ transaction: verifySigTx, signers: [signatureSet] },
'Core.VerifySignature',
true,
);
}

// Finally create the VAA posting transaction
Expand All @@ -187,10 +186,9 @@ export class SolanaWormholeCore<N extends Network, C extends SolanaChains>
signatureSet.publicKey,
),
);
postVaaTx.recentBlockhash = blockhash;
postVaaTx.feePayer = senderAddr;

yield this.createUnsignedTx(postVaaTx, 'Core.PostVAA');
yield this.createUnsignedTx({ transaction: postVaaTx }, 'Core.PostVAA');
}

static parseSequenceFromLog(
Expand Down Expand Up @@ -327,7 +325,7 @@ export class SolanaWormholeCore<N extends Network, C extends SolanaChains>
}

private createUnsignedTx(
txReq: Transaction,
txReq: SolanaTransaction,
description: string,
parallelizable: boolean = false,
): SolanaUnsignedTransaction<N, C> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import {
SolanaChains,
SolanaPlatform,
SolanaPlatformType,
SolanaTransaction,
SolanaUnsignedTransaction,
} from '@wormhole-foundation/connect-sdk-solana';

Expand Down Expand Up @@ -173,18 +174,18 @@ export class SolanaAutomaticTokenBridge<
nonce,
);

const { blockhash } = await SolanaPlatform.latestBlock(this.connection);

transaction.add(transferIx);
transaction.recentBlockhash = blockhash;
transaction.feePayer = senderAddress;

yield this.createUnsignedTx(transaction, 'AutomaticTokenBridge.Transfer');
yield this.createUnsignedTx(
{ transaction },
'AutomaticTokenBridge.Transfer',
);
}

async *redeem(sender: AccountAddress<C>, vaa: AutomaticTokenBridge.VAA) {
const redeemTx = new Transaction();
yield this.createUnsignedTx(redeemTx, 'AutomaticTokenBridge.Redeem');
const transaction = new Transaction();
yield this.createUnsignedTx({ transaction }, 'AutomaticTokenBridge.Redeem');
throw new Error('Method not implemented.');
}

Expand Down Expand Up @@ -327,7 +328,7 @@ export class SolanaAutomaticTokenBridge<
}

private createUnsignedTx(
txReq: Transaction,
txReq: SolanaTransaction,
description: string,
parallelizable: boolean = false,
): SolanaUnsignedTransaction<N, C> {
Expand Down
Loading

0 comments on commit 75c7155

Please sign in to comment.