Add Salvium fork mechanics: config schema and utility functions
Co-authored-by: t1amak <57602242+t1amak@users.noreply.github.com>
This commit is contained in:
27
config.json
27
config.json
@@ -257,6 +257,33 @@
|
|||||||
"currency": "USD"
|
"currency": "USD"
|
||||||
},
|
},
|
||||||
|
|
||||||
|
"salvium": {
|
||||||
|
"enabled": false,
|
||||||
|
"addressSeparator": "+",
|
||||||
|
"heights": {
|
||||||
|
"audit_phase1": 815,
|
||||||
|
"audit_phase2": 900,
|
||||||
|
"audit_phase3": 950,
|
||||||
|
"audit_complete": 1000,
|
||||||
|
"require_dual_login": 1050,
|
||||||
|
"carrot": 1100
|
||||||
|
},
|
||||||
|
"addressPrefixes": {
|
||||||
|
"cryptonote": {
|
||||||
|
"public": "0x3ef318",
|
||||||
|
"integrated": "0x55ef318",
|
||||||
|
"subaddress": "0xf5ef318"
|
||||||
|
},
|
||||||
|
"carrot": {
|
||||||
|
"public": "0x180c96",
|
||||||
|
"integrated": "0x2ccc96",
|
||||||
|
"subaddress": "0x314c96"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"carrotPoolAddress": "",
|
||||||
|
"carrotDonationAddress": ""
|
||||||
|
},
|
||||||
|
|
||||||
"charts": {
|
"charts": {
|
||||||
"pool": {
|
"pool": {
|
||||||
"hashrate": {
|
"hashrate": {
|
||||||
|
|||||||
@@ -28,6 +28,33 @@ if (!config.poolServer.paymentId.addressSeparator) config.poolServer.paymentId.a
|
|||||||
if (!config.payments.priority) config.payments.priority = 0;
|
if (!config.payments.priority) config.payments.priority = 0;
|
||||||
|
|
||||||
function runInterval () {
|
function runInterval () {
|
||||||
|
// Check for Salvium payout blackout
|
||||||
|
if (utils.isSalviumEnabled()) {
|
||||||
|
apiInterfaces.rpcDaemon('getblockcount', [], function (error, result) {
|
||||||
|
if (error) {
|
||||||
|
log('error', logSystem, 'Error getting block count for Salvium check: %j', [error]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let currentHeight = result.count - 1; // getblockcount returns height + 1
|
||||||
|
let salviumState = utils.getSalviumState(currentHeight);
|
||||||
|
|
||||||
|
if (salviumState === 'payout_blackout') {
|
||||||
|
log('info', logSystem, 'Salvium payout blackout active at height %d. Skipping payment processing.', [currentHeight]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Continue with normal payment processing
|
||||||
|
processSalviumAwarePayments(currentHeight);
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Non-Salvium payment processing
|
||||||
|
processSalviumAwarePayments(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
function processSalviumAwarePayments(currentHeight) {
|
||||||
async.waterfall([
|
async.waterfall([
|
||||||
|
|
||||||
// Get worker keys
|
// Get worker keys
|
||||||
@@ -141,15 +168,51 @@ function runInterval () {
|
|||||||
|
|
||||||
let address = worker;
|
let address = worker;
|
||||||
let payment_id = null;
|
let payment_id = null;
|
||||||
|
|
||||||
let with_payment_id = false;
|
let with_payment_id = false;
|
||||||
|
|
||||||
let addr = address.split(config.poolServer.paymentId.addressSeparator);
|
// Handle Salvium dual address and carrot switching
|
||||||
if ((addr.length === 1 && utils.isIntegratedAddress(address)) || addr.length >= 2) {
|
if (utils.isSalviumEnabled()) {
|
||||||
with_payment_id = true;
|
let salviumState = utils.getSalviumState(currentHeight);
|
||||||
if (addr.length >= 2) {
|
|
||||||
|
if (salviumState === 'carrot_payouts') {
|
||||||
|
// Switch to carrot address for payouts
|
||||||
|
let dualAddress = utils.parseSalviumDualAddress(worker);
|
||||||
|
if (dualAddress) {
|
||||||
|
address = dualAddress.carrot;
|
||||||
|
log('info', logSystem, 'Salvium: Sending payment to carrot address %s', [address]);
|
||||||
|
} else {
|
||||||
|
// For backwards compatibility, if no dual address, try to parse as single address
|
||||||
|
let addr = address.split(config.poolServer.paymentId.addressSeparator);
|
||||||
|
address = addr[0];
|
||||||
|
payment_id = addr[1] || null;
|
||||||
|
}
|
||||||
|
} else if (salviumState === 'dual_required') {
|
||||||
|
// Still pay to cryptonote address but parse dual format
|
||||||
|
let dualAddress = utils.parseSalviumDualAddress(worker);
|
||||||
|
if (dualAddress) {
|
||||||
|
address = dualAddress.cryptonote;
|
||||||
|
} else {
|
||||||
|
let addr = address.split(config.poolServer.paymentId.addressSeparator);
|
||||||
|
address = addr[0];
|
||||||
|
payment_id = addr[1] || null;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Normal payment processing for other heights
|
||||||
|
let addr = address.split(config.poolServer.paymentId.addressSeparator);
|
||||||
address = addr[0];
|
address = addr[0];
|
||||||
payment_id = addr[1];
|
payment_id = addr[1] || null;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Standard address parsing for non-Salvium coins
|
||||||
|
let addr = address.split(config.poolServer.paymentId.addressSeparator);
|
||||||
|
address = addr[0];
|
||||||
|
payment_id = addr[1] || null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Payment ID validation (existing logic)
|
||||||
|
if ((utils.isIntegratedAddress && utils.isIntegratedAddress(address)) || payment_id) {
|
||||||
|
with_payment_id = true;
|
||||||
|
if (payment_id) {
|
||||||
payment_id = payment_id.replace(/[^A-Za-z0-9]/g, '');
|
payment_id = payment_id.replace(/[^A-Za-z0-9]/g, '');
|
||||||
if (payment_id.length !== 16 && payment_id.length !== 64) {
|
if (payment_id.length !== 16 && payment_id.length !== 64) {
|
||||||
with_payment_id = false;
|
with_payment_id = false;
|
||||||
@@ -164,7 +227,7 @@ function runInterval () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (config.poolServer.fixedDiff && config.poolServer.fixedDiff.enabled) {
|
if (config.poolServer.fixedDiff && config.poolServer.fixedDiff.enabled) {
|
||||||
addr = address.split(config.poolServer.fixedDiff.addressSeparator);
|
let addr = address.split(config.poolServer.fixedDiff.addressSeparator);
|
||||||
if (addr.length >= 2) address = addr[0];
|
if (addr.length >= 2) address = addr[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
32
lib/pool.js
32
lib/pool.js
@@ -724,9 +724,35 @@ function handleMinerMethod (method, params, ip, portData, sendReply, pushMessage
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
addr = login.split(config.poolServer.paymentId.addressSeparator);
|
// Handle Salvium dual address login validation
|
||||||
address = addr[0] || null;
|
if (utils.isSalviumEnabled()) {
|
||||||
paymentId = addr[1] || null;
|
let currentHeight = currentBlockTemplate[0] ? currentBlockTemplate[0].height : 0;
|
||||||
|
let salviumState = utils.getSalviumState(currentHeight);
|
||||||
|
|
||||||
|
if (salviumState === 'dual_required' || salviumState === 'carrot_payouts') {
|
||||||
|
// Dual address required for these states
|
||||||
|
let dualAddress = utils.parseSalviumDualAddress(login);
|
||||||
|
if (!dualAddress) {
|
||||||
|
log('warn', logSystem, 'Dual address required for Salvium at height %d: %s', [currentHeight, login]);
|
||||||
|
sendReply('Dual address required. Format: [cryptonote_address][separator][carrot_address]');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
address = dualAddress.cryptonote; // Use cryptonote address for mining
|
||||||
|
// Store dual address info for payment processing
|
||||||
|
login = dualAddress.original;
|
||||||
|
} else {
|
||||||
|
// Normal address parsing for earlier heights
|
||||||
|
addr = login.split(config.poolServer.paymentId.addressSeparator);
|
||||||
|
address = addr[0] || null;
|
||||||
|
paymentId = addr[1] || null;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Standard address parsing for non-Salvium coins
|
||||||
|
addr = login.split(config.poolServer.paymentId.addressSeparator);
|
||||||
|
address = addr[0] || null;
|
||||||
|
paymentId = addr[1] || null;
|
||||||
|
}
|
||||||
|
|
||||||
if (!address) {
|
if (!address) {
|
||||||
log('warn', logSystem, 'No address specified for login');
|
log('warn', logSystem, 'No address specified for login');
|
||||||
sendReply('Invalid address used for login');
|
sendReply('Invalid address used for login');
|
||||||
|
|||||||
85
lib/utils.js
85
lib/utils.js
@@ -46,6 +46,13 @@ exports.getAddressPrefix = getAddressPrefix;
|
|||||||
|
|
||||||
// Validate miner address
|
// Validate miner address
|
||||||
exports.validateMinerAddress = function (address) {
|
exports.validateMinerAddress = function (address) {
|
||||||
|
// First check if this is a Salvium pool and use Salvium validation
|
||||||
|
if (isSalviumEnabled()) {
|
||||||
|
return validateSalviumAddress(address, 'cryptonote') ||
|
||||||
|
validateSalviumAddress(address, 'carrot');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Default validation for other coins
|
||||||
let addressPrefix = getAddressPrefix(address);
|
let addressPrefix = getAddressPrefix(address);
|
||||||
if (addressPrefix === addressBase58Prefix) return true;
|
if (addressPrefix === addressBase58Prefix) return true;
|
||||||
else if (addressPrefix === integratedAddressBase58Prefix) return true;
|
else if (addressPrefix === integratedAddressBase58Prefix) return true;
|
||||||
@@ -183,3 +190,81 @@ exports.ringBuffer = function (maxSize) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Salvium-specific utility functions
|
||||||
|
**/
|
||||||
|
|
||||||
|
// Check if Salvium functionality is enabled
|
||||||
|
function isSalviumEnabled() {
|
||||||
|
return config.salvium && config.salvium.enabled === true &&
|
||||||
|
(config.coin === 'Salvium' || config.symbol === 'SAL' || config.symbol === 'SAL1');
|
||||||
|
}
|
||||||
|
exports.isSalviumEnabled = isSalviumEnabled;
|
||||||
|
|
||||||
|
// Get current Salvium state based on block height
|
||||||
|
function getSalviumState(height) {
|
||||||
|
if (!isSalviumEnabled() || !height) return 'disabled';
|
||||||
|
|
||||||
|
if (height >= config.salvium.heights.carrot) return 'carrot_payouts';
|
||||||
|
if (height >= config.salvium.heights.require_dual_login) return 'dual_required';
|
||||||
|
if (height >= config.salvium.heights.audit_complete) return 'payout_resume';
|
||||||
|
if (height >= config.salvium.heights.audit_phase1) return 'payout_blackout';
|
||||||
|
return 'normal';
|
||||||
|
}
|
||||||
|
exports.getSalviumState = getSalviumState;
|
||||||
|
|
||||||
|
// Validate Salvium address with specific prefixes
|
||||||
|
function validateSalviumAddress(address, type) {
|
||||||
|
if (!isSalviumEnabled() || !address) return false;
|
||||||
|
|
||||||
|
let addressPrefix = getAddressPrefix(address);
|
||||||
|
if (!addressPrefix) return false;
|
||||||
|
|
||||||
|
let prefixes = config.salvium.addressPrefixes[type];
|
||||||
|
if (!prefixes) return false;
|
||||||
|
|
||||||
|
return addressPrefix === parseInt(prefixes.public, 16) ||
|
||||||
|
addressPrefix === parseInt(prefixes.integrated, 16) ||
|
||||||
|
addressPrefix === parseInt(prefixes.subaddress, 16);
|
||||||
|
}
|
||||||
|
exports.validateSalviumAddress = validateSalviumAddress;
|
||||||
|
|
||||||
|
// Parse dual address for Salvium
|
||||||
|
function parseSalviumDualAddress(login) {
|
||||||
|
if (!isSalviumEnabled()) return null;
|
||||||
|
|
||||||
|
let separator = config.salvium.addressSeparator || config.poolServer.paymentId.addressSeparator;
|
||||||
|
let parts = login.split(separator);
|
||||||
|
|
||||||
|
if (parts.length < 2) return null;
|
||||||
|
|
||||||
|
let cryptonoteAddress = parts[0];
|
||||||
|
let carrotAddress = parts[1];
|
||||||
|
|
||||||
|
// Validate both addresses
|
||||||
|
if (!validateSalviumAddress(cryptonoteAddress, 'cryptonote') ||
|
||||||
|
!validateSalviumAddress(carrotAddress, 'carrot')) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
cryptonote: cryptonoteAddress,
|
||||||
|
carrot: carrotAddress,
|
||||||
|
original: login
|
||||||
|
};
|
||||||
|
}
|
||||||
|
exports.parseSalviumDualAddress = parseSalviumDualAddress;
|
||||||
|
|
||||||
|
// Get appropriate pool address based on current height
|
||||||
|
function getSalviumPoolAddress(height) {
|
||||||
|
if (!isSalviumEnabled()) return config.poolServer.poolAddress;
|
||||||
|
|
||||||
|
let state = getSalviumState(height);
|
||||||
|
if (state === 'carrot_payouts' && config.salvium.carrotPoolAddress) {
|
||||||
|
return config.salvium.carrotPoolAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
return config.poolServer.poolAddress;
|
||||||
|
}
|
||||||
|
exports.getSalviumPoolAddress = getSalviumPoolAddress;
|
||||||
|
|||||||
Reference in New Issue
Block a user