Skip to content

Commit

Permalink
Direct connection to the daemon
Browse files Browse the repository at this point in the history
  • Loading branch information
gnock committed Jun 23, 2019
1 parent 4b8943e commit 85f7084
Show file tree
Hide file tree
Showing 29 changed files with 706 additions and 832 deletions.
4 changes: 4 additions & 0 deletions src/config.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
let global : any = typeof window !== 'undefined' ? window : self;
global.config = {
apiUrl:typeof window !== 'undefined' && window.location ? window.location.href.substr(0,window.location.href.lastIndexOf('/')+1)+'api/' : 'https://www.masariwallet.com/api/',
trustedDaemonsAddresses:[
'https://www.masariwallet.com:38084/'
],
phpRelay:typeof window !== 'undefined' && window.location.host.indexOf('localhost') !== -1 ? true : false,
mainnetExplorerUrl: "https://msrchain.net/",
mainnetExplorerUrlHash: "https://msrchain.net/tx/{ID}",
mainnetExplorerUrlBlock: "https://msrchain.net/block/{ID}",
Expand Down
1 change: 1 addition & 0 deletions src/d/config.d.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
declare var config : {
apiUrl:string,
trustedDaemonsAddresses:string[],
mainnetExplorerUrl: string,
mainnetExplorerUrlHash: string,
mainnetExplorerUrlBlock: string,
Expand Down
2 changes: 1 addition & 1 deletion src/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, user-scalable=no">

<meta http-equiv="Content-Security-Policy" content="default-src 'self' data: gap: https://www.masariwallet.com 'unsafe-eval' ; style-src 'self' 'unsafe-inline'; media-src *; img-src 'self' data: content:;">
<!--<meta http-equiv="Content-Security-Policy" content="default-src 'self' data: gap: https://www.masariwallet.com 'unsafe-eval' ; style-src 'self' 'unsafe-inline'; media-src *; img-src 'self' data: content:;">-->
<meta name="referrer" content="none">
<meta name="msapplication-tap-highlight" content="no">

Expand Down
9 changes: 4 additions & 5 deletions src/model/AppState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,13 @@
*/

import {DependencyInjectorInstance} from "../lib/numbersLab/DependencyInjector";
import {BlockchainExplorerRpc2, WalletWatchdog} from "./blockchain/BlockchainExplorerRpc2";
import {Wallet} from "./Wallet";
import {BlockchainExplorerProvider} from "../providers/BlockchainExplorerProvider";
import {Observable} from "../lib/numbersLab/Observable";
import {WalletRepository} from "./WalletRepository";
import {BlockchainExplorer, RawDaemon_Transaction} from "./blockchain/BlockchainExplorer";
import {Constants} from "./Constants";
import {TransactionsExplorer} from "./TransactionsExplorer";
import {WalletWatchdog} from "./WalletWatchdog";

export class WalletWorker{
wallet : Wallet;
Expand Down Expand Up @@ -128,9 +127,9 @@ export class AppState{
blockchainHeightToRescanObj[tx.blockHeight] = true;
}
}
let blockchainHeightToRescan = Object.keys(blockchainHeightToRescanObj);
/*let blockchainHeightToRescan = Object.keys(blockchainHeightToRescanObj);
if (blockchainHeightToRescan.length > 0) {
let blockchainExplorer: BlockchainExplorerRpc2 = BlockchainExplorerProvider.getInstance();
let blockchainExplorer: BlockchainExplorer = BlockchainExplorerProvider.getInstance();
let promisesBlocks = [];
for (let height of blockchainHeightToRescan) {
Expand All @@ -147,7 +146,7 @@ export class AppState{
}
}
});
}
}*/
swal.close();
resolve();

Expand Down
8 changes: 5 additions & 3 deletions src/model/TransactionsExplorer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,9 +106,9 @@ export class TransactionsExplorer {
}

static isMinerTx(rawTransaction: RawDaemon_Transaction) {
if (rawTransaction.vin.length > 0)
if (!Array.isArray(rawTransaction.vout) || rawTransaction.vin.length > 0)
return false;
if(rawTransaction.vout.length === 0){
if(!Array.isArray(rawTransaction.vout) || rawTransaction.vout.length === 0){
console.error('Weird tx !', rawTransaction);
return false;
}
Expand Down Expand Up @@ -260,7 +260,7 @@ export class TransactionsExplorer {
let keyImages = wallet.getTransactionKeyImages();
for (let iIn = 0; iIn < rawTransaction.vin.length; ++iIn) {
let vin = rawTransaction.vin[iIn];
if (keyImages.indexOf(vin.key.k_image) != -1) {
if (vin.key && keyImages.indexOf(vin.key.k_image) !== -1) {
// console.log('found in', vin);
let walletOuts = wallet.getAllOuts();
for (let ut of walletOuts) {
Expand All @@ -284,6 +284,8 @@ export class TransactionsExplorer {
for (let iIn = 0; iIn < rawTransaction.vin.length; ++iIn) {
let vin = rawTransaction.vin[iIn];

if(!vin.key)continue;

let absoluteOffets = vin.key.key_offsets.slice();
for (let i = 1; i < absoluteOffets.length; ++i) {
absoluteOffets[i] += absoluteOffets[i - 1];
Expand Down
260 changes: 260 additions & 0 deletions src/model/WalletWatchdog.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,260 @@
import {Wallet} from "./Wallet";
import {BlockchainExplorer, RawDaemon_Transaction} from "./blockchain/BlockchainExplorer";
import {Transaction} from "./Transaction";
import {TransactionsExplorer} from "./TransactionsExplorer";

export class WalletWatchdog{

wallet : Wallet;
explorer : BlockchainExplorer;

constructor(wallet: Wallet, explorer : BlockchainExplorer) {
this.wallet = wallet;
this.explorer = explorer;

this.initWorker();
this.initMempool();
}

initWorker(){
let self = this;
this.workerProcessing = new Worker('./workers/TransferProcessingEntrypoint.js');
this.workerProcessing.onmessage = function(data : MessageEvent){
let message : string|any = data.data;
if(message === 'ready'){
console.info('worker ready');
self.signalWalletUpdate();
}else if(message === 'readyWallet'){
self.workerProcessingReady = true;
}else if(message.type){
if(message.type === 'processed'){
let transactions = message.transactions;
if(transactions.length > 0) {
for(let tx of transactions)
self.wallet.addNew(Transaction.fromRaw(tx));
self.signalWalletUpdate();
}
if(self.workerCurrentProcessing.length>0) {
let transactionHeight = self.workerCurrentProcessing[self.workerCurrentProcessing.length-1].height;
if(typeof transactionHeight !== 'undefined')
self.wallet.lastHeight = transactionHeight;
}

self.workerProcessingWorking = false;
}
}
};
}

signalWalletUpdate(){
let self = this;
console.log('wallet update');
this.lastBlockLoading = -1;//reset scanning
this.workerProcessing.postMessage({
type:'initWallet',
wallet:this.wallet.exportToRaw()
});
clearInterval(this.intervalTransactionsProcess);
this.intervalTransactionsProcess = setInterval(function(){
self.checkTransactionsInterval();
}, this.wallet.options.readSpeed);

//force mempool update after a wallet update (new tx, ...)
self.checkMempool();
}

intervalMempool = 0;
initMempool(force : boolean = false){
let self = this;
if(this.intervalMempool === 0 || force){
if(force && this.intervalMempool !== 0){
clearInterval(this.intervalMempool);
}

this.intervalMempool = setInterval(function(){
self.checkMempool();
}, config.avgBlockTime/2*1000);
}
self.checkMempool();
}

stopped : boolean = false;

stop(){
clearInterval(this.intervalTransactionsProcess);
this.transactionsToProcess = [];
clearInterval(this.intervalMempool);
this.stopped = true;
}

checkMempool() : boolean{
let self = this;
if(this.lastMaximumHeight - this.lastBlockLoading > 1){//only check memory pool if the user is up to date to ensure outs & ins will be found in the wallet
return false;
}

this.wallet.txsMem = [];
this.explorer.getTransactionPool().then(function(data : any){
if(typeof data.transactions !== 'undefined')
for(let rawTx of data.transactions){
let tx = TransactionsExplorer.parse(rawTx.tx_json,self.wallet);
if(tx !== null){
tx.hash = rawTx.id_hash;
tx.fees = rawTx.fee;
self.wallet.txsMem.push(tx);
}
}
}).catch(function(){});
return true;
}

terminateWorker(){
this.workerProcessing.terminate();
this.workerProcessingReady = false;
this.workerCurrentProcessing = [];
this.workerProcessingWorking = false;
this.workerCountProcessed = 0;
}

transactionsToProcess : RawDaemon_Transaction[] = [];
intervalTransactionsProcess = 0;

workerProcessing !: Worker;
workerProcessingReady = false;
workerProcessingWorking = false;
workerCurrentProcessing : RawDaemon_Transaction[] = [];
workerCountProcessed = 0;

checkTransactions(rawTransactions : RawDaemon_Transaction[]){
for(let rawTransaction of rawTransactions){
let height = rawTransaction.height;
if(typeof height !== 'undefined') {
let transaction = TransactionsExplorer.parse(rawTransaction, this.wallet);
if (transaction !== null) {
this.wallet.addNew(transaction);
}
if (height - this.wallet.lastHeight >= 2) {
this.wallet.lastHeight = height - 1;
}
}
}
if(this.transactionsToProcess.length == 0){
this.wallet.lastHeight = this.lastBlockLoading;
}
}

checkTransactionsInterval(){
if(this.workerProcessingWorking || !this.workerProcessingReady) {
return;
}

//we destroy the worker in charge of decoding the transactions every 5k transactions to ensure the memory is not corrupted
//cnUtil bug, see https://github.com/mymonero/mymonero-core-js/issues/8
if(this.workerCountProcessed >= 5*1000){
console.log('Recreate worker..');
this.terminateWorker();
this.initWorker();
return;
}

let transactionsToProcess : RawDaemon_Transaction[] = this.transactionsToProcess.splice(0, 30);
if(transactionsToProcess.length > 0) {
this.workerCurrentProcessing = transactionsToProcess;
this.workerProcessing.postMessage({
type:'process',
transactions:transactionsToProcess
});
this.workerCountProcessed+=this.transactionsToProcess.length;
this.workerProcessingWorking = true;
}else{
clearInterval(this.intervalTransactionsProcess);
this.intervalTransactionsProcess = 0;
}
}

processTransactions(transactions : RawDaemon_Transaction[]){
let transactionsToAdd = [];
for(let tr of transactions){
if(typeof tr.height !== 'undefined')
if(tr.height > this.wallet.lastHeight){
transactionsToAdd.push(tr);
}
}

this.transactionsToProcess.push.apply(this.transactionsToProcess, transactionsToAdd);
if(this.intervalTransactionsProcess === 0){
let self = this;
this.intervalTransactionsProcess = setInterval(function(){
self.checkTransactionsInterval();
}, this.wallet.options.readSpeed);
}
}


lastBlockLoading = -1;
lastMaximumHeight = 0;

loadHistory(){
if(this.stopped)return;

let self = this;

if(this.transactionsToProcess.length > 500){
//to ensure no pile explosion
setTimeout(function () {
self.loadHistory();
}, 2*1000);
return;
}

// console.log('checking');
this.explorer.getHeight().then(function(height){
if(height > self.lastMaximumHeight)self.lastMaximumHeight = height;

if(self.lastBlockLoading === -1)self.lastBlockLoading = self.wallet.lastHeight;

if(self.lastBlockLoading !== height){
let previousStartBlock = self.lastBlockLoading;
let endBlock = previousStartBlock+99;

if(previousStartBlock >= self.lastMaximumHeight)previousStartBlock = self.lastMaximumHeight;
if(endBlock >= self.lastMaximumHeight)endBlock = self.lastMaximumHeight;

self.explorer.getTransactionsForBlocks(previousStartBlock, endBlock, false).then(function(transactions : RawDaemon_Transaction[]){
//to ensure no pile explosion
if(transactions.length > 0){
let lastTx = transactions[transactions.length-1];
if(typeof lastTx.height !== 'undefined') {
self.lastBlockLoading = lastTx.height + 1;
}
self.processTransactions(transactions);
setTimeout(function () {
self.loadHistory();
}, 1);
}else{
self.lastBlockLoading = endBlock+1;
if(self.lastBlockLoading >= self.lastMaximumHeight)self.lastBlockLoading = self.lastMaximumHeight;

setTimeout(function () {
self.loadHistory();
}, 30*1000);
}
}).catch(function(){
setTimeout(function () {
self.loadHistory();
}, 30*1000);//retry 30s later if an error occurred
});
}else{
setTimeout(function () {
self.loadHistory();
}, 30*1000);
}
}).catch(function(){
setTimeout(function () {
self.loadHistory();
}, 30*1000);//retry 30s later if an error occurred
});
}


}
22 changes: 20 additions & 2 deletions src/model/blockchain/BlockchainExplorer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,19 +29,37 @@ export type RawDaemon_RctSignature = {
export type RawDaemon_Transaction = {
extra : number[],
vout : CnTransactions.Vout[],
vin : {key:CnTransactions.Vin}[],
vin : {
key?:CnTransactions.Vin,
gen?:{height:number},
}[],
rct_signatures:CnTransactions.RctSignature,
unlock_time:number,
version:number,
ctsig_prunable:any,
global_index_start?:number,
height?:number,
ts?:number
ts?:number,//timestamp
hash?:string,
};

export type NetworkInfo = {
major_version:number,
hash:string,
reward:number,
height:number,
timestamp:number,
difficulty:number,
};

export interface BlockchainExplorer{
resolveOpenAlias(str : string) : Promise<{ address: string, name: string | null }>;
getHeight() : Promise<number>;
getScannedHeight() : number;
watchdog(wallet : Wallet) : void;
getTransactionPool() : Promise<RawDaemon_Transaction[]>;
getTransactionsForBlocks(startBlock : number, endBlock : number, includeMinerTx : boolean) : Promise<RawDaemon_Transaction[]>;
sendRawTx(rawTx : string) : Promise<any>;
getRandomOuts(numberOuts : number) : Promise<any[]>;
getNetworkInfo() : Promise<NetworkInfo>;
}
Loading

0 comments on commit 85f7084

Please sign in to comment.