diff --git a/src/app/(sidebar)/transaction/dashboard/components/Signatures.tsx b/src/app/(sidebar)/transaction/dashboard/components/Signatures.tsx index 8da474f3c..2e6a2da69 100644 --- a/src/app/(sidebar)/transaction/dashboard/components/Signatures.tsx +++ b/src/app/(sidebar)/transaction/dashboard/components/Signatures.tsx @@ -1,4 +1,10 @@ -import { StrKey, TransactionBuilder } from "@stellar/stellar-sdk"; +import { + hash, + Keypair, + StrKey, + TransactionBuilder, + xdr, +} from "@stellar/stellar-sdk"; import { Icon, Link, Text } from "@stellar/design-system"; import { useStore } from "@/store/useStore"; @@ -103,7 +109,14 @@ export const Signatures = ({ const renderAuthEntriesTableBody = () => { return authEntries.map((entry, index) => { const rowKey = `auth-entry-row-${index}`; - const isMatch = verifyAuthEntryPublicKey(entry.publicKey, entry.address); + const isMatch = + isXdrInit && + verifyAuthEntrySignature( + entry.rawEntry, + entry.publicKey, + entry.signature, + network.passphrase, + ); return ( @@ -244,17 +257,55 @@ const renderSigner = (isVerified: boolean, signer: string) => { }; /** - * Verifies that the public key bytes in an auth entry signature match the - * credential address (G... key). + * Verifies a Soroban authorization entry signature cryptographically. + * + * Reconstructs the HashIdPreimage (network ID, nonce, invocation, + * signatureExpirationLedger), hashes it, and verifies the Ed25519 signature. + * + * @param rawEntry - The JSON-decoded SorobanAuthorizationEntry + * @param publicKeyHex - The hex-encoded public key from the signature map + * @param signatureHex - The hex-encoded signature bytes from the signature map + * @param networkPassphrase - The network passphrase (e.g. "Test SDF Network ; September 2015") + * @returns true if the signature is cryptographically valid + * + * @example + * const isValid = verifyAuthEntrySignature(entry.rawEntry, entry.publicKey, entry.signature, network.passphrase); */ -const verifyAuthEntryPublicKey = ( +const verifyAuthEntrySignature = ( + rawEntry: any, publicKeyHex: string, - address: string, + signatureHex: string, + networkPassphrase: string, ): boolean => { try { - const publicKeyBytes = Buffer.from(publicKeyHex, "hex"); - const derivedAddress = StrKey.encodeEd25519PublicKey(publicKeyBytes); - return derivedAddress === address; + const entryXdrBase64 = StellarXdr.encode( + "SorobanAuthorizationEntry", + JSON.stringify(rawEntry), + ); + const authEntry = xdr.SorobanAuthorizationEntry.fromXDR( + entryXdrBase64, + "base64", + ); + + const addrAuth = authEntry.credentials().address(); + const networkId = hash(Buffer.from(networkPassphrase)); + + const preimage = xdr.HashIdPreimage.envelopeTypeSorobanAuthorization( + new xdr.HashIdPreimageSorobanAuthorization({ + networkId, + nonce: addrAuth.nonce(), + invocation: authEntry.rootInvocation(), + signatureExpirationLedger: addrAuth.signatureExpirationLedger(), + }), + ); + + const payload = hash(preimage.toXDR()); + const stellarAddress = StrKey.encodeEd25519PublicKey( + Buffer.from(publicKeyHex, "hex"), + ); + const keypair = Keypair.fromPublicKey(stellarAddress); + + return keypair.verify(payload, Buffer.from(signatureHex, "hex")); } catch { return false; } @@ -266,6 +317,7 @@ type AuthEntryInfo = { publicKey: string; signature: string; contractId: string; + rawEntry: any; }; const getAuthEntries = (operations: any[] | undefined): AuthEntryInfo[] => { @@ -305,6 +357,7 @@ const parseAuthEntry = (authEntry: any): AuthEntryInfo | null => { publicKey, signature, contractId: contractFn ? contractFn.contract_address : "-", + rawEntry: authEntry, }; }; diff --git a/src/constants/networkLimits.ts b/src/constants/networkLimits.ts index 2d35f352c..629c8ccc0 100644 --- a/src/constants/networkLimits.ts +++ b/src/constants/networkLimits.ts @@ -83,36 +83,36 @@ export const MAINNET_LIMITS: NetworkLimits = { "persistent_rent_rate_denominator": "1215", "temp_rent_rate_denominator": "2430", "live_soroban_state_size_window": [ - "698933560", - "699854984", - "700498804", - "700342140", - "700482104", - "700881920", - "701866036", - "702327232", - "702236112", - "702418272", - "702794004", - "703655676", - "703906824", - "704134152", - "704376184", - "704566128", - "704783500", - "705684296", - "706367628", - "706533156", - "706697884", - "706985136", - "707803656", - "707819944", - "707582232", - "708142500", - "708686816", - "709541828", - "710004992", - "709889972" + "815655900", + "816156784", + "816421916", + "816448200", + "816688596", + "817658144", + "818086792", + "818199320", + "818175708", + "818472788", + "818694368", + "819311776", + "819455068", + "819547528", + "819953300", + "820403320", + "820785516", + "820958412", + "821015980", + "821398448", + "822010672", + "822249580", + "822400856", + "822483696", + "822863824", + "823466952", + "824503299", + "824704343", + "824784835", + "825149423" ], "state_target_size_bytes": "3000000000", "rent_fee_1kb_state_size_low": "-17000", @@ -151,36 +151,36 @@ export const TESTNET_LIMITS: NetworkLimits = { "persistent_rent_rate_denominator": "1215", "temp_rent_rate_denominator": "2430", "live_soroban_state_size_window": [ - "1056094012", - "1056110820", - "1056122744", - "1056144036", - "1056165652", - "1056199296", - "1056237568", - "1056111820", - "1056132616", - "1054811063", - "1051914996", - "1051938276", - "1051964392", - "1051990536", - "1052023580", - "1052055240", - "1052077332", - "1052101084", - "1052119060", - "1052135908", - "1052154432", - "1052174020", - "1052179092", - "1052185260", - "1052189220", - "1052192112", - "1052195920", - "1052050520", - "1052052120", - "1051275947" + "1240242453", + "1240326850", + "1240656940", + "1240689812", + "1240708488", + "1240729856", + "1240967315", + "1240976667", + "1240983511", + "1240169291", + "1239755754", + "1240718349", + "1244432760", + "1245077948", + "1245080420", + "1245109817", + "1247727563", + "1247742799", + "1247622811", + "1247537883", + "1244542212", + "1243128094", + "1243133610", + "1243133598", + "1243139894", + "1243164614", + "1243186802", + "1243193614", + "1243195062", + "1241090546" ], "state_target_size_bytes": "3000000000", "rent_fee_1kb_state_size_low": "-17000", @@ -219,36 +219,36 @@ export const FUTURENET_LIMITS: NetworkLimits = { "persistent_rent_rate_denominator": "1215", "temp_rent_rate_denominator": "2430", "live_soroban_state_size_window": [ - "71567703", - "71567703", - "71567703", - "71567703", - "71567703", - "71567703", - "71567703", - "71567703", - "71567703", - "71567703", - "71567703", - "71567703", - "71567703", - "71567703", - "71567703", - "71567703", - "71567703", - "71566291", - "71566291", - "71566291", - "71566291", - "71566291", - "71566291", - "71566291", - "71566291", - "71566291", - "71566291", - "71566291", - "71566291", - "71566291" + "69864013", + "69864013", + "69864013", + "69864013", + "69864013", + "69864013", + "69864013", + "69864013", + "69864013", + "69864013", + "69864013", + "69864013", + "69864013", + "69864013", + "69864013", + "69864013", + "69864013", + "69864013", + "69864013", + "69864013", + "69864013", + "69864013", + "69864013", + "69864013", + "69864013", + "69864013", + "69864013", + "69864013", + "69864013", + "69864013" ], "state_target_size_bytes": "3000000000", "rent_fee_1kb_state_size_low": "-17000", @@ -2503,18 +2503,18 @@ export const FUTURENET_LIMITS_JSON: NetworkLimitsJson = { }, { "ext": "v0", - "const_term": "2426722", - "linear_term": "96397671" + "const_term": "2347584", + "linear_term": "94135478" }, { "ext": "v0", - "const_term": "1541554", + "const_term": "1020885", "linear_term": "0" }, { "ext": "v0", - "const_term": "3211191", - "linear_term": "6713" + "const_term": "2638451", + "linear_term": "6803" }, { "ext": "v0", @@ -2528,18 +2528,18 @@ export const FUTURENET_LIMITS_JSON: NetworkLimitsJson = { }, { "ext": "v0", - "const_term": "8035968", - "linear_term": "309667335" + "const_term": "7663880", + "linear_term": "298580871" }, { "ext": "v0", - "const_term": "2420202", + "const_term": "1856539", "linear_term": "0" }, { "ext": "v0", - "const_term": "7050564", - "linear_term": "6797" + "const_term": "6315452", + "linear_term": "7232" }, { "ext": "v0", @@ -2598,7 +2598,7 @@ export const FUTURENET_LIMITS_JSON: NetworkLimitsJson = { }, { "ext": "v0", - "const_term": "2937755", + "const_term": "1706052", "linear_term": "0" }, { @@ -2650,6 +2650,11 @@ export const FUTURENET_LIMITS_JSON: NetworkLimitsJson = { "ext": "v0", "const_term": "33151", "linear_term": "0" + }, + { + "ext": "v0", + "const_term": "1185193", + "linear_term": "41568084" } ] }, @@ -2933,16 +2938,16 @@ export const FUTURENET_LIMITS_JSON: NetworkLimitsJson = { { "ext": "v0", "const_term": "109494", - "linear_term": "354667" + "linear_term": "266603" }, { "ext": "v0", - "const_term": "5552", + "const_term": "2776", "linear_term": "0" }, { "ext": "v0", - "const_term": "9424", + "const_term": "5896", "linear_term": "0" }, { @@ -2958,16 +2963,16 @@ export const FUTURENET_LIMITS_JSON: NetworkLimitsJson = { { "ext": "v0", "const_term": "219654", - "linear_term": "354667" + "linear_term": "266603" }, { "ext": "v0", - "const_term": "3344", + "const_term": "1672", "linear_term": "0" }, { "ext": "v0", - "const_term": "6816", + "const_term": "3960", "linear_term": "0" }, { @@ -3079,6 +3084,11 @@ export const FUTURENET_LIMITS_JSON: NetworkLimitsJson = { "ext": "v0", "const_term": "0", "linear_term": "0" + }, + { + "ext": "v0", + "const_term": "73061", + "linear_term": "229779" } ] },