Commit 5be0bec4 authored by Eriksson Monteiro's avatar Eriksson Monteiro

update millix node integration

parent 7652270f
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.10</small>
millix node <small>v1.10.11</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 = 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';
export const NODE_MILLIX_BUILD_DATE = 1625049052;
export const NODE_MILLIX_VERSION = '1.10.11-tangled';
export const DATA_BASE_DIR_MAIN_NETWORK = './millix-tangled';
export const DATA_BASE_DIR_TEST_NETWORK = './millix-tangled';
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';
......
import config from '../config/config';
export const GENESIS_TRANSACTION_MAIN_NETWORK = '2VngVznbdiQ5tqfWqn2NMP8DijqCbLX79Gygo9yYRVFU6iN35h';
export const GENESIS_TRANSACTION_TEST_NETWORK = 'wFtfcYFJb75bJCGU3HVsPCRg8RDHnMmsRL565BSaeu3aidqQN';
export const GENESIS_TRANSACTION_TEST_NETWORK = 'BbYAZLcxbx6adN3KwHZSTGjE6VpeDhiJ3ZPrXs6EMAGqDPfi5';
export const GENESIS_SHARD_ID_MAIN_NETWORK = 'qGuUgMMVmaCvqrvoWG6zARjkrujGMpzJmpNhBgz1y3RjBG7ZR';
export const GENESIS_SHARD_ID_TEST_NETWORK = '2qkemPc9SozT4r8TdcMgyv9DxgE8m4qUkEJ2eBRQLCNP9GD4Vh';
export const GENESIS_SHARD_ID_TEST_NETWORK = 'AyAC3kjLtjM4vktAJ5Xq6mbXKjzEqXoSsmGhhgjnkXUvjtF2M';
export default {
genesis_transaction: config.MODE_TEST_NETWORK ? GENESIS_TRANSACTION_TEST_NETWORK : GENESIS_TRANSACTION_MAIN_NETWORK,
genesis_shard_id : config.MODE_TEST_NETWORK ? GENESIS_SHARD_ID_TEST_NETWORK : GENESIS_SHARD_ID_MAIN_NETWORK
......
......@@ -270,7 +270,10 @@ export class WalletTransactionConsensus {
...input
});
this._getValidInputOnDoubleSpend(input.output_transaction_id, doubleSpendTransactions, nodeID, transactionVisitedSet, doubleSpendSet)
.then(({response_type: responseType, data}) => {
.then(({
response_type: responseType,
data
}) => {
if (data && (responseType === 'transaction_double_spend' || responseType === 'transaction_valid')) {
let doubleSpendInputs = _.filter(doubleSpendTransactions, i => i.transaction_id !== data.transaction_id);
......@@ -385,6 +388,7 @@ export class WalletTransactionConsensus {
.catch((err) => {
if (err && err.cause === 'transaction_double_spend' && !err.transaction_input_double_spend) {
this._updateDoubleSpendTransaction([transaction], srcTransaction);
err.transaction_input_double_spend = srcTransaction;
}
callback(err, false);
});
......@@ -402,18 +406,22 @@ export class WalletTransactionConsensus {
}
_validateTransactionInConsensusRound(data, ws) {
const {node, nodeID, connectionID} = ws;
const transactionID = data.transaction_id;
const {
node,
nodeID,
connectionID
} = ws;
const transactionID = data.transaction_id;
if (!this._transactionValidationState[ws.nodeID] ||
this._transactionValidationState[ws.nodeID].transaction_id !== data.transaction_id ||
!!this._transactionValidationState[ws.nodeID].timestamp) {
return peer.transactionValidationResponse({
cause : 'transaction_validation_unexpected',
transaction_id_failed: transactionID,
transaction_id : transactionID,
valid : false,
type : 'validation_response'
cause : 'transaction_validation_unexpected',
transaction_id_fail: transactionID,
transaction_id : transactionID,
valid : false,
type : 'validation_response'
}, ws, true);
}
......@@ -675,7 +683,7 @@ export class WalletTransactionConsensus {
this._transactionValidationRejected.add(transactionID);
console.log('[consensus][request] the transaction ', transactionID, ' was not validated (due to double spend) during consensus round number ', consensusData.consensus_round_count);
return database.applyShardZeroAndShardRepository('transaction', transaction.shard_id, transactionRepository => {
return transactionRepository.setTransactionAsDoubleSpend(transaction, data.transaction_id_fail /*double spend input*/);
return transactionRepository.setTransactionAsDoubleSpend(transaction, data.transaction_input_double_spend /*double spend input*/);
}).then(() => wallet._checkIfWalletUpdate(new Set(_.map(transaction.transaction_output_list, o => o.address_key_identifier))))
.then(() => {
consensusData.resolve();
......@@ -771,15 +779,15 @@ export class WalletTransactionConsensus {
.then(pendingTransactions => {
// filter out tx that were synced in the
// last 30s and not being validated yet
return _.filter(pendingTransactions, transaction => !(transaction.create_date - transaction.transaction_date > 30 && Date.now() - transaction.create_date < 30 && !this._consensusRoundState[transaction.transaction_id]));
return _.filter(pendingTransactions, transaction => !(Date.now() - transaction.create_date < 30 || this._consensusRoundState[transaction.transaction_id]));
});
}).then(pendingTransactions => {
}, 'transaction_date').then(pendingTransactions => {
if (pendingTransactions.length === 0) {
return database.applyShards((shardID) => {
return database.getRepository('transaction', shardID)
.findUnstableTransaction(excludeTransactionList);
}).then(transactions => [
_.filter(transactions, transaction => !(transaction.create_date - transaction.transaction_date > 30 && Date.now() - transaction.create_date < 30 && !this._consensusRoundState[transaction.transaction_id])),
}, 'transaction_date').then(transactions => [
_.filter(transactions, transaction => !(Date.now() - transaction.create_date < 30 || this._consensusRoundState[transaction.transaction_id])),
false
]);
}
......@@ -811,12 +819,6 @@ export class WalletTransactionConsensus {
this._transactionRetryValidation[transactionID] = Date.now();
}
if (this._consensusRoundState[transactionID]) {
// remove locker
delete this._consensusRoundState[lockerID];
return;
}
delete this._consensusRoundState[lockerID];
this._consensusRoundState[transactionID] = {};
......
......@@ -157,8 +157,11 @@ class Wallet {
}
deriveAndSaveAddress(walletID, isChange, addressPosition) {
const keychain = database.getRepository('keychain');
let {address: addressBase, address_attribute: addressAttribute} = this.deriveAddress(walletID, isChange, addressPosition);
const keychain = database.getRepository('keychain');
let {
address : addressBase,
address_attribute: addressAttribute
} = this.deriveAddress(walletID, isChange, addressPosition);
return keychain.getWalletDefaultKeyIdentifier(walletID)
.then(addressKeyIdentifier => [
addressBase,
......@@ -281,7 +284,10 @@ class Wallet {
const {address: missingAddress} = addressRepository.getAddressComponent(output.address);
//TODO: find a better way to get the address
for (let addressPosition = 0; addressPosition < 2 ** 32; addressPosition++) {
let {address: addressBase, address_attribute: addressAttribute} = this.deriveAddress(this.getDefaultActiveWallet(), 0, addressPosition);
let {
address : addressBase,
address_attribute: addressAttribute
} = this.deriveAddress(this.getDefaultActiveWallet(), 0, addressPosition);
if (addressBase === missingAddress) {
output['address_version'] = addressRepository.getDefaultAddressVersion().version;
output['address_key_identifier'] = this.defaultKeyIdentifier;
......@@ -857,33 +863,24 @@ class Wallet {
processedTransaction.add(transaction.transaction_id);
console.log(`[Wallet] Querying all shards for potential spenders of transaction ${transaction.transaction_id}`);
return new Promise((resolve) => {
return database.applyShards((shardID) => {
return new Promise(resolve => {
database.getRepository('transaction', shardID)
.getTransactionSpenders(transaction.transaction_id)
.then(result => resolve(result))
.catch(err => {
console.log(`[wallet] Error occurred: ${err}`);
resolve([]);
});
});
}).then(transactionSpenders => {
if (transactionSpenders.length === 0) {
return resolve([transaction]);
} // stops recursion
async.mapSeries(transactionSpenders, (spender, callback) => {
if (processedTransaction.has(spender.transaction_id)) {
return callback(false, []);
}
// continues recursion
this.findAllSpenders(spender, processedTransaction)
.then((spenders) => callback(false, spenders));
}, (err, mapOfSpenders) => {
let spenders = Array.prototype.concat.apply([], mapOfSpenders);
spenders.push(transaction);
resolve(spenders);
return database.firstShards((shardID) => {
const transactionRepository = database.getRepository('transaction', shardID);
return transactionRepository.listTransactionOutput({
'transaction_output.transaction_id': transaction.transaction_id
}).then(outputs => outputs.length > 0 ? Promise.resolve(outputs) : Promise.reject());
}).then(outputs => {
return new Promise(resolve => {
const spenderMap = {};
async.eachSeries(outputs, (output, callback) => {
database.applyShards(shardID => {
return database.getRepository('transaction', shardID)
.getTransactionSpenders(output.transaction_id, output.shard_id, output.output_position);
}).then(allOutputSpenders => {
allOutputSpenders.forEach(spender => spenderMap[spender.transaction_id] = spender);
callback();
});
}, () => {
resolve(Object.values(spenderMap));
});
});
});
......@@ -909,7 +906,7 @@ class Wallet {
let chunkTransactionIDs = [];
while (transactionIDs.length) {
chunkTransactionIDs.push(transactionIDs.splice(0, 1000));
chunkTransactionIDs.push(transactionIDs.splice(0, 512));
}
async.eachSeries(chunkTransactionIDs, (transactionIDList, chunkCallback) => {
......@@ -955,7 +952,7 @@ class Wallet {
/* 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);
return database.getRepository('transaction', shardID).getTransactionSpenders(transactionInput.output_transaction_id, transactionInput.output_shard_id, transactionInput.output_position);
}).then(transactionSpenders => {
if (transactionSpenders.length > 1) {
/* skip this output. there is another transaction spending it */
......@@ -1945,10 +1942,13 @@ class Wallet {
})
.then(([outputs, addressKeyIdentifier]) => {
// Creating output - using the first address
const fee = config.TRANSACTION_FEE_DEFAULT;
const addressRepository = database.getRepository('address');
const {address: addressBase, version: addressVersion} = addressRepository.getAddressComponent(outputs[0].address);
const newOutput = {
const fee = config.TRANSACTION_FEE_DEFAULT;
const addressRepository = database.getRepository('address');
const {
address: addressBase,
version: addressVersion
} = addressRepository.getAddressComponent(outputs[0].address);
const newOutput = {
address_base : addressBase,
address_version : addressVersion,
address_key_identifier: addressKeyIdentifier,
......@@ -1997,9 +1997,13 @@ class Wallet {
const addressRepository = database.getRepository('address');
const time = ntp.now();
const transactionDate = new Date(Math.floor(time.getTime() / 1000) * 1000);
const {address: addressBase, version, identifier: addressKeyIdentifier} = addressRepository.getAddressComponent(proxyCandidateData.node_address_default);
let feeOutputs = [
const transactionDate = new Date(Math.floor(time.getTime() / 1000) * 1000);
const {
address: addressBase,
version,
identifier: addressKeyIdentifier
} = addressRepository.getAddressComponent(proxyCandidateData.node_address_default);
let feeOutputs = [
{
...outputFee,
node_id_proxy : proxyCandidateData.node_id,
......
......@@ -424,20 +424,28 @@ export class Database {
applyShardZeroAndShardRepository(repositoryName, shardID, func) {
return new Promise(resolve => {
async.eachSeries([
async.mapSeries([
SHARD_ZERO_NAME,
shardID
], (shardID, callback) => {
const repository = this.getRepository(repositoryName, shardID);
if (repository) {
func(repository)
.then(() => callback())
.catch(() => callback());
.then(result => callback(null, result))
.catch(() => callback(null, []));
}
else {
callback();
callback(null, []);
}
}, () => resolve());
}, (err, data) => {
if (data) {
data = Array.prototype.concat.apply([], data);
}
else {
data = [];
}
resolve(data);
});
});
}
......
......@@ -108,4 +108,4 @@ db.initialize()
});
}
});
//millix v1.10.10-tangled
//millix v1.10.11-tangled
......@@ -8,6 +8,7 @@ CREATE TABLE `transaction`
shard_id CHAR(50) NOT NULL CHECK (length(shard_id) <= 50),
transaction_date INT NOT NULL CHECK (length(transaction_date) <= 10 AND TYPEOF(transaction_date) = 'integer'),
node_id_origin CHAR(34) NOT NULL CHECK (length(node_id_origin) <= 34),
node_id_proxy CHAR(34) NULL CHECK (length(node_id_proxy) <= 34),
version CHAR(4) NOT NULL DEFAULT '0a0' CHECK (length(version) <= 4),
payload_hash CHAR(50) NOT NULL CHECK (length(payload_hash) <= 50),
stable_date INT NULL CHECK (length(stable_date) <= 10 AND (TYPEOF(stable_date) IN ('integer', 'null'))),
......@@ -16,7 +17,7 @@ CREATE TABLE `transaction`
is_parent TINYINT NOT NULL DEFAULT 0 CHECK (is_parent = 0 OR is_parent = 1),
timeout_date INT NULL CHECK(length(timeout_date) <= 10 AND TYPEOF(timeout_date) IN ('integer', 'null')),
is_timeout TINYINT NOT NULL DEFAULT 0 CHECK (is_timeout = 0 OR is_timeout = 1),
status TINYINT NOT NULL DEFAULT 1 CHECK (length(status) <= 3 AND TYPEOF(status) = 'integer'),
status TINYINT NOT NULL DEFAULT 1 CHECK (length(status) <= 3 AND TYPEOF(status) = 'integer'), /*1: default, 2: prune, 3: invalid*/
create_date INT NOT NULL DEFAULT (CAST(strftime('%s', 'now') AS INTEGER)) CHECK(length(create_date) <= 10 AND TYPEOF(create_date) = 'integer')
);
CREATE INDEX idx_transaction_status_is_stable_transaction_date ON `transaction` (status, is_stable, transaction_date);
......@@ -108,14 +109,14 @@ CREATE INDEX idx_transaction_output_create_date ON transaction_output (create_da
CREATE TABLE transaction_output_attribute
(
transaction_output_id CHAR(50) NOT NULL CHECK (length(transaction_output_id) <= 50),
transaction_output_type_id CHAR(20) NOT NULL CHECK (length(transaction_output_type_id) <= 20),
shard_id CHAR(50) NOT NULL CHECK (length(shard_id) <= 50),
value TEXT NOT NULL,
status TINYINT NOT NULL DEFAULT 1 CHECK (length(status) <= 3 AND TYPEOF(status) = 'integer'),
create_date INT NOT NULL DEFAULT (CAST(strftime('%s', 'now') AS INTEGER)) CHECK(length(create_date) <= 10 AND TYPEOF(create_date) = 'integer'),
PRIMARY KEY (transaction_output_id, transaction_output_type_id),
FOREIGN KEY (transaction_output_id) REFERENCES transaction_output (transaction_id)
transaction_id CHAR(50) NOT NULL CHECK (length(transaction_id) <= 50),
attribute_type_id CHAR(20) NOT NULL CHECK (length(attribute_type_id) <= 20),
shard_id CHAR(50) NOT NULL CHECK (length(shard_id) <= 50),
value TEXT NOT NULL,
status TINYINT NOT NULL DEFAULT 1 CHECK (length(status) <= 3 AND TYPEOF(status) = 'integer'),
create_date INT NOT NULL DEFAULT (CAST(strftime('%s', 'now') AS INTEGER)) CHECK(length(create_date) <= 10 AND TYPEOF(create_date) = 'integer'),
PRIMARY KEY (transaction_id, attribute_type_id),
FOREIGN KEY (transaction_id) REFERENCES `transaction` (transaction_id)
);
CREATE INDEX idx_transaction_output_attribute_create_date ON transaction_output_attribute (create_date);
......
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