@@ -22664,6 +22664,149 @@ With the full VAA, Guardian signatures, and the latest Guardian set, we can now
22664
22664
}
22665
22665
```
22666
22666
22667
+ ???- code "Complete Function"
22668
+ ```typescript
22669
+ vaa: string | Uint8Array<ArrayBufferLike>,
22670
+ observations: { guardianAddr: string; signature: string }[],
22671
+ currentGuardians: string[],
22672
+ guardianSetIndex: number
22673
+ ) {
22674
+ console.log('Replacing Signatures...');
22675
+
22676
+ try {
22677
+ if (!vaa) throw new Error('VAA is undefined or empty.');
22678
+ if (currentGuardians.length === 0)
22679
+ throw new Error('Guardian set is empty.');
22680
+ if (observations.length === 0) throw new Error('No observations provided.');
22681
+
22682
+ const validSigs = observations.filter((sig) =>
22683
+ currentGuardians.includes(sig.guardianAddr)
22684
+ );
22685
+
22686
+ if (validSigs.length === 0)
22687
+ throw new Error('No valid signatures found. Cannot proceed.');
22688
+
22689
+ const formattedSigs = validSigs
22690
+ .map((sig) => {
22691
+ try {
22692
+ const sigBuffer = Buffer.from(sig.signature, 'base64');
22693
+ // If it's 130 bytes, it's hex-encoded and needs conversion
22694
+ const sigBuffer1 =
22695
+ sigBuffer.length === 130
22696
+ ? Buffer.from(sigBuffer.toString(), 'hex')
22697
+ : sigBuffer;
22698
+
22699
+ const r = BigInt('0x' + sigBuffer1.subarray(0, 32).toString('hex'));
22700
+ const s = BigInt('0x' + sigBuffer1.subarray(32, 64).toString('hex'));
22701
+ const vRaw = sigBuffer1[64];
22702
+ const v = vRaw < 27 ? vRaw : vRaw - 27;
22703
+
22704
+ return {
22705
+ guardianIndex: currentGuardians.indexOf(sig.guardianAddr),
22706
+ signature: new Signature(r, s, v),
22707
+ };
22708
+ } catch (error) {
22709
+ console.error(
22710
+ `Failed to process signature for guardian: ${sig.guardianAddr}`,
22711
+ error
22712
+ );
22713
+ return null;
22714
+ }
22715
+ })
22716
+ .filter(
22717
+ (sig): sig is { guardianIndex: number; signature: Signature } =>
22718
+ sig !== null
22719
+ ); // Remove null values
22720
+
22721
+ let parsedVaa: VAA<'Uint8Array'>;
22722
+ try {
22723
+ parsedVaa = deserialize('Uint8Array', vaa);
22724
+ } catch (error) {
22725
+ throw new Error(`Error deserializing VAA: ${error}`);
22726
+ }
22727
+
22728
+ const outdatedGuardianIndexes = parsedVaa.signatures
22729
+ .filter(
22730
+ (vaaSig) =>
22731
+ !formattedSigs.some(
22732
+ (sig) => sig.guardianIndex === vaaSig.guardianIndex
22733
+ )
22734
+ )
22735
+ .map((sig) => sig.guardianIndex);
22736
+
22737
+ console.log('Outdated Guardian Indexes:', outdatedGuardianIndexes);
22738
+
22739
+ let updatedSignatures = parsedVaa.signatures.filter(
22740
+ (sig) => !outdatedGuardianIndexes.includes(sig.guardianIndex)
22741
+ );
22742
+
22743
+ const validReplacements = formattedSigs.filter(
22744
+ (sig) =>
22745
+ !updatedSignatures.some((s) => s.guardianIndex === sig.guardianIndex)
22746
+ );
22747
+
22748
+ // Check if we have enough valid signatures to replace outdated ones**
22749
+ if (outdatedGuardianIndexes.length > validReplacements.length) {
22750
+ console.warn(
22751
+ `Not enough valid replacement signatures! Need ${outdatedGuardianIndexes.length}, but only ${validReplacements.length} available.`
22752
+ );
22753
+ return;
22754
+ }
22755
+
22756
+ updatedSignatures = [
22757
+ ...updatedSignatures,
22758
+ ...validReplacements.slice(0, outdatedGuardianIndexes.length),
22759
+ ];
22760
+
22761
+ updatedSignatures.sort((a, b) => a.guardianIndex - b.guardianIndex);
22762
+
22763
+ const updatedVaa: VAA<'Uint8Array'> = {
22764
+ ...parsedVaa,
22765
+ guardianSet: guardianSetIndex,
22766
+ signatures: updatedSignatures,
22767
+ };
22768
+
22769
+ let patchedVaa: Uint8Array;
22770
+ try {
22771
+ patchedVaa = serialize(updatedVaa);
22772
+ } catch (error) {
22773
+ throw new Error(`Error serializing updated VAA: ${error}`);
22774
+ }
22775
+
22776
+ try {
22777
+ if (!(patchedVaa instanceof Uint8Array))
22778
+ throw new Error('Patched VAA is not a Uint8Array!');
22779
+
22780
+ const vaaHex = `0x${Buffer.from(patchedVaa).toString('hex')}`;
22781
+
22782
+ console.log('Sending updated VAA to RPC...');
22783
+
22784
+ const result = await axios.post(RPC, {
22785
+ jsonrpc: '2.0',
22786
+ id: 1,
22787
+ method: 'eth_call',
22788
+ params: [
22789
+ {
22790
+ from: null,
22791
+ to: ETH_CORE,
22792
+ data: eth.abi.encodeFunctionCall(PARSE_AND_VERIFY_VM_ABI, [vaaHex]),
22793
+ },
22794
+ 'latest',
22795
+ ],
22796
+ });
22797
+
22798
+ const verificationResult = result.data.result;
22799
+ console.log('Updated VAA (hex):', vaaHex);
22800
+ return verificationResult;
22801
+ } catch (error) {
22802
+ throw new Error(`Error sending updated VAA to RPC: ${error}`);
22803
+ }
22804
+ } catch (error) {
22805
+ console.error('Unexpected error in replaceSignatures:', error);
22806
+ }
22807
+ }
22808
+ ```
22809
+
22667
22810
## Create Script to Replace Outdated VAA Signatures
22668
22811
22669
22812
Now that we have all the necessary helper functions, we will create a script to automate replacing outdated VAA signatures. This script will retrieve a transaction’s VAA sequentially, check its validity, fetch the latest Guardian set, and update its signatures. By the end, it will output a correctly signed VAA that can be proposed for Guardian approval.
0 commit comments