Skip to content

Commit

Permalink
Changes to encoding of swift message for hex+utf-8 (#1335)
Browse files Browse the repository at this point in the history
* feat: change encoding of order message to use hex+utf-8

* accept swift taker order as hexified digest

* prettify

* feat: encodeSwiftOrderParamsMessage just return borsh buffer

* formatting

* fix borrow error

* fix: update sdk for hex encoding swift taker msg

* fix: maker order swift encoding add hex in tests

* fix tests

---------

Co-authored-by: jordy25519 <[email protected]>
Co-authored-by: Nour Alharithi <[email protected]>
  • Loading branch information
3 people authored Dec 2, 2024
1 parent a52afa0 commit 71a49b9
Show file tree
Hide file tree
Showing 13 changed files with 65 additions and 33 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions programs/drift/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ pythnet-sdk = { git = "https://github.com/drift-labs/pyth-crosschain", rev = "3e
pyth-solana-receiver-sdk = { git = "https://github.com/drift-labs/pyth-crosschain", rev = "3e8a24ecd0bcf22b787313e2020f4186bb22c729"}
bytemuck = { version = "1.4.0" }
borsh = "0.10.3"
hex = "0.4.3"
num-traits = "0.2"
uint = { version = "0.9.1", default-features = false }
num-derive = "0.3"
Expand Down
15 changes: 8 additions & 7 deletions programs/drift/src/instructions/keeper.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use std::cell::RefMut;
use std::convert::TryFrom;
use std::convert::{TryFrom, TryInto};

use anchor_lang::prelude::*;
use anchor_spl::associated_token::get_associated_token_address;
Expand Down Expand Up @@ -60,11 +60,11 @@ use crate::state::user::{
MarginMode, MarketType, OrderStatus, OrderTriggerCondition, OrderType, User, UserStats,
};
use crate::state::user_map::{load_user_map, load_user_maps, UserMap, UserStatsMap};
use crate::validation::sig_verification::{extract_ed25519_ix_signature, verify_ed25519_digest};
use crate::validation::sig_verification::{extract_ed25519_ix_signature, verify_ed25519_msg};
use crate::validation::user::{validate_user_deletion, validate_user_is_idle};
use crate::{
controller, digest_struct, load, math, print_error, safe_decrement, OracleSource,
GOV_SPOT_MARKET_INDEX, MARGIN_PRECISION,
controller, digest_struct, digest_struct_hex, load, math, print_error, safe_decrement,
OracleSource, GOV_SPOT_MARKET_INDEX, MARGIN_PRECISION,
};
use crate::{load_mut, QUOTE_PRECISION_U64};
use crate::{validate, QUOTE_PRECISION_I128};
Expand Down Expand Up @@ -597,18 +597,19 @@ pub fn place_swift_taker_order<'c: 'info, 'info>(

// Verify data from first verify ix
let ix: Instruction = load_instruction_at_checked(ix_idx as usize - 2, ix_sysvar)?;
verify_ed25519_digest(
verify_ed25519_msg(
&ix,
&swift_server::id().to_bytes(),
&digest_struct!(swift_message),
)?;

// Verify data from second verify ix
let digest_hex = digest_struct_hex!(taker_order_params_message);
let ix: Instruction = load_instruction_at_checked(ix_idx as usize - 1, ix_sysvar)?;
verify_ed25519_digest(
verify_ed25519_msg(
&ix,
&taker.authority.to_bytes(),
&digest_struct!(&taker_order_params_message),
arrayref::array_ref!(digest_hex, 0, 64),
)?;

// Verify that sig from swift server corresponds to order message
Expand Down
9 changes: 9 additions & 0 deletions programs/drift/src/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,9 +89,18 @@ macro_rules! safe_decrement {
}};
}

/// Calculate the sha256 digest of anchor encoded `struct`
#[macro_export]
macro_rules! digest_struct {
($struct:expr) => {
solana_program::hash::hash(&$struct.try_to_vec().unwrap()).to_bytes()
};
}

/// Calculate the hexified sha256 digest of anchor encoded `struct`
#[macro_export]
macro_rules! digest_struct_hex {
($struct:expr) => {{
hex::encode(digest_struct!($struct)).into_bytes()
}};
}
14 changes: 9 additions & 5 deletions programs/drift/src/validation/sig_verification.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,15 +79,19 @@ fn check_ed25519_data(data: &[u8], pubkey: &[u8], msg: &[u8], sig: &[u8]) -> Res
Ok(())
}

/// Check Ed25519Program instruction data verifies the given digest
/// Check Ed25519Program instruction data verifies the given msg
///
/// `ix` an Ed25519Program instruction [see](https://github.com/solana-labs/solana/blob/master/sdk/src/ed25519_instruction.rs))
///
/// `digest` expected digest signed by the offchain client i.e 'sha256(appMessage.serialize())'
/// `msg` expected msg signed by the offchain client e.g 'sha256(appMessage.serialize())' for a digest
///
/// `pubkey` expected pubkey of the signer
///
pub fn verify_ed25519_digest(ix: &Instruction, pubkey: &[u8; 32], digest: &[u8; 32]) -> Result<()> {
pub fn verify_ed25519_msg<const N: usize>(
ix: &Instruction,
pubkey: &[u8; 32],
msg: &[u8; N],
) -> Result<()> {
if ix.program_id != ED25519_ID || ix.accounts.len() != 0 {
msg!("Invalid Ix: program ID: {:?}", ix.program_id);
msg!("Invalid Ix: accounts: {:?}", ix.accounts.len());
Expand All @@ -100,7 +104,7 @@ pub fn verify_ed25519_digest(ix: &Instruction, pubkey: &[u8; 32], digest: &[u8;
msg!(
"Invalid Ix: data: {:?}, len: {:?}",
ix.data.len(),
16 + 64 + 32 + digest.len()
16 + 64 + 32 + N
);
return Err(ErrorCode::SigVerificationFailed.into());
}
Expand Down Expand Up @@ -137,7 +141,7 @@ pub fn verify_ed25519_digest(ix: &Instruction, pubkey: &[u8; 32], digest: &[u8;

// verify data is for digest and pubkey
let ix_msg_data = &ix_data[112..];
if ix_msg_data != digest || message_data_size != digest.len() as u16 {
if ix_msg_data != msg || message_data_size != N as u16 {
return Err(ErrorCode::SigVerificationFailed.into());
}

Expand Down
11 changes: 7 additions & 4 deletions sdk/src/driftClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5823,10 +5823,11 @@ export class DriftClient {
public signSwiftOrderParamsMessage(
orderParamsMessage: SwiftOrderParamsMessage
): Buffer {
const takerOrderParamsMessage = Uint8Array.from(
digest(this.encodeSwiftOrderParamsMessage(orderParamsMessage))
const takerOrderParamsMessage =
this.encodeSwiftOrderParamsMessage(orderParamsMessage);
return this.signMessage(
new TextEncoder().encode(digest(takerOrderParamsMessage).toString('hex'))
);
return this.signMessage(takerOrderParamsMessage);
}

public encodeSwiftOrderParamsMessage(
Expand Down Expand Up @@ -5912,7 +5913,9 @@ export class DriftClient {
Ed25519Program.createInstructionWithPublicKey({
publicKey: takerInfo.takerUserAccount.authority.toBytes(),
signature: Uint8Array.from(swiftOrderParamsSignature),
message: Uint8Array.from(digest(encodedSwiftOrderParamsMessage)),
message: new TextEncoder().encode(
digest(encodedSwiftOrderParamsMessage).toString('hex')
),
});

const placeTakerSwiftPerpOrderIx =
Expand Down
8 changes: 6 additions & 2 deletions sdk/tests/auctions/test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import { PRICE_PRECISION, BN, deriveOracleAuctionParams } from '../../src';
import {
PRICE_PRECISION,
BN,
deriveOracleAuctionParams,
PositionDirection,
} from '../../src';
import { assert } from 'chai';
import { PositionDirection } from '../../lib';

describe('Auction Tests', () => {
it('deriveOracleAuctionParams', async () => {
Expand Down
6 changes: 3 additions & 3 deletions sdk/tests/decode/test.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
import { AnchorProvider, Idl, Program } from '@coral-xyz/anchor';
import driftIDL from '../../src/idl/drift.json';
import { Connection, Keypair } from '@solana/web3.js';
import { Wallet } from '../../src';
import {
decodeUser,
Wallet,
DRIFT_PROGRAM_ID,
isSpotPositionAvailable,
isVariant,
Order,
PerpPosition,
positionIsAvailable,
SpotPosition,
} from '../../lib';
import { decodeUser } from '../../lib/decode/user';
} from '../../src';
import { assert } from 'chai';
import { userAccountBufferStrings } from './userAccountBufferStrings';
const sizeof = require('object-sizeof');
Expand Down
6 changes: 6 additions & 0 deletions sdk/tests/dlob/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,8 @@ export const mockPerpMarkets: Array<PerpMarketAccount> = [
numberOfUsers: 0,
marginRatioInitial: 2000,
marginRatioMaintenance: 1000,
highLeverageMarginRatioInitial: 0,
highLeverageMarginRatioMaintenance: 0,
nextFillRecordId: new BN(0),
pnlPool: {
scaledBalance: new BN(0),
Expand Down Expand Up @@ -207,6 +209,8 @@ export const mockPerpMarkets: Array<PerpMarketAccount> = [
numberOfUsers: 0,
marginRatioInitial: 0,
marginRatioMaintenance: 0,
highLeverageMarginRatioInitial: 0,
highLeverageMarginRatioMaintenance: 0,
nextFillRecordId: new BN(0),
pnlPool: {
scaledBalance: new BN(0),
Expand Down Expand Up @@ -249,6 +253,8 @@ export const mockPerpMarkets: Array<PerpMarketAccount> = [
numberOfUsers: 0,
marginRatioInitial: 0,
marginRatioMaintenance: 0,
highLeverageMarginRatioInitial: 0,
highLeverageMarginRatioMaintenance: 0,
nextFillRecordId: new BN(0),
pnlPool: {
scaledBalance: new BN(0),
Expand Down
2 changes: 1 addition & 1 deletion sdk/tests/subscriber/openbook.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { OpenbookV2Subscriber, PRICE_PRECISION } from '../../lib';
import { OpenbookV2Subscriber, PRICE_PRECISION } from '../../src';
import { Connection, PublicKey } from '@solana/web3.js';

describe('openbook v2 subscriber', function () {
Expand Down
2 changes: 2 additions & 0 deletions sdk/tests/user/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
OrderTriggerCondition,
UserAccount,
ZERO,
MarginMode,
} from '../../src';

import { mockPerpPosition } from '../dlob/helpers';
Expand Down Expand Up @@ -86,4 +87,5 @@ export const mockUserAccount: UserAccount = {
openAuctions: 0,
hasOpenAuction: false,
lastFuelBonusUpdateTs: 0,
marginMode: MarginMode.DEFAULT,
};
10 changes: 5 additions & 5 deletions tests/placeAndMakeSwiftPerp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,7 @@ describe('place and make swift order', () => {
makerDriftClient.encodeSwiftServerMessage(swiftServerMessage);

const swiftSignature = makerDriftClient.signMessage(
Uint8Array.from(digest(encodedSwiftServerMessage)),
digest(encodedSwiftServerMessage),
swiftKeypair
);

Expand Down Expand Up @@ -394,7 +394,7 @@ describe('place and make swift order', () => {
makerDriftClient.encodeSwiftServerMessage(swiftServerMessage);

const swiftSignature = makerDriftClient.signMessage(
Uint8Array.from(digest(encodedSwiftServerMessage)),
digest(encodedSwiftServerMessage),
swiftKeypair
);

Expand Down Expand Up @@ -512,7 +512,7 @@ describe('place and make swift order', () => {
takerDriftClient.encodeSwiftServerMessage(swiftServerMessage);

const swiftSignature = takerDriftClient.signMessage(
Uint8Array.from(digest(encodedSwiftServerMessage))
digest(encodedSwiftServerMessage)
);

try {
Expand Down Expand Up @@ -632,7 +632,7 @@ describe('place and make swift order', () => {
makerDriftClient.encodeSwiftServerMessage(swiftServerMessage);

const swiftSignature = makerDriftClient.signMessage(
Uint8Array.from(digest(encodedSwiftServerMessage)),
digest(encodedSwiftServerMessage),
swiftKeypair
);

Expand Down Expand Up @@ -663,7 +663,7 @@ describe('place and make swift order', () => {
makerDriftClient.encodeSwiftServerMessage(swiftServerMessage2);

const swiftSignature2 = makerDriftClient.signMessage(
Uint8Array.from(digest(encodedSwiftServerMessage2)),
digest(encodedSwiftServerMessage2),
swiftKeypair
);

Expand Down
13 changes: 7 additions & 6 deletions tests/placeAndMakeSwiftPerpBankrun.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import {
ANCHOR_TEST_SWIFT_ID,
SwiftOrderRecord,
getSwiftUserAccountPublicKey,
digest,
} from '../sdk/src';

import {
Expand Down Expand Up @@ -244,7 +245,7 @@ describe('place and make swift order', () => {
makerDriftClient.encodeSwiftServerMessage(swiftServerMessage);

const swiftSignature = makerDriftClient.signMessage(
Uint8Array.from(encodedSwiftServerMessage),
digest(encodedSwiftServerMessage),
swiftKeypair
);

Expand Down Expand Up @@ -415,7 +416,7 @@ describe('place and make swift order', () => {
swiftDriftClient.encodeSwiftServerMessage(swiftServerMessage);

const swiftSignature = swiftDriftClient.signMessage(
Uint8Array.from(encodedSwiftServerMessage),
digest(encodedSwiftServerMessage),
swiftKeypair
);

Expand Down Expand Up @@ -534,7 +535,7 @@ describe('place and make swift order', () => {
takerDriftClient.encodeSwiftServerMessage(swiftServerMessage);

const swiftSignature = takerDriftClient.signMessage(
Uint8Array.from(encodedSwiftServerMessage),
digest(encodedSwiftServerMessage),
swiftKeypair
);

Expand Down Expand Up @@ -613,7 +614,7 @@ describe('place and make swift order', () => {
takerDriftClient.encodeSwiftServerMessage(swiftServerMessage);

const swiftSignature = takerDriftClient.signMessage(
Uint8Array.from(encodedSwiftServerMessage),
digest(encodedSwiftServerMessage),
swiftKeypair
);

Expand Down Expand Up @@ -711,7 +712,7 @@ describe('place and make swift order', () => {
makerDriftClient.encodeSwiftServerMessage(swiftServerMessage);

const swiftSignature = makerDriftClient.signMessage(
Uint8Array.from(encodedSwiftServerMessage),
digest(encodedSwiftServerMessage),
swiftKeypair
);

Expand Down Expand Up @@ -788,7 +789,7 @@ describe('place and make swift order', () => {
makerDriftClient.encodeSwiftServerMessage(swiftServerMessage);

const swiftSignature = makerDriftClient.signMessage(
Uint8Array.from(encodedSwiftServerMessage),
digest(encodedSwiftServerMessage),
swiftKeypair
);

Expand Down

0 comments on commit 71a49b9

Please sign in to comment.