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 @@
<br>
<a href="#"><img src="https://github.com/millix/millix-wallet/blob/master/app/icon.png?raw=true" alt="millix node" width="200"></a>
<br>
millix node <small>v1.10.7</small>
millix node <small>v1.10.10</small>
<br>
</h1>
......
......@@ -774,10 +774,10 @@ export const NETWORK_SHORT_TIME_WAIT_MAX = 1500;
export const DATABASE_ENGINE = 'sqlite';
export const DATABASE_CONNECTION = {};
export const MILLIX_CIRCULATION = 9e15;
export const NODE_MILLIX_BUILD_DATE = 1622937315;
export const NODE_MILLIX_VERSION = '1.10.9-tangled';
export const DATA_BASE_DIR_MAIN_NETWORK = './millix-tangled';
export const DATA_BASE_DIR_TEST_NETWORK = './millix-tangled';
export const NODE_MILLIX_BUILD_DATE = 1624026768;
export const NODE_MILLIX_VERSION = '1.10.10';
export const DATA_BASE_DIR_MAIN_NETWORK = './millix';
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;
export const NODE_KEY_PATH = DATA_BASE_DIR + '/node.json';
export const NODE_CERTIFICATE_KEY_PATH = DATA_BASE_DIR + '/node_certificate_key.pem';
......
......@@ -118,35 +118,42 @@ export class WalletSync {
return callback(); //something was wrong skip this output.
}
database.firstShardZeroORShardRepository('transaction', shardID, (transactionRepository) => {
return transactionRepository.getTransactionInput({
database.applyShards(shardID => {
const transactionRepository = database.getRepository('transaction');
return transactionRepository.listTransactionInput({
output_transaction_id: transactionID,
output_shard_id : shardID,
output_position : outputPosition
}).then(input => {
if (input) {
/* check if there is any input that is double spend.
if so, we should force updating this transaction output as spent.
*/
return transactionRepository.listTransactionInput({
'transaction_input.transaction_id' : input.transaction_id,
is_double_spend: 1
}).then(doubleSpendInputList => {
if (doubleSpendInputList.length > 0) {
return Promise.reject();
}
return transactionRepository.getTransaction(input.transaction_id);
});
}
else {
return Promise.reject();
}
}).then(inputList => {
const spendingInputs = [];
return new Promise((resolve) => {
async.eachSeries(inputList, (input, callbackInput) => {
/* check if there is any input that is double spend.
if so, we should force updating this transaction output as spent.
*/
transactionRepository.listTransactionInput({
'transaction_input.transaction_id': input.transaction_id,
is_double_spend : 1
}).then(doubleSpendInputList => {
if (doubleSpendInputList.length > 0) {
return callbackInput();
}
return transactionRepository.getTransaction(input.transaction_id)
.then(transaction => {
if (transaction && transaction.status !== 3) {
spendingInputs.push(transaction);
}
callbackInput();
});
});
}, () => resolve(spendingInputs));
});
});
}).then(spendingTransaction => {
}).then(spendingTransactionList => {
// skip if we already know that the tx is spent
if (spendingTransaction) {
if (spendingTransactionList.length > 0) {
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(() => {
callback();
});
......
......@@ -153,9 +153,9 @@ export class WalletTransactionConsensus {
_updateDoubleSpendTransaction(transactions, doubleSpendTransactionInput) {
console.log('[consensus][oracle] setting ', transactions.length, ' transaction as double spend');
async.eachSeries(transactions, (transactionID, callback) => {
async.eachSeries(transactions, (transaction, callback) => {
database.getRepository('transaction')
.setTransactionAsDoubleSpend(transactionID, doubleSpendTransactionInput)
.setTransactionAsDoubleSpend(transaction, doubleSpendTransactionInput)
.then(() => callback());
});
}
......@@ -171,16 +171,15 @@ export class WalletTransactionConsensus {
}
return new Promise((resolve, reject) => {
(() => transaction ? Promise.resolve([
transaction,
transaction.shard_id
]) : database.firstShards((shardID) => {
return new Promise((resolve, reject) => {
const transactionRepository = database.getRepository('transaction', shardID);
transactionRepository.getTransactionObject(transactionID)
.then(transaction => transaction ? resolve(transaction) : reject());
});
}))().then((transaction) => {
(() => transaction ? Promise.resolve(transaction) :
this._transactionObjectCache[transactionID] ? Promise.resolve(this._transactionObjectCache[transactionID]) :
database.firstShards((shardID) => {
return new Promise((resolve, reject) => {
const transactionRepository = database.getRepository('transaction', shardID);
transactionRepository.getTransactionObject(transactionID)
.then(transaction => transaction ? resolve(transaction) : reject());
});
}))().then((transaction) => {
if (transaction && transaction.is_stable && _.every(transaction.transaction_output_list, output => output.is_stable && !output.is_double_spend)) {
console.log('[consensus][oracle] validated in consensus round after found a validated transaction at depth ', depth);
......@@ -193,21 +192,14 @@ export class WalletTransactionConsensus {
message : 'invalid transaction found: ' + transactionID
});
}
if (transaction && transaction.is_stable !== undefined) { // transaction object needs to be normalized
transaction = database.getRepository('transaction').normalizeTransactionObject(transaction);
}
if (!transaction) {
else if (transaction && transaction.is_stable && _.some(transaction.transaction_output_list, output => output.is_double_spend === 1) ||
doubleSpendSet.has(transactionID)) {
return reject({
cause : 'transaction_not_found',
cause : 'transaction_double_spend',
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) {
return reject({
cause : 'transaction_validation_max_depth',
......@@ -215,17 +207,25 @@ export class WalletTransactionConsensus {
message : `not validated in a depth of ${depth}`
});
}
else if (doubleSpendSet.has(transactionID)) {
return reject({
cause : 'transaction_double_spend',
transaction_id_fail: transactionID,
message : 'double spend found in ' + transactionID
});
else if (transaction && transaction.transaction_id === genesisConfig.genesis_transaction) {
return resolve();
}
else if (transactionVisitedSet.has(transactionID)) {
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)
.then(valid => {
if (!valid) {
......@@ -255,7 +255,7 @@ export class WalletTransactionConsensus {
(() => {
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 || []);
}
else {
......@@ -310,14 +310,7 @@ export class WalletTransactionConsensus {
}
});
}).then(() => {
// get
// the
// total
// millix
// amount
// of
// this
// input
/* get the total millix amount of this input */
database.firstShards((shardID) => {
return new Promise((resolve, reject) => {
if (this._transactionObjectCache[input.output_transaction_id]) {
......@@ -370,8 +363,7 @@ export class WalletTransactionConsensus {
});
}
// compare input and output
// amount
/* compare input and output amount */
let outputTotalAmount = 0;
_.each(transaction.transaction_output_list, output => {
outputTotalAmount += output.amount;
......@@ -388,9 +380,14 @@ export class WalletTransactionConsensus {
// check inputs transactions
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))
.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) => {
if (err && !valid) {
return reject(err);
......@@ -867,7 +864,7 @@ export class WalletTransactionConsensus {
this._transactionValidationRejected.add(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})
.then(_ => _);
this._transactionValidationRejected.add(transactionID);
......
......@@ -561,8 +561,9 @@ class WalletUtils {
}
else {
// before 1620603935 the refresh time was 3 days
// now the refresh time is 10 min (TRANSACTION_OUTPUT_EXPIRE_OLDER_THAN)
const expireMinutes = transactionDate.getTime() <= 1620603935000 ? 4320 : config.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;
let maximumOldestDate = new Date(transactionDate.getTime());
maximumOldestDate.setMinutes(maximumOldestDate.getMinutes() - expireMinutes);
this.isConsumingExpiredOutputs(transaction.transaction_input_list, maximumOldestDate)
......@@ -631,8 +632,8 @@ class WalletUtils {
if (transaction.transaction_id !== genesisConfig.genesis_transaction) {
const outputUsedInTransaction = new Set();
for (let i = 0; i < transaction.transaction_input_list.length; i++) {
const input = transaction.transaction_input_list[i];
const outputID = input.output_transaction_id + ":" + input.output_position;
const input = transaction.transaction_input_list[i];
const outputID = input.output_transaction_id + ':' + input.output_position;
if (!this.isValidAddress(input.address_base)
|| !this.isValidAddress(input.address_key_identifier)
|| !addressRepository.supportedVersionSet.has(input.address_version)
......@@ -805,13 +806,10 @@ class WalletUtils {
address_attribute: addressAttributeMap[addressBase]
}));
return resolve(signatureList);
}))
.then((signatureList) => peer.getNodeAddress()
.then(() => signatureList))
.then(signatureList => this.isConsumingExpiredOutputs(inputList, maximumOldestDate).then(isConsumingExpiredOutputs => [
signatureList,
isConsumingExpiredOutputs
]))
})).then(signatureList => this.isConsumingExpiredOutputs(inputList, maximumOldestDate).then(isConsumingExpiredOutputs => [
signatureList,
isConsumingExpiredOutputs
]))
.then(([signatureList, isConsumingExpiredOutputs]) => {
let transactionList = [];
let transaction;
......@@ -867,7 +865,7 @@ class WalletUtils {
let signature;
for (let transactionSignature of signatureList) {
if(transactionSignature.address_base === refreshOutput.address_base){
if (transactionSignature.address_base === refreshOutput.address_base) {
signature = _.cloneDeep(transactionSignature);
break;
}
......
......@@ -702,7 +702,7 @@ class Wallet {
delete this._transactionRequested[transaction.transaction_id];
delete this._transactionFundingActiveWallet[transaction.transaction_id];
walletSync.removeTransactionSync(transaction.transaction_id);
return false;
// return false;
}
const isFundingWallet = !!this._transactionFundingActiveWallet[transaction.transaction_id];
......@@ -891,6 +891,7 @@ class Wallet {
markAllSpendersAsInvalid(spenders) {
let spendersByShard = {};
let spendersSet = new Set();
for (let spender of spenders) {
const shardID = spender.shard_id || genesisConfig.genesis_shard_id;
......@@ -899,6 +900,7 @@ class Wallet {
}
spendersByShard[shardID].push(spender.transaction_id);
spendersSet.add(spender.transaction_id);
}
return new Promise((resolve) => {
......@@ -915,10 +917,63 @@ class Wallet {
return transactionRepository.markTransactionsAsInvalid(transactionIDList);
}).then(() => {
console.log(`[wallet] set transactions ${transactionIDList} as invalid`);
chunkCallback();
}).catch((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());
}, () => {
......@@ -1979,7 +2034,8 @@ class Wallet {
'proxy_network_error',
'proxy_timeout',
'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)))
.then(proxyCandidates => {
......@@ -1994,7 +2050,7 @@ class Wallet {
error : true,
message: e
}) : 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'));
});
});
......@@ -2116,7 +2172,7 @@ class Wallet {
eventBus.removeAllListeners('transaction_sync_response');
eventBus.removeAllListeners('transaction_sync_by_date_response');
eventBus.removeAllListeners('shard_sync_request');
eventBus.removeAllListeners('address_transaction_sync');
eventBus.removeAllListeners('wallet_transaction_sync');
eventBus.removeAllListeners('transaction_validation_request');
eventBus.removeAllListeners('transaction_validation_response');
eventBus.removeAllListeners('transaction_spend_request');
......
......@@ -107,6 +107,5 @@ db.initialize()
console.log('registered new genesis: ', genesisConfig.genesis_transaction);
});
}
})
.then(() => setTimeout(() => wallet.syncAddresses(), 2000));
//millix v1.10.9-tangled
});
//millix v1.10.10-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