@@ -18,6 +18,26 @@ const __dirname = path.dirname(__filename);
1818const ALGO = "aes-256-gcm" ;
1919const IV_LENGTH = 12 ;
2020
21+ // --- Master Keys ---
22+ const MASTER_KEY = process . env . MASTER_KEY ;
23+ const BACKUP_KEYS = ( process . env . BACKUP_KEYS || "" )
24+ . split ( "," )
25+ . map ( k => k . trim ( ) )
26+ . filter ( Boolean ) ;
27+
28+ if ( ! MASTER_KEY ) {
29+ console . error ( chalk . bgRed . white . bold ( "❌ MASTER_KEY environment variable is not set!" ) ) ;
30+ process . exit ( 1 ) ;
31+ }
32+
33+ const ALL_MASTER_KEYS = [ MASTER_KEY , ...BACKUP_KEYS ] ;
34+
35+ // --- Session Salt for Stronger Key Derivation ---
36+ const sessionSalt = crypto . randomBytes ( 16 ) ;
37+ function deriveKey ( masterKey ) {
38+ return crypto . scryptSync ( masterKey , sessionSalt , 32 ) ;
39+ }
40+
2141/**
2242 * Encrypts a private key using a master key.
2343 * @param {string } privateKey - The private key to encrypt.
@@ -26,7 +46,7 @@ const IV_LENGTH = 12;
2646 */
2747function encryptPrivateKey ( privateKey , masterKey ) {
2848 const iv = crypto . randomBytes ( IV_LENGTH ) ;
29- const derivedKey = crypto . scryptSync ( masterKey , 'salt' , 32 ) ;
49+ const derivedKey = deriveKey ( masterKey ) ;
3050 const cipher = crypto . createCipheriv ( ALGO , derivedKey , iv ) ;
3151
3252 let encrypted = cipher . update ( privateKey , "utf8" , "hex" ) ;
@@ -46,7 +66,7 @@ function decryptPrivateKey(encrypted, masterKey) {
4666 const [ ivHex , authTagHex , data ] = encrypted . split ( ":" ) ;
4767 const iv = Buffer . from ( ivHex , "hex" ) ;
4868 const authTag = Buffer . from ( authTagHex , "hex" ) ;
49- const derivedKey = crypto . scryptSync ( masterKey , 'salt' , 32 ) ;
69+ const derivedKey = deriveKey ( masterKey ) ;
5070 const decipher = crypto . createDecipheriv ( ALGO , derivedKey , iv ) ;
5171 decipher . setAuthTag ( authTag ) ;
5272
@@ -56,9 +76,27 @@ function decryptPrivateKey(encrypted, masterKey) {
5676 return decrypted ;
5777}
5878
79+ /**
80+ * Attempts to decrypt an encrypted key with any of the available master keys.
81+ * @param {string } encrypted - The encrypted key string.
82+ * @returns {string } The decrypted private key.
83+ * @throws {Error } If decryption fails with all keys.
84+ */
85+ function decryptWithAnyKey ( encrypted ) {
86+ for ( const key of ALL_MASTER_KEYS ) {
87+ try {
88+ return decryptPrivateKey ( encrypted , key ) ;
89+ } catch {
90+ continue ;
91+ }
92+ }
93+ throw new Error ( "❌ Failed to decrypt private key with all available master keys" ) ;
94+ }
95+
5996// === CONFIG ===
6097// List of public RPCs for Celo.
6198const RPCS = [
99+ "https://celo-mainnet.infura.io/v3/f0c6b3797dd54dc2aa91cd4a463bcc57" ,
62100 "https://rpc.ankr.com/celo" ,
63101 "https://celo.drpc.org" ,
64102 "https://forno.celo.org" ,
@@ -73,13 +111,6 @@ let lastKey = null;
73111let ENCRYPTED_KEYS = [ ] ;
74112let ALL_WALLETS = [ ] ;
75113
76- // === NEW: Master Key from Environment ===
77- const MASTER_KEY = process . env . MASTER_KEY ;
78- if ( ! MASTER_KEY ) {
79- console . error ( chalk . bgRed . white . bold ( "❌ MASTER_KEY environment variable is not set!" ) ) ;
80- process . exit ( 1 ) ;
81- }
82-
83114// normalize to 0x-prefixed hex string
84115function normalizeKey ( k ) {
85116 if ( ! k ) return null ;
@@ -252,7 +283,7 @@ setInterval(flushTxLog, FLUSH_INTERVAL);
252283function pickRandomKey ( ) {
253284 const idx = Math . floor ( Math . random ( ) * ENCRYPTED_KEYS . length ) ;
254285 const encrypted = ENCRYPTED_KEYS [ idx ] ;
255- const privateKey = decryptPrivateKey ( encrypted , MASTER_KEY ) ;
286+ const privateKey = decryptWithAnyKey ( encrypted ) ;
256287 return privateKey ;
257288}
258289
@@ -538,8 +569,8 @@ async function main() {
538569 // === END NEW LOGIC ===
539570
540571 // Get the decrypted private key and create a new wallet instance for the transaction
541- const key = pickRandomKey ( ) ;
542- const wallet = new ethers . Wallet ( key , provider ) ;
572+ let key = pickRandomKey ( ) ;
573+ let wallet = new ethers . Wallet ( key , provider ) ;
543574 const profile = ensurePersona ( wallet ) ;
544575
545576 // === NEW: Main loop modification ===
@@ -551,6 +582,10 @@ async function main() {
551582 // Execute the transaction logic, including retries
552583 await safeSendTx ( wallet , provider , profile , url ) ;
553584
585+ // Explicit memory wipe after use
586+ key = null ;
587+ wallet = null ;
588+
554589 // NEW LOGIC: Use persona's avgWait for the wait loop
555590 let waitSec = Math . floor ( profile . avgWait * ( 0.8 + Math . random ( ) * 0.4 ) ) ;
556591
0 commit comments