@leofcoin/chain 1.3.1 → 1.3.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/demo/chain.browser.js +17 -13
- package/demo/peernet-swarm.browser.js +8 -9
- package/demo/workers/machine-worker.js +30 -11
- package/dist/browser/workers/machine-worker.js +18 -12
- package/dist/chain.js +149 -134
- package/dist/contracts/factory.js +1 -1
- package/dist/contracts/{nameService.js → name-service.js} +1 -1
- package/dist/contracts/native-token.js +1 -0
- package/dist/contracts/validators.js +1 -1
- package/dist/module/chain.js +146 -131
- package/dist/module/workers/machine-worker.js +18 -12
- package/dist/standards/token.js +1 -1
- package/dist/workers/machine-worker.js +1 -1
- package/package.json +20 -2
- package/rollup.config.js +4 -4
- package/src/chain.js +112 -102
- package/src/contracts/factory.js +58 -15
- package/src/contracts/{nameService.js → name-service.js} +3 -5
- package/src/contracts/{nativeToken.js → native-token.js} +2 -2
- package/src/contracts/{powerToken.js → power-token.js} +1 -1
- package/src/contracts/proxies/{factoryProxy.js → factory-proxy.js} +1 -1
- package/src/contracts/proxies/{nameServiceProxy.js → name-service-proxy.js} +1 -1
- package/src/contracts/proxies/{nativeTokenProxy.js → native-token-proxy.js} +1 -1
- package/src/contracts/proxies/{validatorsProxy.js → validators-proxy.js} +1 -1
- package/src/contracts/proxies/{votingProxy.js → voting-proxy.js} +1 -1
- package/src/contracts/{proxyManager.js → proxy-manager.js} +1 -1
- package/src/contracts/validators.js +35 -25
- package/src/fee/config.js +1 -1
- package/src/machine.js +34 -29
- package/src/standards/{proxyManager.js → proxy-manager.js} +0 -0
- package/src/standards/{Proxy.js → proxy.js} +4 -8
- package/src/standards/roles.js +7 -5
- package/src/standards/voting.js +1 -0
- package/src/transactions/transaction.js +1 -3
- package/src/transactions/validator.js +1 -1
- package/src/typer.js +1 -1
- package/dist/865.browser.js +0 -10
- package/dist/chain.browser.js +0 -59741
- package/dist/contracts/nativeToken.js +0 -1
- package/dist/generate-account.browser.js +0 -50
- package/dist/messages.browser.js +0 -328
- package/dist/multi-wallet.browser.js +0 -15
- package/dist/node.browser.js +0 -9858
- package/dist/pako.browser.js +0 -6900
- package/dist/peernet-swarm.browser.js +0 -840
- package/dist/storage.browser.js +0 -3724
- package/dist/wrtc.browser.js +0 -28
- package/src/standards/Voting.js +0 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
class Validators{#name="ArtOnlineValidators";#totalValidators=0;#validators={};#
|
|
1
|
+
class Roles{#roles={IMPLEMENTATION_MANAGER:[],OWNER:[],MINT:[],BURN:[]};constructor(roles){if(roles){if(!(roles instanceof Object))throw new TypeError("expected roles to be an object");this.#roles={...roles,...this.#roles}}else this.#grantRole(msg.sender,"OWNER"),this.#grantRole(msg.sender,"IMPLEMENTATION_MANAGER")}get state(){return{roles:this.roles}}get roles(){return{...this.#roles}}hasRole(address,role){return!!this.#roles[role]&&this.#roles[role].includes(address)}#grantRole(address,role){if(this.hasRole(address,role))throw new Error(`${role} role already granted for ${address}`);this.#roles[role].push(address)}#revokeRole(address,role){if(!this.hasRole(address,role))throw new Error(`${role} role already revoked for ${address}`);if("OWNER"===role&&1===this.#roles[role].length)throw new Error("atleast one owner is needed!");this.#roles[role].splice(this.#roles[role].indexOf(address))}grantRole(address,role){if(!this.hasRole(address,"OWNER"))throw new Error("Not allowed");this.#grantRole(address,role)}revokeRole(address,role){if(!this.hasRole(address,"OWNER"))throw new Error("Not allowed");this.#revokeRole(address,role)}}class Validators extends Roles{#name="ArtOnlineValidators";#totalValidators=0;#activeValidators=0;#validators={};#currency;#minimumBalance;get state(){return{...super.state,minimumBalance:this.#minimumBalance,currency:this.#currency,totalValidators:this.#totalValidators,activeValidators:this.#activeValidators,validators:this.#validators}}constructor(tokenAddress,state){super(state?.roles),state?(this.#minimumBalance=state.minimumBalance,this.#currency=state.currency,this.#totalValidators=state.totalValidators,this.#activeValidators=state.activeValidators,this.#validators=state.validators):(this.#minimumBalance=5e4,this.#currency=tokenAddress,this.#totalValidators+=1,this.#activeValidators+=1,this.#validators[msg.sender]={firstSeen:Date.now(),lastSeen:Date.now(),active:!0})}get name(){return this.#name}get currency(){return this.#currency}get validators(){return{...this.#validators}}get totalValidators(){return this.#totalValidators}get minimumBalance(){return this.#minimumBalance}changeCurrency(currency){if(!this.hasRole(msg.sender,"OWNER"))throw new Error("not an owner");this.#currency=currency}has(validator){return Boolean(void 0!==this.#validators[validator])}#isAllowed(address){if(msg.sender!==address&&!this.hasRole(msg.sender,"OWNER"))throw new Error("sender is not the validator or owner");return!0}async addValidator(validator){if(this.#isAllowed(validator),this.has(validator))throw new Error("already a validator");const balance=await msg.staticCall(this.currency,"balanceOf",[validator]);if(balance<this.minimumBalance)throw new Error(`balance to low! got: ${balance} need: ${this.#minimumBalance}`);this.#totalValidators+=1,this.#activeValidators+=1,this.#validators[validator]={firstSeen:Date.now(),lastSeen:Date.now(),active:!0}}removeValidator(validator){if(this.#isAllowed(validator),!this.has(validator))throw new Error("validator not found");this.#totalValidators-=1,this.#validators[validator].active&&(this.#activeValidators-=1),delete this.#validators[validator]}async updateValidator(validator,active){if(this.#isAllowed(validator),!this.has(validator))throw new Error("validator not found");const balance=await msg.staticCall(this.currency,"balanceOf",[validator]);if(balance<this.minimumBalance&&active)throw new Error(`balance to low! got: ${balance} need: ${this.#minimumBalance}`);if(this.#validators[validator].active===active)throw new Error("already "+(active?"activated":"deactivated"));active?this.#activeValidators+=1:this.#activeValidators-=1,this.#validators[validator].active=active}}export{Validators as default};
|
package/dist/module/chain.js
CHANGED
|
@@ -3,8 +3,8 @@ import _BN from 'bn.js';
|
|
|
3
3
|
import '@ethersproject/bytes';
|
|
4
4
|
import { Logger } from '@ethersproject/logger';
|
|
5
5
|
import '@ethersproject/bignumber';
|
|
6
|
-
import { randomBytes } from 'crypto';
|
|
7
|
-
import { join } from 'path';
|
|
6
|
+
import { randomBytes } from 'node:crypto';
|
|
7
|
+
import { join } from 'node:path';
|
|
8
8
|
import EasyWorker from '@vandeurenglenn/easy-worker';
|
|
9
9
|
import { FormatInterface } from '@leofcoin/codec-format-interface';
|
|
10
10
|
import MultiWallet from '@leofcoin/multi-wallet';
|
|
@@ -55,8 +55,8 @@ class Machine {
|
|
|
55
55
|
#nonces = {}
|
|
56
56
|
lastBlock = {index: 0, hash: '0x0', previousHash: '0x0'}
|
|
57
57
|
|
|
58
|
-
constructor() {
|
|
59
|
-
return this.#init()
|
|
58
|
+
constructor(blocks) {
|
|
59
|
+
return this.#init(blocks)
|
|
60
60
|
}
|
|
61
61
|
|
|
62
62
|
#createMessage(sender = peernet.selectedAccount) {
|
|
@@ -69,31 +69,36 @@ class Machine {
|
|
|
69
69
|
|
|
70
70
|
async #onmessage(data) {
|
|
71
71
|
switch (data.type) {
|
|
72
|
-
case 'contractError':
|
|
72
|
+
case 'contractError': {
|
|
73
73
|
console.warn(`removing contract ${await data.hash}`);
|
|
74
74
|
await contractStore.delete(await data.hash);
|
|
75
|
-
break
|
|
75
|
+
break
|
|
76
|
+
}
|
|
76
77
|
|
|
77
|
-
case 'executionError':
|
|
78
|
+
case 'executionError': {
|
|
78
79
|
// console.warn(`error executing transaction ${data.message}`);
|
|
79
80
|
pubsub.publish(data.id, {error: data.message});
|
|
80
|
-
break
|
|
81
|
+
break
|
|
82
|
+
}
|
|
81
83
|
|
|
82
|
-
case 'debug':
|
|
83
|
-
data.messages
|
|
84
|
-
break
|
|
85
|
-
|
|
84
|
+
case 'debug': {
|
|
85
|
+
for (const message of data.messages) debug(message);
|
|
86
|
+
break
|
|
87
|
+
}
|
|
88
|
+
case 'machine-ready': {
|
|
86
89
|
this.lastBlock = data.lastBlock;
|
|
87
90
|
pubsub.publish('machine.ready', true);
|
|
88
|
-
break
|
|
89
|
-
|
|
91
|
+
break
|
|
92
|
+
}
|
|
93
|
+
case 'response': {
|
|
90
94
|
pubsub.publish(data.id, data.value);
|
|
91
|
-
break
|
|
95
|
+
break
|
|
96
|
+
}
|
|
92
97
|
}
|
|
93
98
|
|
|
94
99
|
}
|
|
95
100
|
|
|
96
|
-
async #init() {
|
|
101
|
+
async #init(blocks) {
|
|
97
102
|
return new Promise(async (resolve) => {
|
|
98
103
|
pubsub.subscribe('machine.ready', () => {
|
|
99
104
|
resolve(this);
|
|
@@ -102,7 +107,7 @@ class Machine {
|
|
|
102
107
|
this.worker = await new EasyWorker(join(__dirname, './workers/machine-worker.js'), {serialization: 'advanced', type:'module'});
|
|
103
108
|
this.worker.onmessage(this.#onmessage.bind(this));
|
|
104
109
|
|
|
105
|
-
const blocks = await blockStore.values()
|
|
110
|
+
// const blocks = await blockStore.values()
|
|
106
111
|
const contracts = await Promise.all([
|
|
107
112
|
contractStore.get(contractFactory$1),
|
|
108
113
|
contractStore.get(nativeToken$1),
|
|
@@ -124,19 +129,19 @@ class Machine {
|
|
|
124
129
|
}
|
|
125
130
|
|
|
126
131
|
async #runContract(contractMessage) {
|
|
127
|
-
const
|
|
132
|
+
const parameters = contractMessage.decoded.constructorParameters;
|
|
128
133
|
try {
|
|
129
134
|
|
|
130
|
-
const
|
|
131
|
-
const Contract =
|
|
135
|
+
const function_ = new Function(contractMessage.decoded.contract);
|
|
136
|
+
const Contract = function_();
|
|
132
137
|
|
|
133
138
|
globalThis.msg = this.#createMessage(contractMessage.decoded.creator);
|
|
134
139
|
// globalThis.msg = {sender: contractMessage.decoded.creator}
|
|
135
|
-
this.#contracts[await contractMessage.hash] = await new Contract(...
|
|
140
|
+
this.#contracts[await contractMessage.hash] = await new Contract(...parameters);
|
|
136
141
|
debug(`loaded contract: ${await contractMessage.hash}`);
|
|
137
142
|
debug(`size: ${formatBytes(contractMessage.encoded.length)}`);
|
|
138
|
-
} catch (
|
|
139
|
-
console.log(
|
|
143
|
+
} catch (error) {
|
|
144
|
+
console.log(error);
|
|
140
145
|
console.warn(`removing contract ${await contractMessage.hash}`);
|
|
141
146
|
await contractStore.delete(await contractMessage.hash, contractMessage.encoded);
|
|
142
147
|
}
|
|
@@ -153,7 +158,7 @@ class Machine {
|
|
|
153
158
|
throw new Error('duplicate contract')
|
|
154
159
|
}
|
|
155
160
|
|
|
156
|
-
async execute(contract, method,
|
|
161
|
+
async execute(contract, method, parameters) {
|
|
157
162
|
return new Promise((resolve, reject) => {
|
|
158
163
|
const id = randomBytes(20).toString('hex');
|
|
159
164
|
const message = message => {
|
|
@@ -167,22 +172,22 @@ class Machine {
|
|
|
167
172
|
input: {
|
|
168
173
|
contract,
|
|
169
174
|
method,
|
|
170
|
-
params
|
|
175
|
+
params: parameters
|
|
171
176
|
}
|
|
172
177
|
});
|
|
173
178
|
})
|
|
174
179
|
|
|
175
180
|
}
|
|
176
181
|
|
|
177
|
-
addJob(contract, method,
|
|
182
|
+
addJob(contract, method, parameters, from, nonce) {
|
|
178
183
|
if (!this.#nonces[from]) this.#nonces[from] = nonce;
|
|
179
|
-
if (nonce === this.#nonces[from] + 1) return this.#contracts[contract][method](...
|
|
184
|
+
if (nonce === this.#nonces[from] + 1) return this.#contracts[contract][method](...parameters)
|
|
180
185
|
// return setTimeout(() => {
|
|
181
186
|
// return this.addJob(contract, method, params, from, nonce)
|
|
182
187
|
// }, 50)
|
|
183
188
|
}
|
|
184
189
|
|
|
185
|
-
get(contract, method,
|
|
190
|
+
get(contract, method, parameters) {
|
|
186
191
|
return new Promise((resolve, reject) => {
|
|
187
192
|
const id = randomBytes(20).toString();
|
|
188
193
|
const message = message => {
|
|
@@ -195,7 +200,7 @@ class Machine {
|
|
|
195
200
|
input: {
|
|
196
201
|
contract,
|
|
197
202
|
method,
|
|
198
|
-
params
|
|
203
|
+
params: parameters
|
|
199
204
|
}
|
|
200
205
|
});
|
|
201
206
|
})
|
|
@@ -404,8 +409,10 @@ class Chain {
|
|
|
404
409
|
#blocks = []
|
|
405
410
|
#machine
|
|
406
411
|
#runningEpoch = false
|
|
412
|
+
#chainSyncing = false
|
|
407
413
|
#lastBlock = {index: 0, hash: '0x0', previousHash: '0x0'}
|
|
408
|
-
|
|
414
|
+
#participants = []
|
|
415
|
+
#participating = false
|
|
409
416
|
#jail = []
|
|
410
417
|
|
|
411
418
|
constructor() {
|
|
@@ -445,14 +452,14 @@ class Chain {
|
|
|
445
452
|
console.log(validators);
|
|
446
453
|
if (!validators[peernet.selectedAccount]?.active) return
|
|
447
454
|
|
|
448
|
-
const start =
|
|
455
|
+
const start = Date.now();
|
|
449
456
|
try {
|
|
450
457
|
await this.#createBlock();
|
|
451
|
-
} catch (
|
|
452
|
-
console.error(
|
|
458
|
+
} catch (error) {
|
|
459
|
+
console.error(error);
|
|
453
460
|
}
|
|
454
461
|
|
|
455
|
-
const end =
|
|
462
|
+
const end = Date.now();
|
|
456
463
|
console.log(((end - start) / 1000) + ' s');
|
|
457
464
|
|
|
458
465
|
if (await this.hasTransactionToHandle()) return this.#runEpoch()
|
|
@@ -489,7 +496,7 @@ class Chain {
|
|
|
489
496
|
const timeout = setTimeout(() => {
|
|
490
497
|
resolve([{index: 0, hash: '0x0'}]);
|
|
491
498
|
debug('sync timed out');
|
|
492
|
-
},
|
|
499
|
+
}, 10_000);
|
|
493
500
|
|
|
494
501
|
promises = await Promise.allSettled(promises);
|
|
495
502
|
promises = promises.filter(({status}) => status === 'fulfilled');
|
|
@@ -503,11 +510,11 @@ class Chain {
|
|
|
503
510
|
|
|
504
511
|
}
|
|
505
512
|
|
|
506
|
-
|
|
507
|
-
return this.#
|
|
513
|
+
getLatestBlock() {
|
|
514
|
+
return this.#getLatestBlock()
|
|
508
515
|
}
|
|
509
516
|
|
|
510
|
-
async #
|
|
517
|
+
async #getLatestBlock() {
|
|
511
518
|
let promises = [];
|
|
512
519
|
|
|
513
520
|
let data = await new peernet.protos['peernet-request']({request: 'lastBlock'});
|
|
@@ -519,37 +526,38 @@ class Chain {
|
|
|
519
526
|
} else if (!peer.connected || peer.readyState !== 'open') ;
|
|
520
527
|
}
|
|
521
528
|
promises = await this.promiseRequests(promises);
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
return set
|
|
529
|
-
}, {index: 0, hash: '0x0'});
|
|
530
|
-
// get lastblock
|
|
531
|
-
if (promises.hash && promises.hash !== '0x0') {
|
|
532
|
-
await peernet.get(promises.hash);
|
|
529
|
+
let latest = {index: 0, hash: '0x0'};
|
|
530
|
+
|
|
531
|
+
for (const value of promises) {
|
|
532
|
+
if (value.index > latest.index) {
|
|
533
|
+
latest.index = value.index;
|
|
534
|
+
latest.hash = value.hash;
|
|
533
535
|
}
|
|
534
|
-
|
|
535
|
-
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
if (latest.hash && latest.hash !== '0x0') {
|
|
539
|
+
let latestBlock = await peernet.get(latest.hash, block);
|
|
540
|
+
latestBlock = await new BlockMessage(latestBlock);
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
return latestBlock
|
|
536
544
|
}
|
|
537
545
|
|
|
538
546
|
async #init() {
|
|
539
547
|
// this.node = await new Node()
|
|
540
|
-
this
|
|
541
|
-
this
|
|
548
|
+
this.#participants = [];
|
|
549
|
+
this.#participating = false;
|
|
542
550
|
const initialized = await contractStore.has(addresses.contractFactory);
|
|
543
551
|
if (!initialized) await this.#setup();
|
|
544
552
|
|
|
545
|
-
|
|
553
|
+
|
|
546
554
|
this.utils = { BigNumber, formatUnits, parseUnits };
|
|
547
555
|
|
|
548
556
|
try {
|
|
549
557
|
let localBlock;
|
|
550
558
|
try {
|
|
551
559
|
localBlock = await chainStore.get('lastBlock');
|
|
552
|
-
} catch
|
|
560
|
+
} catch{
|
|
553
561
|
await chainStore.put('lastBlock', '0x0');
|
|
554
562
|
localBlock = await chainStore.get('lastBlock');
|
|
555
563
|
}
|
|
@@ -559,13 +567,11 @@ class Chain {
|
|
|
559
567
|
localBlock = await new BlockMessage(localBlock);
|
|
560
568
|
this.#lastBlock = {...localBlock.decoded, hash: await localBlock.hash};
|
|
561
569
|
} else {
|
|
562
|
-
await this.#
|
|
570
|
+
const latestBlock = await this.#getLatestBlock();
|
|
571
|
+
await this.#syncChain(latestBlock);
|
|
563
572
|
}
|
|
564
|
-
} catch (
|
|
565
|
-
console.log({e});
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
// this.#setup()
|
|
573
|
+
} catch (error) {
|
|
574
|
+
console.log({e: error});
|
|
569
575
|
}
|
|
570
576
|
|
|
571
577
|
await peernet.addRequestHandler('bw-request-message', () => {
|
|
@@ -586,6 +592,8 @@ class Chain {
|
|
|
586
592
|
|
|
587
593
|
// load local blocks
|
|
588
594
|
await this.resolveBlocks();
|
|
595
|
+
this.#machine = await new Machine(this.#blocks);
|
|
596
|
+
await this.#loadBlocks(this.#blocks);
|
|
589
597
|
return this
|
|
590
598
|
}
|
|
591
599
|
|
|
@@ -596,29 +604,33 @@ class Chain {
|
|
|
596
604
|
this.#jail.push(validatorInfo.address);
|
|
597
605
|
}
|
|
598
606
|
|
|
599
|
-
async #
|
|
600
|
-
|
|
601
|
-
node = await peernet.prepareMessage(node);
|
|
602
|
-
let response = await peer.request(node.encoded);
|
|
603
|
-
response = await new globalThis.peernet.protos['peernet-response'](response);
|
|
604
|
-
let lastBlock = response.decoded.response;
|
|
607
|
+
async #syncChain(lastBlock) {
|
|
608
|
+
if (this.#chainSyncing) return
|
|
605
609
|
|
|
606
610
|
if (!this.lastBlock || Number(this.lastBlock.index) < Number(lastBlock.index)) {
|
|
607
|
-
|
|
611
|
+
this.#chainSyncing = true;
|
|
612
|
+
// TODO: check if valid
|
|
608
613
|
const localIndex = this.lastBlock ? this.lastBlock.index : 0;
|
|
609
614
|
const index = lastBlock.index;
|
|
610
615
|
await this.resolveBlock(lastBlock.hash);
|
|
611
|
-
let blocksSynced = localIndex > 0 ? localIndex > index ? localIndex - index : index - localIndex : index;
|
|
616
|
+
let blocksSynced = localIndex > 0 ? (localIndex > index ? localIndex - index : index - localIndex) : index;
|
|
612
617
|
debug(`synced ${blocksSynced} ${blocksSynced > 1 ? 'blocks' : 'block'}`);
|
|
613
618
|
|
|
614
619
|
this.#blocks.length;
|
|
615
|
-
|
|
616
|
-
await this.#loadBlocks(this
|
|
617
|
-
this.#
|
|
618
|
-
|
|
619
|
-
await blockStore.put(await message.hash, message.encoded);
|
|
620
|
-
await chainStore.put('lastBlock', this.lastBlock.hash);
|
|
620
|
+
const start = this.#blocks.length - blocksSynced;
|
|
621
|
+
await this.#loadBlocks(this.blocks.slice(start));
|
|
622
|
+
await this.#updateState(this.#blocks[this.#blocks.length - 1]);
|
|
623
|
+
this.#chainSyncing = false;
|
|
621
624
|
}
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
async #peerConnected(peer) {
|
|
628
|
+
let node = await new peernet.protos['peernet-request']({request: 'lastBlock'});
|
|
629
|
+
node = await peernet.prepareMessage(node);
|
|
630
|
+
let response = await peer.request(node.encoded);
|
|
631
|
+
response = await new globalThis.peernet.protos['peernet-response'](response);
|
|
632
|
+
let lastBlock = response.decoded.response;
|
|
633
|
+
this.#syncChain(lastBlock);
|
|
622
634
|
}
|
|
623
635
|
|
|
624
636
|
#epochTimeout
|
|
@@ -628,9 +640,9 @@ class Chain {
|
|
|
628
640
|
transaction = await new TransactionMessage(transaction);
|
|
629
641
|
const has = await transactionPoolStore.has(await transaction.hash);
|
|
630
642
|
if (!has) await transactionPoolStore.put(await transaction.hash, transaction.encoded);
|
|
631
|
-
if (this
|
|
632
|
-
} catch
|
|
633
|
-
throw Error('invalid transaction')
|
|
643
|
+
if (this.#participating && !this.#runningEpoch) this.#runEpoch();
|
|
644
|
+
} catch {
|
|
645
|
+
throw new Error('invalid transaction')
|
|
634
646
|
}
|
|
635
647
|
}
|
|
636
648
|
|
|
@@ -643,11 +655,11 @@ async resolveBlock(hash) {
|
|
|
643
655
|
let block = await peernet.get(hash, 'block');
|
|
644
656
|
block = await new BlockMessage(block);
|
|
645
657
|
if (!await peernet.has(hash, 'block')) await peernet.put(hash, block.encoded, 'block');
|
|
646
|
-
const size = block.encoded.length
|
|
658
|
+
const size = block.encoded.length > 0 ? block.encoded.length : block.encoded.byteLength;
|
|
647
659
|
block = {...block.decoded, hash};
|
|
648
|
-
if (this.#blocks[block.index]) throw `invalid block ${hash} @${block.index}`
|
|
660
|
+
if (this.#blocks[block.index] && this.#blocks[block.index].hash !== block.hash) throw `invalid block ${hash} @${block.index}`
|
|
649
661
|
this.#blocks[block.index] = block;
|
|
650
|
-
console.log(`
|
|
662
|
+
console.log(`resolved block: ${hash} @${block.index} ${formatBytes(size)}`);
|
|
651
663
|
if (block.previousHash !== '0x0') {
|
|
652
664
|
return this.resolveBlock(block.previousHash)
|
|
653
665
|
}
|
|
@@ -661,8 +673,8 @@ async resolveBlock(hash) {
|
|
|
661
673
|
if (hash && hash !== '0x0')
|
|
662
674
|
await this.resolveBlock(hash);
|
|
663
675
|
this.#lastBlock = this.#blocks[this.#blocks.length - 1];
|
|
664
|
-
|
|
665
|
-
} catch
|
|
676
|
+
|
|
677
|
+
} catch {
|
|
666
678
|
await chainStore.put('lastBlock', new TextEncoder().encode('0x0'));
|
|
667
679
|
return this.resolveBlocks()
|
|
668
680
|
// console.log(e);
|
|
@@ -676,11 +688,12 @@ async resolveBlock(hash) {
|
|
|
676
688
|
try {
|
|
677
689
|
await this.#machine.execute(transaction.to, transaction.method, transaction.params);
|
|
678
690
|
|
|
679
|
-
} catch (
|
|
680
|
-
console.log(
|
|
691
|
+
} catch (error) {
|
|
692
|
+
console.log(error);
|
|
681
693
|
}
|
|
682
694
|
}
|
|
683
|
-
block.loaded = true;
|
|
695
|
+
this.#blocks[block.index].loaded = true;
|
|
696
|
+
console.log(`loaded block: ${block.hash} @${block.index}`);
|
|
684
697
|
// let message = await peernet.get(block.hash, 'block')
|
|
685
698
|
|
|
686
699
|
// const compressed = pako.deflate(message);
|
|
@@ -708,10 +721,10 @@ async resolveBlock(hash) {
|
|
|
708
721
|
let result = await this.#machine.execute(to, method, params, from, nonce);
|
|
709
722
|
// if (!result) result = this.#machine.state
|
|
710
723
|
pubsub.publish(`transaction.completed.${hash}`, {status: 'fulfilled', hash});
|
|
711
|
-
return result
|
|
712
|
-
} catch (
|
|
713
|
-
pubsub.publish(`transaction.completed.${hash}`, {status: 'fail', hash, error:
|
|
714
|
-
throw
|
|
724
|
+
return result || 'no state change'
|
|
725
|
+
} catch (error) {
|
|
726
|
+
pubsub.publish(`transaction.completed.${hash}`, {status: 'fail', hash, error: error});
|
|
727
|
+
throw error
|
|
715
728
|
}
|
|
716
729
|
}
|
|
717
730
|
|
|
@@ -732,8 +745,6 @@ async resolveBlock(hash) {
|
|
|
732
745
|
// transaction = new TransactionMessage(transaction)
|
|
733
746
|
// return transaction
|
|
734
747
|
// }
|
|
735
|
-
|
|
736
|
-
console.log(blockMessage);
|
|
737
748
|
await Promise.all(blockMessage.decoded.transactions
|
|
738
749
|
.map(async transaction => transactionPoolStore.delete(await transaction.hash)));
|
|
739
750
|
const hash = await blockMessage.hash;
|
|
@@ -750,11 +761,15 @@ async resolveBlock(hash) {
|
|
|
750
761
|
// await transactionStore.put(transaction.hash, transaction.encoded)
|
|
751
762
|
const index = contracts.indexOf(transaction.to);
|
|
752
763
|
if (index === -1) contracts.push(transaction.to);
|
|
764
|
+
// Todo: go trough all accounts
|
|
753
765
|
promises.push(this.#executeTransaction(transaction));
|
|
766
|
+
|
|
754
767
|
}
|
|
755
768
|
try {
|
|
756
769
|
promises = await Promise.allSettled(promises);
|
|
757
770
|
for (let transaction of blockMessage.decoded.transactions) {
|
|
771
|
+
pubsub.publish('transaction-processed', transaction);
|
|
772
|
+
if (transaction.to === peernet.selectedAccount) pubsub.publish('account-transaction-processed', transaction);
|
|
758
773
|
await accountsStore.put(transaction.from, String(transaction.nonce));
|
|
759
774
|
}
|
|
760
775
|
|
|
@@ -767,8 +782,9 @@ async resolveBlock(hash) {
|
|
|
767
782
|
|
|
768
783
|
|
|
769
784
|
pubsub.publish('block-processed', blockMessage.decoded);
|
|
770
|
-
|
|
771
|
-
|
|
785
|
+
|
|
786
|
+
} catch (error) {
|
|
787
|
+
console.log({e: error});
|
|
772
788
|
}
|
|
773
789
|
|
|
774
790
|
}
|
|
@@ -788,7 +804,7 @@ async resolveBlock(hash) {
|
|
|
788
804
|
// introduce peer-reputation
|
|
789
805
|
// peerReputation(peerId)
|
|
790
806
|
// {bandwith: {up, down}, uptime}
|
|
791
|
-
this
|
|
807
|
+
this.#participating = true;
|
|
792
808
|
if (!await this.staticCall(addresses.validators, 'has', [address])) await this.createTransactionFrom(address, addresses.validators, 'addValidator', [address]);
|
|
793
809
|
if (await this.hasTransactionToHandle() && !this.#runningEpoch) await this.#runEpoch();
|
|
794
810
|
|
|
@@ -850,7 +866,7 @@ async resolveBlock(hash) {
|
|
|
850
866
|
block.transactions.push(transaction);
|
|
851
867
|
block.fees += Number(calculateFee(transaction));
|
|
852
868
|
await accountsStore.put(transaction.from, new TextEncoder().encode(String(transaction.nonce)));
|
|
853
|
-
} catch
|
|
869
|
+
} catch {
|
|
854
870
|
transaction = await new TransactionMessage(transaction);
|
|
855
871
|
await transactionPoolStore.delete(await transaction.hash);
|
|
856
872
|
}
|
|
@@ -883,9 +899,7 @@ async resolveBlock(hash) {
|
|
|
883
899
|
address: validator,
|
|
884
900
|
bw: bw.up + bw.down
|
|
885
901
|
});
|
|
886
|
-
} catch
|
|
887
|
-
|
|
888
|
-
}
|
|
902
|
+
} catch{}
|
|
889
903
|
|
|
890
904
|
} else if (peernet.selectedAccount === validator) {
|
|
891
905
|
block.validators.push({
|
|
@@ -913,17 +927,17 @@ async resolveBlock(hash) {
|
|
|
913
927
|
else block.index += 1;
|
|
914
928
|
|
|
915
929
|
block.previousHash = this.lastBlock?.hash || '0x0';
|
|
916
|
-
block.timestamp =
|
|
930
|
+
block.timestamp = Date.now();
|
|
917
931
|
|
|
918
932
|
const parts = String(block.fees).split('.');
|
|
919
933
|
let decimals = 0;
|
|
920
934
|
if (parts[1]) {
|
|
921
935
|
const potentional = parts[1].split('e');
|
|
922
|
-
if (potentional[0]
|
|
923
|
-
parts[1] = potentional[0];
|
|
924
|
-
decimals = Number(potentional[1]?.replace(/\-|\+/g, '')) + Number(potentional[0].length);
|
|
925
|
-
} else {
|
|
936
|
+
if (potentional[0] === parts[1]) {
|
|
926
937
|
decimals = parts[1].length;
|
|
938
|
+
} else {
|
|
939
|
+
parts[1] = potentional[0];
|
|
940
|
+
decimals = Number(potentional[1]?.replace(/[+-]/g, '')) + Number(potentional[0].length);
|
|
927
941
|
}
|
|
928
942
|
|
|
929
943
|
}
|
|
@@ -943,9 +957,10 @@ async resolveBlock(hash) {
|
|
|
943
957
|
debug(`created block: ${hash}`);
|
|
944
958
|
|
|
945
959
|
peernet.publish('add-block', blockMessage.encoded);
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
960
|
+
pubsub.publish('add-block', blockMessage.decoded);
|
|
961
|
+
} catch (error) {
|
|
962
|
+
console.log(error);
|
|
963
|
+
throw new Error(`invalid block ${block}`)
|
|
949
964
|
}
|
|
950
965
|
// data = await this.#machine.execute(to, method, params)
|
|
951
966
|
// transactionStore.put(message.hash, message.encoded)
|
|
@@ -1014,8 +1029,8 @@ async resolveBlock(hash) {
|
|
|
1014
1029
|
* @param {Array} params - array of paramters to apply to the contract method
|
|
1015
1030
|
* @param {Number} nonce - total transaction count [optional]
|
|
1016
1031
|
*/
|
|
1017
|
-
async createTransaction(to, method,
|
|
1018
|
-
return this.createTransactionFrom(peernet.selectedAccount, to, method,
|
|
1032
|
+
async createTransaction(to, method, parameters, nonce, signature) {
|
|
1033
|
+
return this.createTransactionFrom(peernet.selectedAccount, to, method, parameters, nonce)
|
|
1019
1034
|
}
|
|
1020
1035
|
|
|
1021
1036
|
|
|
@@ -1075,8 +1090,8 @@ async #signTransaction (transaction, wallet) {
|
|
|
1075
1090
|
} else {
|
|
1076
1091
|
let nonce = await accountsStore.get(transaction.from);
|
|
1077
1092
|
nonce = new TextDecoder().decode(nonce);
|
|
1078
|
-
if (transaction.nonce < nonce) throw Error(`a transaction with a higher nonce already exists`)
|
|
1079
|
-
if (transaction.nonce === nonce) throw Error(`a transaction with the same nonce already exists`)
|
|
1093
|
+
if (transaction.nonce < nonce) throw new Error(`a transaction with a higher nonce already exists`)
|
|
1094
|
+
if (transaction.nonce === nonce) throw new Error(`a transaction with the same nonce already exists`)
|
|
1080
1095
|
}
|
|
1081
1096
|
return transaction
|
|
1082
1097
|
}
|
|
@@ -1091,10 +1106,10 @@ async #signTransaction (transaction, wallet) {
|
|
|
1091
1106
|
* @param {Array} params - array of paramters to apply to the contract method
|
|
1092
1107
|
* @param {Number} nonce - total transaction count [optional]
|
|
1093
1108
|
*/
|
|
1094
|
-
async createTransactionFrom(from, to, method,
|
|
1109
|
+
async createTransactionFrom(from, to, method, parameters, nonce) {
|
|
1095
1110
|
try {
|
|
1096
1111
|
|
|
1097
|
-
const rawTransaction = await this.createRawTransaction({from, to, nonce, method, params});
|
|
1112
|
+
const rawTransaction = await this.createRawTransaction({from, to, nonce, method, params: parameters});
|
|
1098
1113
|
const transaction = await this.signTransaction(rawTransaction, from);
|
|
1099
1114
|
const message = await new TransactionMessage(transaction);
|
|
1100
1115
|
|
|
@@ -1110,7 +1125,7 @@ async #signTransaction (transaction, wallet) {
|
|
|
1110
1125
|
|
|
1111
1126
|
setTimeout(async () => {
|
|
1112
1127
|
pubsub.unsubscribe(`transaction.completed.${await message.hash}`, completed);
|
|
1113
|
-
},
|
|
1128
|
+
}, 10_000);
|
|
1114
1129
|
};
|
|
1115
1130
|
pubsub.subscribe(`transaction.completed.${await message.hash}`, completed);
|
|
1116
1131
|
}
|
|
@@ -1122,9 +1137,9 @@ async #signTransaction (transaction, wallet) {
|
|
|
1122
1137
|
peernet.publish('add-transaction', message.encoded);
|
|
1123
1138
|
this.#addTransaction(message.encoded);
|
|
1124
1139
|
return {hash: await message.hash, data, fee: await calculateFee(message.decoded), wait}
|
|
1125
|
-
} catch (
|
|
1126
|
-
console.log(
|
|
1127
|
-
throw
|
|
1140
|
+
} catch (error) {
|
|
1141
|
+
console.log(error);
|
|
1142
|
+
throw error
|
|
1128
1143
|
}
|
|
1129
1144
|
|
|
1130
1145
|
}
|
|
@@ -1142,15 +1157,15 @@ async #signTransaction (transaction, wallet) {
|
|
|
1142
1157
|
*
|
|
1143
1158
|
* @param {String} contract - a contract string (see plugins/deployContract)
|
|
1144
1159
|
*/
|
|
1145
|
-
async deployContract(contract,
|
|
1160
|
+
async deployContract(contract, parameters = []) {
|
|
1146
1161
|
globalThis.msg = {sender: peernet.selectedAccount, call: this.call};
|
|
1147
1162
|
|
|
1148
|
-
const hash = await this.createContractAddress(creator, contract,
|
|
1163
|
+
const hash = await this.createContractAddress(creator, contract, parameters);
|
|
1149
1164
|
console.log(hash);
|
|
1150
1165
|
try {
|
|
1151
1166
|
const tx = await this.createTransactionFrom(peernet.selectedAccount, addresses.contractFactory, 'deployContract', [hash, creator, contract, constructorParameters]);
|
|
1152
|
-
} catch (
|
|
1153
|
-
throw
|
|
1167
|
+
} catch (error) {
|
|
1168
|
+
throw error
|
|
1154
1169
|
}
|
|
1155
1170
|
return this.#machine.addContract(message)
|
|
1156
1171
|
}
|
|
@@ -1165,33 +1180,33 @@ console.log(hash);
|
|
|
1165
1180
|
}
|
|
1166
1181
|
}
|
|
1167
1182
|
|
|
1168
|
-
internalCall(sender, contract, method,
|
|
1183
|
+
internalCall(sender, contract, method, parameters) {
|
|
1169
1184
|
globalThis.msg = this.#createMessage(sender);
|
|
1170
1185
|
|
|
1171
|
-
return this.#machine.execute(contract, method,
|
|
1186
|
+
return this.#machine.execute(contract, method, parameters)
|
|
1172
1187
|
}
|
|
1173
1188
|
|
|
1174
|
-
call(contract, method,
|
|
1189
|
+
call(contract, method, parameters) {
|
|
1175
1190
|
globalThis.msg = this.#createMessage();
|
|
1176
1191
|
|
|
1177
|
-
return this.#machine.execute(contract, method,
|
|
1192
|
+
return this.#machine.execute(contract, method, parameters)
|
|
1178
1193
|
}
|
|
1179
1194
|
|
|
1180
|
-
staticCall(contract, method,
|
|
1195
|
+
staticCall(contract, method, parameters) {
|
|
1181
1196
|
globalThis.msg = this.#createMessage();
|
|
1182
|
-
return this.#machine.get(contract, method,
|
|
1197
|
+
return this.#machine.get(contract, method, parameters)
|
|
1183
1198
|
}
|
|
1184
1199
|
|
|
1185
|
-
delegate(contract, method,
|
|
1200
|
+
delegate(contract, method, parameters) {
|
|
1186
1201
|
globalThis.msg = this.#createMessage();
|
|
1187
1202
|
|
|
1188
|
-
return this.#machine.execute(contract, method,
|
|
1203
|
+
return this.#machine.execute(contract, method, parameters)
|
|
1189
1204
|
}
|
|
1190
1205
|
|
|
1191
|
-
staticDelegate(contract, method,
|
|
1206
|
+
staticDelegate(contract, method, parameters) {
|
|
1192
1207
|
globalThis.msg = this.#createMessage();
|
|
1193
1208
|
|
|
1194
|
-
return this.#machine.get(contract, method,
|
|
1209
|
+
return this.#machine.get(contract, method, parameters)
|
|
1195
1210
|
}
|
|
1196
1211
|
|
|
1197
1212
|
mint(to, amount) {
|