Commit 7652270f authored by Eriksson Monteiro's avatar Eriksson Monteiro

update millix node

parent 4d0547f8
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
<br> <br>
<a href="#"><img src="https://github.com/millix/millix-wallet/blob/master/app/icon.png?raw=true" alt="millix node" width="200"></a> <a href="#"><img src="https://github.com/millix/millix-wallet/blob/master/app/icon.png?raw=true" alt="millix node" width="200"></a>
<br> <br>
millix node <small>v1.10.7</small> millix node <small>v1.10.10</small>
<br> <br>
</h1> </h1>
......
...@@ -774,10 +774,10 @@ export const NETWORK_SHORT_TIME_WAIT_MAX = 1500; ...@@ -774,10 +774,10 @@ export const NETWORK_SHORT_TIME_WAIT_MAX = 1500;
export const DATABASE_ENGINE = 'sqlite'; export const DATABASE_ENGINE = 'sqlite';
export const DATABASE_CONNECTION = {}; export const DATABASE_CONNECTION = {};
export const MILLIX_CIRCULATION = 9e15; export const MILLIX_CIRCULATION = 9e15;
export const NODE_MILLIX_BUILD_DATE = 1622937315; export const NODE_MILLIX_BUILD_DATE = 1624026768;
export const NODE_MILLIX_VERSION = '1.10.9-tangled'; export const NODE_MILLIX_VERSION = '1.10.10';
export const DATA_BASE_DIR_MAIN_NETWORK = './millix-tangled'; export const DATA_BASE_DIR_MAIN_NETWORK = './millix';
export const DATA_BASE_DIR_TEST_NETWORK = './millix-tangled'; export const DATA_BASE_DIR_TEST_NETWORK = './millix-testnet';
let DATA_BASE_DIR = MODE_TEST_NETWORK ? DATA_BASE_DIR_TEST_NETWORK : DATA_BASE_DIR_MAIN_NETWORK; let DATA_BASE_DIR = MODE_TEST_NETWORK ? DATA_BASE_DIR_TEST_NETWORK : DATA_BASE_DIR_MAIN_NETWORK;
export const NODE_KEY_PATH = DATA_BASE_DIR + '/node.json'; export const NODE_KEY_PATH = DATA_BASE_DIR + '/node.json';
export const NODE_CERTIFICATE_KEY_PATH = DATA_BASE_DIR + '/node_certificate_key.pem'; export const NODE_CERTIFICATE_KEY_PATH = DATA_BASE_DIR + '/node_certificate_key.pem';
......
...@@ -118,35 +118,42 @@ export class WalletSync { ...@@ -118,35 +118,42 @@ export class WalletSync {
return callback(); //something was wrong skip this output. return callback(); //something was wrong skip this output.
} }
database.firstShardZeroORShardRepository('transaction', shardID, (transactionRepository) => { database.applyShards(shardID => {
return transactionRepository.getTransactionInput({ const transactionRepository = database.getRepository('transaction');
return transactionRepository.listTransactionInput({
output_transaction_id: transactionID, output_transaction_id: transactionID,
output_shard_id : shardID, output_shard_id : shardID,
output_position : outputPosition output_position : outputPosition
}).then(input => { }).then(inputList => {
if (input) { const spendingInputs = [];
return new Promise((resolve) => {
async.eachSeries(inputList, (input, callbackInput) => {
/* check if there is any input that is double spend. /* check if there is any input that is double spend.
if so, we should force updating this transaction output as spent. if so, we should force updating this transaction output as spent.
*/ */
return transactionRepository.listTransactionInput({ transactionRepository.listTransactionInput({
'transaction_input.transaction_id' : input.transaction_id, 'transaction_input.transaction_id': input.transaction_id,
is_double_spend: 1 is_double_spend : 1
}).then(doubleSpendInputList => { }).then(doubleSpendInputList => {
if (doubleSpendInputList.length > 0) { if (doubleSpendInputList.length > 0) {
return Promise.reject(); return callbackInput();
} }
return transactionRepository.getTransaction(input.transaction_id); return transactionRepository.getTransaction(input.transaction_id)
}); .then(transaction => {
} if (transaction && transaction.status !== 3) {
else { spendingInputs.push(transaction);
return Promise.reject();
} }
callbackInput();
});
});
}, () => resolve(spendingInputs));
});
}); });
}).then(spendingTransaction => { }).then(spendingTransactionList => {
// skip if we already know that the tx is spent // skip if we already know that the tx is spent
if (spendingTransaction) { if (spendingTransactionList.length > 0) {
return database.applyShardZeroAndShardRepository('transaction', shardID, transactionRepository => { return database.applyShardZeroAndShardRepository('transaction', shardID, transactionRepository => {
return transactionRepository.updateTransactionOutput(transactionID, outputPosition, spendingTransaction.transaction_date); return transactionRepository.updateTransactionOutput(transactionID, outputPosition, _.min(_.map(spendingTransactionList, spendingInput => spendingInput.transaction_date)));
}).then(() => { }).then(() => {
callback(); callback();
}); });
......
...@@ -153,9 +153,9 @@ export class WalletTransactionConsensus { ...@@ -153,9 +153,9 @@ export class WalletTransactionConsensus {
_updateDoubleSpendTransaction(transactions, doubleSpendTransactionInput) { _updateDoubleSpendTransaction(transactions, doubleSpendTransactionInput) {
console.log('[consensus][oracle] setting ', transactions.length, ' transaction as double spend'); console.log('[consensus][oracle] setting ', transactions.length, ' transaction as double spend');
async.eachSeries(transactions, (transactionID, callback) => { async.eachSeries(transactions, (transaction, callback) => {
database.getRepository('transaction') database.getRepository('transaction')
.setTransactionAsDoubleSpend(transactionID, doubleSpendTransactionInput) .setTransactionAsDoubleSpend(transaction, doubleSpendTransactionInput)
.then(() => callback()); .then(() => callback());
}); });
} }
...@@ -171,10 +171,9 @@ export class WalletTransactionConsensus { ...@@ -171,10 +171,9 @@ export class WalletTransactionConsensus {
} }
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
(() => transaction ? Promise.resolve([ (() => transaction ? Promise.resolve(transaction) :
transaction, this._transactionObjectCache[transactionID] ? Promise.resolve(this._transactionObjectCache[transactionID]) :
transaction.shard_id database.firstShards((shardID) => {
]) : database.firstShards((shardID) => {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const transactionRepository = database.getRepository('transaction', shardID); const transactionRepository = database.getRepository('transaction', shardID);
transactionRepository.getTransactionObject(transactionID) transactionRepository.getTransactionObject(transactionID)
...@@ -193,21 +192,14 @@ export class WalletTransactionConsensus { ...@@ -193,21 +192,14 @@ export class WalletTransactionConsensus {
message : 'invalid transaction found: ' + transactionID message : 'invalid transaction found: ' + transactionID
}); });
} }
else if (transaction && transaction.is_stable && _.some(transaction.transaction_output_list, output => output.is_double_spend === 1) ||
if (transaction && transaction.is_stable !== undefined) { // transaction object needs to be normalized doubleSpendSet.has(transactionID)) {
transaction = database.getRepository('transaction').normalizeTransactionObject(transaction);
}
if (!transaction) {
return reject({ return reject({
cause : 'transaction_not_found', cause : 'transaction_double_spend',
transaction_id_fail: transactionID, transaction_id_fail: transactionID,
message : 'no information found for ' + transactionID message : 'double spend found in ' + transactionID
}); });
} }
else if (transaction.transaction_id === genesisConfig.genesis_transaction) {
return resolve();
}
else if (depth === config.CONSENSUS_VALIDATION_REQUEST_DEPTH_MAX) { else if (depth === config.CONSENSUS_VALIDATION_REQUEST_DEPTH_MAX) {
return reject({ return reject({
cause : 'transaction_validation_max_depth', cause : 'transaction_validation_max_depth',
...@@ -215,17 +207,25 @@ export class WalletTransactionConsensus { ...@@ -215,17 +207,25 @@ export class WalletTransactionConsensus {
message : `not validated in a depth of ${depth}` message : `not validated in a depth of ${depth}`
}); });
} }
else if (doubleSpendSet.has(transactionID)) { else if (transaction && transaction.transaction_id === genesisConfig.genesis_transaction) {
return reject({ return resolve();
cause : 'transaction_double_spend',
transaction_id_fail: transactionID,
message : 'double spend found in ' + transactionID
});
} }
else if (transactionVisitedSet.has(transactionID)) { else if (transactionVisitedSet.has(transactionID)) {
return resolve(); return resolve();
} }
if (transaction && transaction.is_stable !== undefined) { // transaction object needs to be normalized
transaction = database.getRepository('transaction').normalizeTransactionObject(transaction);
}
if (!transaction) {
return reject({
cause : 'transaction_not_found',
transaction_id_fail: transactionID,
message : 'no information found for ' + transactionID
});
}
walletUtils.verifyTransaction(transaction) walletUtils.verifyTransaction(transaction)
.then(valid => { .then(valid => {
if (!valid) { if (!valid) {
...@@ -255,7 +255,7 @@ export class WalletTransactionConsensus { ...@@ -255,7 +255,7 @@ export class WalletTransactionConsensus {
(() => { (() => {
if (!transactionVisitedSet.has(input.output_transaction_id)) { if (!transactionVisitedSet.has(input.output_transaction_id)) {
sourceTransactions.add(input.output_transaction_id); sourceTransactions.add(input);
return database.applyShards((shardID) => database.getRepository('transaction', shardID).getInputDoubleSpend(input, transaction.transaction_id)).then(data => data || []); return database.applyShards((shardID) => database.getRepository('transaction', shardID).getInputDoubleSpend(input, transaction.transaction_id)).then(data => data || []);
} }
else { else {
...@@ -310,14 +310,7 @@ export class WalletTransactionConsensus { ...@@ -310,14 +310,7 @@ export class WalletTransactionConsensus {
} }
}); });
}).then(() => { }).then(() => {
// get /* get the total millix amount of this input */
// the
// total
// millix
// amount
// of
// this
// input
database.firstShards((shardID) => { database.firstShards((shardID) => {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
if (this._transactionObjectCache[input.output_transaction_id]) { if (this._transactionObjectCache[input.output_transaction_id]) {
...@@ -370,8 +363,7 @@ export class WalletTransactionConsensus { ...@@ -370,8 +363,7 @@ export class WalletTransactionConsensus {
}); });
} }
// compare input and output /* compare input and output amount */
// amount
let outputTotalAmount = 0; let outputTotalAmount = 0;
_.each(transaction.transaction_output_list, output => { _.each(transaction.transaction_output_list, output => {
outputTotalAmount += output.amount; outputTotalAmount += output.amount;
...@@ -388,9 +380,14 @@ export class WalletTransactionConsensus { ...@@ -388,9 +380,14 @@ export class WalletTransactionConsensus {
// check inputs transactions // check inputs transactions
async.everySeries(sourceTransactions, (srcTransaction, callback) => { async.everySeries(sourceTransactions, (srcTransaction, callback) => {
this._validateTransaction(this._transactionObjectCache[srcTransaction] || srcTransaction, nodeID, depth + 1, transactionVisitedSet, doubleSpendSet) this._validateTransaction(this._transactionObjectCache[srcTransaction.output_transaction_id] || srcTransaction.output_transaction_id, nodeID, depth + 1, transactionVisitedSet, doubleSpendSet)
.then(() => callback(null, true)) .then(() => callback(null, true))
.catch((err) => callback(err, false)); .catch((err) => {
if (err && err.cause === 'transaction_double_spend' && !err.transaction_input_double_spend) {
this._updateDoubleSpendTransaction([transaction], srcTransaction);
}
callback(err, false);
});
}, (err, valid) => { }, (err, valid) => {
if (err && !valid) { if (err && !valid) {
return reject(err); return reject(err);
...@@ -867,7 +864,7 @@ export class WalletTransactionConsensus { ...@@ -867,7 +864,7 @@ export class WalletTransactionConsensus {
this._transactionValidationRejected.add(transactionID); this._transactionValidationRejected.add(transactionID);
delete this._validationPrepareState[transactionID]; delete this._validationPrepareState[transactionID];
} }
else if (err.cause === 'transaction_invalid') { else if (err.cause === 'transaction_invalid' || err.cause === 'transaction_invalid_amount') {
wallet.findAndSetAllSpendersAsInvalid({transaction_id: err.transaction_id_fail}) wallet.findAndSetAllSpendersAsInvalid({transaction_id: err.transaction_id_fail})
.then(_ => _); .then(_ => _);
this._transactionValidationRejected.add(transactionID); this._transactionValidationRejected.add(transactionID);
......
...@@ -561,7 +561,8 @@ class WalletUtils { ...@@ -561,7 +561,8 @@ class WalletUtils {
} }
else { else {
// before 1620603935 the refresh time was 3 days // before 1620603935 the refresh time was 3 days
// now the refresh time is 10 min (TRANSACTION_OUTPUT_EXPIRE_OLDER_THAN) // now the refresh time is 10 min
// (TRANSACTION_OUTPUT_EXPIRE_OLDER_THAN)
const expireMinutes = transactionDate.getTime() <= 1620603935000 ? 4320 : config.TRANSACTION_OUTPUT_EXPIRE_OLDER_THAN; const expireMinutes = transactionDate.getTime() <= 1620603935000 ? 4320 : config.TRANSACTION_OUTPUT_EXPIRE_OLDER_THAN;
let maximumOldestDate = new Date(transactionDate.getTime()); let maximumOldestDate = new Date(transactionDate.getTime());
maximumOldestDate.setMinutes(maximumOldestDate.getMinutes() - expireMinutes); maximumOldestDate.setMinutes(maximumOldestDate.getMinutes() - expireMinutes);
...@@ -632,7 +633,7 @@ class WalletUtils { ...@@ -632,7 +633,7 @@ class WalletUtils {
const outputUsedInTransaction = new Set(); const outputUsedInTransaction = new Set();
for (let i = 0; i < transaction.transaction_input_list.length; i++) { for (let i = 0; i < transaction.transaction_input_list.length; i++) {
const input = transaction.transaction_input_list[i]; const input = transaction.transaction_input_list[i];
const outputID = input.output_transaction_id + ":" + input.output_position; const outputID = input.output_transaction_id + ':' + input.output_position;
if (!this.isValidAddress(input.address_base) if (!this.isValidAddress(input.address_base)
|| !this.isValidAddress(input.address_key_identifier) || !this.isValidAddress(input.address_key_identifier)
|| !addressRepository.supportedVersionSet.has(input.address_version) || !addressRepository.supportedVersionSet.has(input.address_version)
...@@ -805,10 +806,7 @@ class WalletUtils { ...@@ -805,10 +806,7 @@ class WalletUtils {
address_attribute: addressAttributeMap[addressBase] address_attribute: addressAttributeMap[addressBase]
})); }));
return resolve(signatureList); return resolve(signatureList);
})) })).then(signatureList => this.isConsumingExpiredOutputs(inputList, maximumOldestDate).then(isConsumingExpiredOutputs => [
.then((signatureList) => peer.getNodeAddress()
.then(() => signatureList))
.then(signatureList => this.isConsumingExpiredOutputs(inputList, maximumOldestDate).then(isConsumingExpiredOutputs => [
signatureList, signatureList,
isConsumingExpiredOutputs isConsumingExpiredOutputs
])) ]))
...@@ -867,7 +865,7 @@ class WalletUtils { ...@@ -867,7 +865,7 @@ class WalletUtils {
let signature; let signature;
for (let transactionSignature of signatureList) { for (let transactionSignature of signatureList) {
if(transactionSignature.address_base === refreshOutput.address_base){ if (transactionSignature.address_base === refreshOutput.address_base) {
signature = _.cloneDeep(transactionSignature); signature = _.cloneDeep(transactionSignature);
break; break;
} }
......
...@@ -702,7 +702,7 @@ class Wallet { ...@@ -702,7 +702,7 @@ class Wallet {
delete this._transactionRequested[transaction.transaction_id]; delete this._transactionRequested[transaction.transaction_id];
delete this._transactionFundingActiveWallet[transaction.transaction_id]; delete this._transactionFundingActiveWallet[transaction.transaction_id];
walletSync.removeTransactionSync(transaction.transaction_id); walletSync.removeTransactionSync(transaction.transaction_id);
return false; // return false;
} }
const isFundingWallet = !!this._transactionFundingActiveWallet[transaction.transaction_id]; const isFundingWallet = !!this._transactionFundingActiveWallet[transaction.transaction_id];
...@@ -891,6 +891,7 @@ class Wallet { ...@@ -891,6 +891,7 @@ class Wallet {
markAllSpendersAsInvalid(spenders) { markAllSpendersAsInvalid(spenders) {
let spendersByShard = {}; let spendersByShard = {};
let spendersSet = new Set();
for (let spender of spenders) { for (let spender of spenders) {
const shardID = spender.shard_id || genesisConfig.genesis_shard_id; const shardID = spender.shard_id || genesisConfig.genesis_shard_id;
...@@ -899,6 +900,7 @@ class Wallet { ...@@ -899,6 +900,7 @@ class Wallet {
} }
spendersByShard[shardID].push(spender.transaction_id); spendersByShard[shardID].push(spender.transaction_id);
spendersSet.add(spender.transaction_id);
} }
return new Promise((resolve) => { return new Promise((resolve) => {
...@@ -915,10 +917,63 @@ class Wallet { ...@@ -915,10 +917,63 @@ class Wallet {
return transactionRepository.markTransactionsAsInvalid(transactionIDList); return transactionRepository.markTransactionsAsInvalid(transactionIDList);
}).then(() => { }).then(() => {
console.log(`[wallet] set transactions ${transactionIDList} as invalid`); console.log(`[wallet] set transactions ${transactionIDList} as invalid`);
chunkCallback();
}).catch((err) => { }).catch((err) => {
console.log(`[wallet] error while marking transactions as invalid: ${err}`); console.log(`[wallet] error while marking transactions as invalid: ${err}`);
chunkCallback(); }).then(() => {
async.eachSeries(transactionIDList, (transactionID, callbackTransaction) => {
// get all inputs
database.firstShardORShardZeroRepository('transaction', shardID, transactionRepository => {
return transactionRepository.getTransactionInputs(transactionID)
.then(inputs => !inputs || inputs.length === 0 ? Promise.reject() : inputs);
}).then(transactionInputList => {
/* check if this the output spent in this input should be reset */
async.eachSeries(transactionInputList, (transactionInput, callbackInput) => {
/* if this output is invalid too we dont reset it */
if (spendersSet.has(transactionInput.output_transaction_id)) {
return callbackInput();
}
/* get information about the transaction that generated this input */
database.firstShardORShardZeroRepository('transaction', transactionInput.output_shard_id, transactionRepository => {
return transactionRepository.getTransaction(transactionInput.output_transaction_id, transactionInput.output_shard_id)
.then(transaction => transaction || Promise.reject());
}).then(transaction => {
if (!transaction || transaction.status === 3) {
/* the transaction was not found or it's invalid*/
return callbackInput();
}
/* if the transaction is a double spend we dont reset the output state */
database.firstShardORShardZeroRepository('transaction', transaction.shard_id, transactionRepository => {
return transactionRepository.getTransactionOutput({
transaction_id : transaction.transaction_id,
is_double_spend: 1
}).then(output => output || Promise.reject());
}).then(doubleSpentTransactionOutput => {
if (doubleSpentTransactionOutput) {
/* there is a double spend output. skip this transaction*/
return callbackInput();
}
/* we should reset the spend status of the output if there is no other tx spending it */
database.applyShards(shardID => {
return database.getRepository('transaction', shardID).getTransactionSpenders(transactionInput.output_transaction_id, transactionInput.output_position);
}).then(transactionSpenders => {
if (transactionSpenders.length > 1) {
/* skip this output. there is another transaction spending it */
return callbackInput();
}
/* set the transaction output as unspent because the spender was an invalid transaction */
database.applyShardZeroAndShardRepository('transaction', transactionInput.output_shard_id, transactionRepository => {
return transactionRepository.updateTransactionOutput(transactionInput.output_transaction_id, transactionInput.output_position, null);
}).then(() => {
callbackInput();
});
});
});
});
}, () => callbackTransaction());
});
}, () => chunkCallback());
}); });
}, () => callback()); }, () => callback());
}, () => { }, () => {
...@@ -1979,7 +2034,8 @@ class Wallet { ...@@ -1979,7 +2034,8 @@ class Wallet {
'proxy_network_error', 'proxy_network_error',
'proxy_timeout', 'proxy_timeout',
'invalid_proxy_transaction_chain', 'invalid_proxy_transaction_chain',
'proxy_connection_state_invalid' 'proxy_connection_state_invalid',
'transaction_proxy_rejected'
]; ];
return transactionRepository.getPeersAsProxyCandidate(_.uniq(_.map(network.registeredClients, ws => ws.nodeID))) return transactionRepository.getPeersAsProxyCandidate(_.uniq(_.map(network.registeredClients, ws => ws.nodeID)))
.then(proxyCandidates => { .then(proxyCandidates => {
...@@ -1994,7 +2050,7 @@ class Wallet { ...@@ -1994,7 +2050,7 @@ class Wallet {
error : true, error : true,
message: e message: e
}) : callback()); }) : callback());
}, data => data.error && typeof data.message === 'string' && !proxyErrorList.includes(data.message) ? reject(data.message) : }, data => data && data.error && typeof data.message === 'string' && !proxyErrorList.includes(data.message) ? reject(data.message) :
data && data.transaction ? resolve(data.transaction) : reject('proxy_not_found')); data && data.transaction ? resolve(data.transaction) : reject('proxy_not_found'));
}); });
}); });
...@@ -2116,7 +2172,7 @@ class Wallet { ...@@ -2116,7 +2172,7 @@ class Wallet {
eventBus.removeAllListeners('transaction_sync_response'); eventBus.removeAllListeners('transaction_sync_response');
eventBus.removeAllListeners('transaction_sync_by_date_response'); eventBus.removeAllListeners('transaction_sync_by_date_response');
eventBus.removeAllListeners('shard_sync_request'); eventBus.removeAllListeners('shard_sync_request');
eventBus.removeAllListeners('address_transaction_sync'); eventBus.removeAllListeners('wallet_transaction_sync');
eventBus.removeAllListeners('transaction_validation_request'); eventBus.removeAllListeners('transaction_validation_request');
eventBus.removeAllListeners('transaction_validation_response'); eventBus.removeAllListeners('transaction_validation_response');
eventBus.removeAllListeners('transaction_spend_request'); eventBus.removeAllListeners('transaction_spend_request');
......
...@@ -107,6 +107,5 @@ db.initialize() ...@@ -107,6 +107,5 @@ db.initialize()
console.log('registered new genesis: ', genesisConfig.genesis_transaction); console.log('registered new genesis: ', genesisConfig.genesis_transaction);
}); });
} }
}) });
.then(() => setTimeout(() => wallet.syncAddresses(), 2000)); //millix v1.10.10-tangled
//millix v1.10.9-tangled
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment