@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
package/dist/chain.js
CHANGED
|
@@ -5,8 +5,8 @@ var _BN = require('bn.js');
|
|
|
5
5
|
require('@ethersproject/bytes');
|
|
6
6
|
var logger = require('@ethersproject/logger');
|
|
7
7
|
require('@ethersproject/bignumber');
|
|
8
|
-
var
|
|
9
|
-
var
|
|
8
|
+
var node_crypto = require('node:crypto');
|
|
9
|
+
var node_path = require('node:path');
|
|
10
10
|
var EasyWorker = require('@vandeurenglenn/easy-worker');
|
|
11
11
|
var codecFormatInterface = require('@leofcoin/codec-format-interface');
|
|
12
12
|
var MultiWallet = require('@leofcoin/multi-wallet');
|
|
@@ -64,8 +64,8 @@ class Machine {
|
|
|
64
64
|
#nonces = {}
|
|
65
65
|
lastBlock = {index: 0, hash: '0x0', previousHash: '0x0'}
|
|
66
66
|
|
|
67
|
-
constructor() {
|
|
68
|
-
return this.#init()
|
|
67
|
+
constructor(blocks) {
|
|
68
|
+
return this.#init(blocks)
|
|
69
69
|
}
|
|
70
70
|
|
|
71
71
|
#createMessage(sender = peernet.selectedAccount) {
|
|
@@ -78,40 +78,45 @@ class Machine {
|
|
|
78
78
|
|
|
79
79
|
async #onmessage(data) {
|
|
80
80
|
switch (data.type) {
|
|
81
|
-
case 'contractError':
|
|
81
|
+
case 'contractError': {
|
|
82
82
|
console.warn(`removing contract ${await data.hash}`);
|
|
83
83
|
await contractStore.delete(await data.hash);
|
|
84
|
-
break
|
|
84
|
+
break
|
|
85
|
+
}
|
|
85
86
|
|
|
86
|
-
case 'executionError':
|
|
87
|
+
case 'executionError': {
|
|
87
88
|
// console.warn(`error executing transaction ${data.message}`);
|
|
88
89
|
pubsub.publish(data.id, {error: data.message});
|
|
89
|
-
break
|
|
90
|
+
break
|
|
91
|
+
}
|
|
90
92
|
|
|
91
|
-
case 'debug':
|
|
92
|
-
data.messages
|
|
93
|
-
break
|
|
94
|
-
|
|
93
|
+
case 'debug': {
|
|
94
|
+
for (const message of data.messages) debug(message);
|
|
95
|
+
break
|
|
96
|
+
}
|
|
97
|
+
case 'machine-ready': {
|
|
95
98
|
this.lastBlock = data.lastBlock;
|
|
96
99
|
pubsub.publish('machine.ready', true);
|
|
97
|
-
break
|
|
98
|
-
|
|
100
|
+
break
|
|
101
|
+
}
|
|
102
|
+
case 'response': {
|
|
99
103
|
pubsub.publish(data.id, data.value);
|
|
100
|
-
break
|
|
104
|
+
break
|
|
105
|
+
}
|
|
101
106
|
}
|
|
102
107
|
|
|
103
108
|
}
|
|
104
109
|
|
|
105
|
-
async #init() {
|
|
110
|
+
async #init(blocks) {
|
|
106
111
|
return new Promise(async (resolve) => {
|
|
107
112
|
pubsub.subscribe('machine.ready', () => {
|
|
108
113
|
resolve(this);
|
|
109
114
|
});
|
|
110
115
|
|
|
111
|
-
this.worker = await new EasyWorker__default["default"](
|
|
116
|
+
this.worker = await new EasyWorker__default["default"](node_path.join(__dirname, './workers/machine-worker.js'), {serialization: 'advanced', type:'module'});
|
|
112
117
|
this.worker.onmessage(this.#onmessage.bind(this));
|
|
113
118
|
|
|
114
|
-
const blocks = await blockStore.values()
|
|
119
|
+
// const blocks = await blockStore.values()
|
|
115
120
|
const contracts = await Promise.all([
|
|
116
121
|
contractStore.get(contractFactory$1),
|
|
117
122
|
contractStore.get(nativeToken$1),
|
|
@@ -133,19 +138,19 @@ class Machine {
|
|
|
133
138
|
}
|
|
134
139
|
|
|
135
140
|
async #runContract(contractMessage) {
|
|
136
|
-
const
|
|
141
|
+
const parameters = contractMessage.decoded.constructorParameters;
|
|
137
142
|
try {
|
|
138
143
|
|
|
139
|
-
const
|
|
140
|
-
const Contract =
|
|
144
|
+
const function_ = new Function(contractMessage.decoded.contract);
|
|
145
|
+
const Contract = function_();
|
|
141
146
|
|
|
142
147
|
globalThis.msg = this.#createMessage(contractMessage.decoded.creator);
|
|
143
148
|
// globalThis.msg = {sender: contractMessage.decoded.creator}
|
|
144
|
-
this.#contracts[await contractMessage.hash] = await new Contract(...
|
|
149
|
+
this.#contracts[await contractMessage.hash] = await new Contract(...parameters);
|
|
145
150
|
debug(`loaded contract: ${await contractMessage.hash}`);
|
|
146
151
|
debug(`size: ${formatBytes(contractMessage.encoded.length)}`);
|
|
147
|
-
} catch (
|
|
148
|
-
console.log(
|
|
152
|
+
} catch (error) {
|
|
153
|
+
console.log(error);
|
|
149
154
|
console.warn(`removing contract ${await contractMessage.hash}`);
|
|
150
155
|
await contractStore.delete(await contractMessage.hash, contractMessage.encoded);
|
|
151
156
|
}
|
|
@@ -162,9 +167,9 @@ class Machine {
|
|
|
162
167
|
throw new Error('duplicate contract')
|
|
163
168
|
}
|
|
164
169
|
|
|
165
|
-
async execute(contract, method,
|
|
170
|
+
async execute(contract, method, parameters) {
|
|
166
171
|
return new Promise((resolve, reject) => {
|
|
167
|
-
const id =
|
|
172
|
+
const id = node_crypto.randomBytes(20).toString('hex');
|
|
168
173
|
const message = message => {
|
|
169
174
|
if (message?.error) reject(message.error);
|
|
170
175
|
else resolve(message);
|
|
@@ -176,24 +181,24 @@ class Machine {
|
|
|
176
181
|
input: {
|
|
177
182
|
contract,
|
|
178
183
|
method,
|
|
179
|
-
params
|
|
184
|
+
params: parameters
|
|
180
185
|
}
|
|
181
186
|
});
|
|
182
187
|
})
|
|
183
188
|
|
|
184
189
|
}
|
|
185
190
|
|
|
186
|
-
addJob(contract, method,
|
|
191
|
+
addJob(contract, method, parameters, from, nonce) {
|
|
187
192
|
if (!this.#nonces[from]) this.#nonces[from] = nonce;
|
|
188
|
-
if (nonce === this.#nonces[from] + 1) return this.#contracts[contract][method](...
|
|
193
|
+
if (nonce === this.#nonces[from] + 1) return this.#contracts[contract][method](...parameters)
|
|
189
194
|
// return setTimeout(() => {
|
|
190
195
|
// return this.addJob(contract, method, params, from, nonce)
|
|
191
196
|
// }, 50)
|
|
192
197
|
}
|
|
193
198
|
|
|
194
|
-
get(contract, method,
|
|
199
|
+
get(contract, method, parameters) {
|
|
195
200
|
return new Promise((resolve, reject) => {
|
|
196
|
-
const id =
|
|
201
|
+
const id = node_crypto.randomBytes(20).toString();
|
|
197
202
|
const message = message => {
|
|
198
203
|
resolve(message);
|
|
199
204
|
};
|
|
@@ -204,7 +209,7 @@ class Machine {
|
|
|
204
209
|
input: {
|
|
205
210
|
contract,
|
|
206
211
|
method,
|
|
207
|
-
params
|
|
212
|
+
params: parameters
|
|
208
213
|
}
|
|
209
214
|
});
|
|
210
215
|
})
|
|
@@ -413,8 +418,10 @@ class Chain {
|
|
|
413
418
|
#blocks = []
|
|
414
419
|
#machine
|
|
415
420
|
#runningEpoch = false
|
|
421
|
+
#chainSyncing = false
|
|
416
422
|
#lastBlock = {index: 0, hash: '0x0', previousHash: '0x0'}
|
|
417
|
-
|
|
423
|
+
#participants = []
|
|
424
|
+
#participating = false
|
|
418
425
|
#jail = []
|
|
419
426
|
|
|
420
427
|
constructor() {
|
|
@@ -454,14 +461,14 @@ class Chain {
|
|
|
454
461
|
console.log(validators);
|
|
455
462
|
if (!validators[peernet.selectedAccount]?.active) return
|
|
456
463
|
|
|
457
|
-
const start =
|
|
464
|
+
const start = Date.now();
|
|
458
465
|
try {
|
|
459
466
|
await this.#createBlock();
|
|
460
|
-
} catch (
|
|
461
|
-
console.error(
|
|
467
|
+
} catch (error) {
|
|
468
|
+
console.error(error);
|
|
462
469
|
}
|
|
463
470
|
|
|
464
|
-
const end =
|
|
471
|
+
const end = Date.now();
|
|
465
472
|
console.log(((end - start) / 1000) + ' s');
|
|
466
473
|
|
|
467
474
|
if (await this.hasTransactionToHandle()) return this.#runEpoch()
|
|
@@ -498,7 +505,7 @@ class Chain {
|
|
|
498
505
|
const timeout = setTimeout(() => {
|
|
499
506
|
resolve([{index: 0, hash: '0x0'}]);
|
|
500
507
|
debug('sync timed out');
|
|
501
|
-
},
|
|
508
|
+
}, 10_000);
|
|
502
509
|
|
|
503
510
|
promises = await Promise.allSettled(promises);
|
|
504
511
|
promises = promises.filter(({status}) => status === 'fulfilled');
|
|
@@ -512,11 +519,11 @@ class Chain {
|
|
|
512
519
|
|
|
513
520
|
}
|
|
514
521
|
|
|
515
|
-
|
|
516
|
-
return this.#
|
|
522
|
+
getLatestBlock() {
|
|
523
|
+
return this.#getLatestBlock()
|
|
517
524
|
}
|
|
518
525
|
|
|
519
|
-
async #
|
|
526
|
+
async #getLatestBlock() {
|
|
520
527
|
let promises = [];
|
|
521
528
|
|
|
522
529
|
let data = await new peernet.protos['peernet-request']({request: 'lastBlock'});
|
|
@@ -528,37 +535,38 @@ class Chain {
|
|
|
528
535
|
} else if (!peer.connected || peer.readyState !== 'open') ;
|
|
529
536
|
}
|
|
530
537
|
promises = await this.promiseRequests(promises);
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
return set
|
|
538
|
-
}, {index: 0, hash: '0x0'});
|
|
539
|
-
// get lastblock
|
|
540
|
-
if (promises.hash && promises.hash !== '0x0') {
|
|
541
|
-
await peernet.get(promises.hash);
|
|
538
|
+
let latest = {index: 0, hash: '0x0'};
|
|
539
|
+
|
|
540
|
+
for (const value of promises) {
|
|
541
|
+
if (value.index > latest.index) {
|
|
542
|
+
latest.index = value.index;
|
|
543
|
+
latest.hash = value.hash;
|
|
542
544
|
}
|
|
543
|
-
|
|
544
|
-
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
if (latest.hash && latest.hash !== '0x0') {
|
|
548
|
+
let latestBlock = await peernet.get(latest.hash, block);
|
|
549
|
+
latestBlock = await new BlockMessage(latestBlock);
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
return latestBlock
|
|
545
553
|
}
|
|
546
554
|
|
|
547
555
|
async #init() {
|
|
548
556
|
// this.node = await new Node()
|
|
549
|
-
this
|
|
550
|
-
this
|
|
557
|
+
this.#participants = [];
|
|
558
|
+
this.#participating = false;
|
|
551
559
|
const initialized = await contractStore.has(addresses.contractFactory);
|
|
552
560
|
if (!initialized) await this.#setup();
|
|
553
561
|
|
|
554
|
-
|
|
562
|
+
|
|
555
563
|
this.utils = { BigNumber: utils.BigNumber, formatUnits: utils.formatUnits, parseUnits: utils.parseUnits };
|
|
556
564
|
|
|
557
565
|
try {
|
|
558
566
|
let localBlock;
|
|
559
567
|
try {
|
|
560
568
|
localBlock = await chainStore.get('lastBlock');
|
|
561
|
-
} catch
|
|
569
|
+
} catch{
|
|
562
570
|
await chainStore.put('lastBlock', '0x0');
|
|
563
571
|
localBlock = await chainStore.get('lastBlock');
|
|
564
572
|
}
|
|
@@ -568,13 +576,11 @@ class Chain {
|
|
|
568
576
|
localBlock = await new BlockMessage(localBlock);
|
|
569
577
|
this.#lastBlock = {...localBlock.decoded, hash: await localBlock.hash};
|
|
570
578
|
} else {
|
|
571
|
-
await this.#
|
|
579
|
+
const latestBlock = await this.#getLatestBlock();
|
|
580
|
+
await this.#syncChain(latestBlock);
|
|
572
581
|
}
|
|
573
|
-
} catch (
|
|
574
|
-
console.log({e});
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
// this.#setup()
|
|
582
|
+
} catch (error) {
|
|
583
|
+
console.log({e: error});
|
|
578
584
|
}
|
|
579
585
|
|
|
580
586
|
await peernet.addRequestHandler('bw-request-message', () => {
|
|
@@ -595,6 +601,8 @@ class Chain {
|
|
|
595
601
|
|
|
596
602
|
// load local blocks
|
|
597
603
|
await this.resolveBlocks();
|
|
604
|
+
this.#machine = await new Machine(this.#blocks);
|
|
605
|
+
await this.#loadBlocks(this.#blocks);
|
|
598
606
|
return this
|
|
599
607
|
}
|
|
600
608
|
|
|
@@ -605,29 +613,33 @@ class Chain {
|
|
|
605
613
|
this.#jail.push(validatorInfo.address);
|
|
606
614
|
}
|
|
607
615
|
|
|
608
|
-
async #
|
|
609
|
-
|
|
610
|
-
node = await peernet.prepareMessage(node);
|
|
611
|
-
let response = await peer.request(node.encoded);
|
|
612
|
-
response = await new globalThis.peernet.protos['peernet-response'](response);
|
|
613
|
-
let lastBlock = response.decoded.response;
|
|
616
|
+
async #syncChain(lastBlock) {
|
|
617
|
+
if (this.#chainSyncing) return
|
|
614
618
|
|
|
615
619
|
if (!this.lastBlock || Number(this.lastBlock.index) < Number(lastBlock.index)) {
|
|
616
|
-
|
|
620
|
+
this.#chainSyncing = true;
|
|
621
|
+
// TODO: check if valid
|
|
617
622
|
const localIndex = this.lastBlock ? this.lastBlock.index : 0;
|
|
618
623
|
const index = lastBlock.index;
|
|
619
624
|
await this.resolveBlock(lastBlock.hash);
|
|
620
|
-
let blocksSynced = localIndex > 0 ? localIndex > index ? localIndex - index : index - localIndex : index;
|
|
625
|
+
let blocksSynced = localIndex > 0 ? (localIndex > index ? localIndex - index : index - localIndex) : index;
|
|
621
626
|
debug(`synced ${blocksSynced} ${blocksSynced > 1 ? 'blocks' : 'block'}`);
|
|
622
627
|
|
|
623
628
|
this.#blocks.length;
|
|
624
|
-
|
|
625
|
-
await this.#loadBlocks(this
|
|
626
|
-
this.#
|
|
627
|
-
|
|
628
|
-
await blockStore.put(await message.hash, message.encoded);
|
|
629
|
-
await chainStore.put('lastBlock', this.lastBlock.hash);
|
|
629
|
+
const start = this.#blocks.length - blocksSynced;
|
|
630
|
+
await this.#loadBlocks(this.blocks.slice(start));
|
|
631
|
+
await this.#updateState(this.#blocks[this.#blocks.length - 1]);
|
|
632
|
+
this.#chainSyncing = false;
|
|
630
633
|
}
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
async #peerConnected(peer) {
|
|
637
|
+
let node = await new peernet.protos['peernet-request']({request: 'lastBlock'});
|
|
638
|
+
node = await peernet.prepareMessage(node);
|
|
639
|
+
let response = await peer.request(node.encoded);
|
|
640
|
+
response = await new globalThis.peernet.protos['peernet-response'](response);
|
|
641
|
+
let lastBlock = response.decoded.response;
|
|
642
|
+
this.#syncChain(lastBlock);
|
|
631
643
|
}
|
|
632
644
|
|
|
633
645
|
#epochTimeout
|
|
@@ -637,9 +649,9 @@ class Chain {
|
|
|
637
649
|
transaction = await new TransactionMessage(transaction);
|
|
638
650
|
const has = await transactionPoolStore.has(await transaction.hash);
|
|
639
651
|
if (!has) await transactionPoolStore.put(await transaction.hash, transaction.encoded);
|
|
640
|
-
if (this
|
|
641
|
-
} catch
|
|
642
|
-
throw Error('invalid transaction')
|
|
652
|
+
if (this.#participating && !this.#runningEpoch) this.#runEpoch();
|
|
653
|
+
} catch {
|
|
654
|
+
throw new Error('invalid transaction')
|
|
643
655
|
}
|
|
644
656
|
}
|
|
645
657
|
|
|
@@ -652,11 +664,11 @@ async resolveBlock(hash) {
|
|
|
652
664
|
let block = await peernet.get(hash, 'block');
|
|
653
665
|
block = await new BlockMessage(block);
|
|
654
666
|
if (!await peernet.has(hash, 'block')) await peernet.put(hash, block.encoded, 'block');
|
|
655
|
-
const size = block.encoded.length
|
|
667
|
+
const size = block.encoded.length > 0 ? block.encoded.length : block.encoded.byteLength;
|
|
656
668
|
block = {...block.decoded, hash};
|
|
657
|
-
if (this.#blocks[block.index]) throw `invalid block ${hash} @${block.index}`
|
|
669
|
+
if (this.#blocks[block.index] && this.#blocks[block.index].hash !== block.hash) throw `invalid block ${hash} @${block.index}`
|
|
658
670
|
this.#blocks[block.index] = block;
|
|
659
|
-
console.log(`
|
|
671
|
+
console.log(`resolved block: ${hash} @${block.index} ${formatBytes(size)}`);
|
|
660
672
|
if (block.previousHash !== '0x0') {
|
|
661
673
|
return this.resolveBlock(block.previousHash)
|
|
662
674
|
}
|
|
@@ -670,8 +682,8 @@ async resolveBlock(hash) {
|
|
|
670
682
|
if (hash && hash !== '0x0')
|
|
671
683
|
await this.resolveBlock(hash);
|
|
672
684
|
this.#lastBlock = this.#blocks[this.#blocks.length - 1];
|
|
673
|
-
|
|
674
|
-
} catch
|
|
685
|
+
|
|
686
|
+
} catch {
|
|
675
687
|
await chainStore.put('lastBlock', new TextEncoder().encode('0x0'));
|
|
676
688
|
return this.resolveBlocks()
|
|
677
689
|
// console.log(e);
|
|
@@ -685,11 +697,12 @@ async resolveBlock(hash) {
|
|
|
685
697
|
try {
|
|
686
698
|
await this.#machine.execute(transaction.to, transaction.method, transaction.params);
|
|
687
699
|
|
|
688
|
-
} catch (
|
|
689
|
-
console.log(
|
|
700
|
+
} catch (error) {
|
|
701
|
+
console.log(error);
|
|
690
702
|
}
|
|
691
703
|
}
|
|
692
|
-
block.loaded = true;
|
|
704
|
+
this.#blocks[block.index].loaded = true;
|
|
705
|
+
console.log(`loaded block: ${block.hash} @${block.index}`);
|
|
693
706
|
// let message = await peernet.get(block.hash, 'block')
|
|
694
707
|
|
|
695
708
|
// const compressed = pako.deflate(message);
|
|
@@ -717,10 +730,10 @@ async resolveBlock(hash) {
|
|
|
717
730
|
let result = await this.#machine.execute(to, method, params, from, nonce);
|
|
718
731
|
// if (!result) result = this.#machine.state
|
|
719
732
|
pubsub.publish(`transaction.completed.${hash}`, {status: 'fulfilled', hash});
|
|
720
|
-
return result
|
|
721
|
-
} catch (
|
|
722
|
-
pubsub.publish(`transaction.completed.${hash}`, {status: 'fail', hash, error:
|
|
723
|
-
throw
|
|
733
|
+
return result || 'no state change'
|
|
734
|
+
} catch (error) {
|
|
735
|
+
pubsub.publish(`transaction.completed.${hash}`, {status: 'fail', hash, error: error});
|
|
736
|
+
throw error
|
|
724
737
|
}
|
|
725
738
|
}
|
|
726
739
|
|
|
@@ -741,8 +754,6 @@ async resolveBlock(hash) {
|
|
|
741
754
|
// transaction = new TransactionMessage(transaction)
|
|
742
755
|
// return transaction
|
|
743
756
|
// }
|
|
744
|
-
|
|
745
|
-
console.log(blockMessage);
|
|
746
757
|
await Promise.all(blockMessage.decoded.transactions
|
|
747
758
|
.map(async transaction => transactionPoolStore.delete(await transaction.hash)));
|
|
748
759
|
const hash = await blockMessage.hash;
|
|
@@ -759,11 +770,15 @@ async resolveBlock(hash) {
|
|
|
759
770
|
// await transactionStore.put(transaction.hash, transaction.encoded)
|
|
760
771
|
const index = contracts.indexOf(transaction.to);
|
|
761
772
|
if (index === -1) contracts.push(transaction.to);
|
|
773
|
+
// Todo: go trough all accounts
|
|
762
774
|
promises.push(this.#executeTransaction(transaction));
|
|
775
|
+
|
|
763
776
|
}
|
|
764
777
|
try {
|
|
765
778
|
promises = await Promise.allSettled(promises);
|
|
766
779
|
for (let transaction of blockMessage.decoded.transactions) {
|
|
780
|
+
pubsub.publish('transaction-processed', transaction);
|
|
781
|
+
if (transaction.to === peernet.selectedAccount) pubsub.publish('account-transaction-processed', transaction);
|
|
767
782
|
await accountsStore.put(transaction.from, String(transaction.nonce));
|
|
768
783
|
}
|
|
769
784
|
|
|
@@ -776,8 +791,9 @@ async resolveBlock(hash) {
|
|
|
776
791
|
|
|
777
792
|
|
|
778
793
|
pubsub.publish('block-processed', blockMessage.decoded);
|
|
779
|
-
|
|
780
|
-
|
|
794
|
+
|
|
795
|
+
} catch (error) {
|
|
796
|
+
console.log({e: error});
|
|
781
797
|
}
|
|
782
798
|
|
|
783
799
|
}
|
|
@@ -797,7 +813,7 @@ async resolveBlock(hash) {
|
|
|
797
813
|
// introduce peer-reputation
|
|
798
814
|
// peerReputation(peerId)
|
|
799
815
|
// {bandwith: {up, down}, uptime}
|
|
800
|
-
this
|
|
816
|
+
this.#participating = true;
|
|
801
817
|
if (!await this.staticCall(addresses.validators, 'has', [address])) await this.createTransactionFrom(address, addresses.validators, 'addValidator', [address]);
|
|
802
818
|
if (await this.hasTransactionToHandle() && !this.#runningEpoch) await this.#runEpoch();
|
|
803
819
|
|
|
@@ -859,7 +875,7 @@ async resolveBlock(hash) {
|
|
|
859
875
|
block.transactions.push(transaction);
|
|
860
876
|
block.fees += Number(calculateFee(transaction));
|
|
861
877
|
await accountsStore.put(transaction.from, new TextEncoder().encode(String(transaction.nonce)));
|
|
862
|
-
} catch
|
|
878
|
+
} catch {
|
|
863
879
|
transaction = await new TransactionMessage(transaction);
|
|
864
880
|
await transactionPoolStore.delete(await transaction.hash);
|
|
865
881
|
}
|
|
@@ -892,9 +908,7 @@ async resolveBlock(hash) {
|
|
|
892
908
|
address: validator,
|
|
893
909
|
bw: bw.up + bw.down
|
|
894
910
|
});
|
|
895
|
-
} catch
|
|
896
|
-
|
|
897
|
-
}
|
|
911
|
+
} catch{}
|
|
898
912
|
|
|
899
913
|
} else if (peernet.selectedAccount === validator) {
|
|
900
914
|
block.validators.push({
|
|
@@ -922,17 +936,17 @@ async resolveBlock(hash) {
|
|
|
922
936
|
else block.index += 1;
|
|
923
937
|
|
|
924
938
|
block.previousHash = this.lastBlock?.hash || '0x0';
|
|
925
|
-
block.timestamp =
|
|
939
|
+
block.timestamp = Date.now();
|
|
926
940
|
|
|
927
941
|
const parts = String(block.fees).split('.');
|
|
928
942
|
let decimals = 0;
|
|
929
943
|
if (parts[1]) {
|
|
930
944
|
const potentional = parts[1].split('e');
|
|
931
|
-
if (potentional[0]
|
|
932
|
-
parts[1] = potentional[0];
|
|
933
|
-
decimals = Number(potentional[1]?.replace(/\-|\+/g, '')) + Number(potentional[0].length);
|
|
934
|
-
} else {
|
|
945
|
+
if (potentional[0] === parts[1]) {
|
|
935
946
|
decimals = parts[1].length;
|
|
947
|
+
} else {
|
|
948
|
+
parts[1] = potentional[0];
|
|
949
|
+
decimals = Number(potentional[1]?.replace(/[+-]/g, '')) + Number(potentional[0].length);
|
|
936
950
|
}
|
|
937
951
|
|
|
938
952
|
}
|
|
@@ -952,9 +966,10 @@ async resolveBlock(hash) {
|
|
|
952
966
|
debug(`created block: ${hash}`);
|
|
953
967
|
|
|
954
968
|
peernet.publish('add-block', blockMessage.encoded);
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
969
|
+
pubsub.publish('add-block', blockMessage.decoded);
|
|
970
|
+
} catch (error) {
|
|
971
|
+
console.log(error);
|
|
972
|
+
throw new Error(`invalid block ${block}`)
|
|
958
973
|
}
|
|
959
974
|
// data = await this.#machine.execute(to, method, params)
|
|
960
975
|
// transactionStore.put(message.hash, message.encoded)
|
|
@@ -1023,8 +1038,8 @@ async resolveBlock(hash) {
|
|
|
1023
1038
|
* @param {Array} params - array of paramters to apply to the contract method
|
|
1024
1039
|
* @param {Number} nonce - total transaction count [optional]
|
|
1025
1040
|
*/
|
|
1026
|
-
async createTransaction(to, method,
|
|
1027
|
-
return this.createTransactionFrom(peernet.selectedAccount, to, method,
|
|
1041
|
+
async createTransaction(to, method, parameters, nonce, signature) {
|
|
1042
|
+
return this.createTransactionFrom(peernet.selectedAccount, to, method, parameters, nonce)
|
|
1028
1043
|
}
|
|
1029
1044
|
|
|
1030
1045
|
|
|
@@ -1084,8 +1099,8 @@ async #signTransaction (transaction, wallet) {
|
|
|
1084
1099
|
} else {
|
|
1085
1100
|
let nonce = await accountsStore.get(transaction.from);
|
|
1086
1101
|
nonce = new TextDecoder().decode(nonce);
|
|
1087
|
-
if (transaction.nonce < nonce) throw Error(`a transaction with a higher nonce already exists`)
|
|
1088
|
-
if (transaction.nonce === nonce) throw Error(`a transaction with the same nonce already exists`)
|
|
1102
|
+
if (transaction.nonce < nonce) throw new Error(`a transaction with a higher nonce already exists`)
|
|
1103
|
+
if (transaction.nonce === nonce) throw new Error(`a transaction with the same nonce already exists`)
|
|
1089
1104
|
}
|
|
1090
1105
|
return transaction
|
|
1091
1106
|
}
|
|
@@ -1100,10 +1115,10 @@ async #signTransaction (transaction, wallet) {
|
|
|
1100
1115
|
* @param {Array} params - array of paramters to apply to the contract method
|
|
1101
1116
|
* @param {Number} nonce - total transaction count [optional]
|
|
1102
1117
|
*/
|
|
1103
|
-
async createTransactionFrom(from, to, method,
|
|
1118
|
+
async createTransactionFrom(from, to, method, parameters, nonce) {
|
|
1104
1119
|
try {
|
|
1105
1120
|
|
|
1106
|
-
const rawTransaction = await this.createRawTransaction({from, to, nonce, method, params});
|
|
1121
|
+
const rawTransaction = await this.createRawTransaction({from, to, nonce, method, params: parameters});
|
|
1107
1122
|
const transaction = await this.signTransaction(rawTransaction, from);
|
|
1108
1123
|
const message = await new TransactionMessage(transaction);
|
|
1109
1124
|
|
|
@@ -1119,7 +1134,7 @@ async #signTransaction (transaction, wallet) {
|
|
|
1119
1134
|
|
|
1120
1135
|
setTimeout(async () => {
|
|
1121
1136
|
pubsub.unsubscribe(`transaction.completed.${await message.hash}`, completed);
|
|
1122
|
-
},
|
|
1137
|
+
}, 10_000);
|
|
1123
1138
|
};
|
|
1124
1139
|
pubsub.subscribe(`transaction.completed.${await message.hash}`, completed);
|
|
1125
1140
|
}
|
|
@@ -1131,9 +1146,9 @@ async #signTransaction (transaction, wallet) {
|
|
|
1131
1146
|
peernet.publish('add-transaction', message.encoded);
|
|
1132
1147
|
this.#addTransaction(message.encoded);
|
|
1133
1148
|
return {hash: await message.hash, data, fee: await calculateFee(message.decoded), wait}
|
|
1134
|
-
} catch (
|
|
1135
|
-
console.log(
|
|
1136
|
-
throw
|
|
1149
|
+
} catch (error) {
|
|
1150
|
+
console.log(error);
|
|
1151
|
+
throw error
|
|
1137
1152
|
}
|
|
1138
1153
|
|
|
1139
1154
|
}
|
|
@@ -1151,15 +1166,15 @@ async #signTransaction (transaction, wallet) {
|
|
|
1151
1166
|
*
|
|
1152
1167
|
* @param {String} contract - a contract string (see plugins/deployContract)
|
|
1153
1168
|
*/
|
|
1154
|
-
async deployContract(contract,
|
|
1169
|
+
async deployContract(contract, parameters = []) {
|
|
1155
1170
|
globalThis.msg = {sender: peernet.selectedAccount, call: this.call};
|
|
1156
1171
|
|
|
1157
|
-
const hash = await this.createContractAddress(creator, contract,
|
|
1172
|
+
const hash = await this.createContractAddress(creator, contract, parameters);
|
|
1158
1173
|
console.log(hash);
|
|
1159
1174
|
try {
|
|
1160
1175
|
const tx = await this.createTransactionFrom(peernet.selectedAccount, addresses.contractFactory, 'deployContract', [hash, creator, contract, constructorParameters]);
|
|
1161
|
-
} catch (
|
|
1162
|
-
throw
|
|
1176
|
+
} catch (error) {
|
|
1177
|
+
throw error
|
|
1163
1178
|
}
|
|
1164
1179
|
return this.#machine.addContract(message)
|
|
1165
1180
|
}
|
|
@@ -1174,33 +1189,33 @@ console.log(hash);
|
|
|
1174
1189
|
}
|
|
1175
1190
|
}
|
|
1176
1191
|
|
|
1177
|
-
internalCall(sender, contract, method,
|
|
1192
|
+
internalCall(sender, contract, method, parameters) {
|
|
1178
1193
|
globalThis.msg = this.#createMessage(sender);
|
|
1179
1194
|
|
|
1180
|
-
return this.#machine.execute(contract, method,
|
|
1195
|
+
return this.#machine.execute(contract, method, parameters)
|
|
1181
1196
|
}
|
|
1182
1197
|
|
|
1183
|
-
call(contract, method,
|
|
1198
|
+
call(contract, method, parameters) {
|
|
1184
1199
|
globalThis.msg = this.#createMessage();
|
|
1185
1200
|
|
|
1186
|
-
return this.#machine.execute(contract, method,
|
|
1201
|
+
return this.#machine.execute(contract, method, parameters)
|
|
1187
1202
|
}
|
|
1188
1203
|
|
|
1189
|
-
staticCall(contract, method,
|
|
1204
|
+
staticCall(contract, method, parameters) {
|
|
1190
1205
|
globalThis.msg = this.#createMessage();
|
|
1191
|
-
return this.#machine.get(contract, method,
|
|
1206
|
+
return this.#machine.get(contract, method, parameters)
|
|
1192
1207
|
}
|
|
1193
1208
|
|
|
1194
|
-
delegate(contract, method,
|
|
1209
|
+
delegate(contract, method, parameters) {
|
|
1195
1210
|
globalThis.msg = this.#createMessage();
|
|
1196
1211
|
|
|
1197
|
-
return this.#machine.execute(contract, method,
|
|
1212
|
+
return this.#machine.execute(contract, method, parameters)
|
|
1198
1213
|
}
|
|
1199
1214
|
|
|
1200
|
-
staticDelegate(contract, method,
|
|
1215
|
+
staticDelegate(contract, method, parameters) {
|
|
1201
1216
|
globalThis.msg = this.#createMessage();
|
|
1202
1217
|
|
|
1203
|
-
return this.#machine.get(contract, method,
|
|
1218
|
+
return this.#machine.get(contract, method, parameters)
|
|
1204
1219
|
}
|
|
1205
1220
|
|
|
1206
1221
|
mint(to, amount) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
class Factory{#name="ArtOnlineContractFactory";#totalContracts=0;#contracts=[];constructor(state){state&&(this.#contracts=state.contracts,this.#totalContracts=state.totalContracts)}get state(){return{totalContracts:this.#totalContracts,contracts:this.#contracts}}get name(){return this.#name}get contracts(){return[...this.#contracts]}get totalContracts(){return this.#totalContracts}
|
|
1
|
+
class Factory{#name="ArtOnlineContractFactory";#totalContracts=0;#contracts=[];#implementations={};constructor(state){state&&(this.#contracts=state.contracts,this.#totalContracts=state.totalContracts,this.#implementations=state.implementations)}get state(){return{totalContracts:this.#totalContracts,contracts:this.#contracts,implementations:this.#implementations}}get name(){return this.#name}get contracts(){return[...this.#contracts]}get totalContracts(){return this.#totalContracts}get implementations(){return{...this.#implementations}}async registerContract(address){let isAllowed=!1;if(isAllowed=await msg.staticCall(address,"hasRole",[msg.sender,"IMPLEMENTATION_MANAGER"]),!isAllowed)throw new Error("only the implementation manager can update");if(this.#implementations[address])throw new Error("already registered");this.#totalContracts+=1,this.#implementations[address]=[],this.#implementations[address].push(address),this.#contracts.push(address)}async updateImplementation(address,newAddress){let isAllowed=!1;if(isAllowed=await msg.staticCall(address,"hasRole",[msg.sender,"IMPLEMENTATION_MANAGER"]),!isAllowed)throw new Error("only the implementation manager can update");if(!this.#implementations[address])throw new Error(`register ${address} before updating to ${newAddress}`);this.#implementations[address].push(newAddress)}getImplementations(address){return this.#implementations[address]}getImplementation(address,index){return index=index||this.#implementations[address].length-1,this.#implementations[address][index]}}export{Factory as default};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
class NameService{#name="ArtOnlineNameService";#owner;#price=0;#registry={};#currency;get name(){return this.#name}get registry(){return{...this.#registry}}get state(){}constructor(factoryAddress,currency,validatorAddress,price,state){state?(this.#owner=state.owner,this.#registry=state.registry,this.#currency=state.currency,this.#price=state.price):(this.#owner=msg.sender,this.#price=price,this.#registry.ArtOnlineContractFactory={owner:msg.sender,address:factoryAddress},this.#registry.ArtOnlineToken={owner:msg.sender,address:currency},this.#registry.ArtOnlineValidators={owner:msg.sender,address:validatorAddress},this.#currency=currency)}changeOwner(owner){if(msg.sender!==this.#owner)throw new Error("no owner");this.#owner=owner}changePrice(price){if(msg.sender!==this.#owner)throw new Error("no owner");this.#price=price}changeCurrency(currency){if(msg.sender!==this.#owner)throw new Error("no owner");this.#currency=currency}async purchaseName(name,address){if(await msg.call(this.#currency,"balanceOf",[msg.sender])<this.#price)throw new Error("price exceeds balance");try{await msg.call(this.#currency,"transfer",[msg.sender,this.#owner,this.#price])}catch(
|
|
1
|
+
class NameService{#name="ArtOnlineNameService";#owner;#price=0;#registry={};#currency;get name(){return this.#name}get registry(){return{...this.#registry}}get state(){}constructor(factoryAddress,currency,validatorAddress,price,state){state?(this.#owner=state.owner,this.#registry=state.registry,this.#currency=state.currency,this.#price=state.price):(this.#owner=msg.sender,this.#price=price,this.#registry.ArtOnlineContractFactory={owner:msg.sender,address:factoryAddress},this.#registry.ArtOnlineToken={owner:msg.sender,address:currency},this.#registry.ArtOnlineValidators={owner:msg.sender,address:validatorAddress},this.#currency=currency)}changeOwner(owner){if(msg.sender!==this.#owner)throw new Error("no owner");this.#owner=owner}changePrice(price){if(msg.sender!==this.#owner)throw new Error("no owner");this.#price=price}changeCurrency(currency){if(msg.sender!==this.#owner)throw new Error("no owner");this.#currency=currency}async purchaseName(name,address){if(await msg.call(this.#currency,"balanceOf",[msg.sender])<this.#price)throw new Error("price exceeds balance");try{await msg.call(this.#currency,"transfer",[msg.sender,this.#owner,this.#price])}catch(error){throw error}this.#registry[name]={owner:msg.sender,address}}lookup(name){return this.#registry[name]}transferOwnership(name,to){if(msg.sender!==this.#registry.owner)throw new Error("not a owner");this.#registry[name].owner=to}changeAddress(name,address){if(msg.sender!==this.#registry.owner)throw new Error("not a owner");this.#registry[name].address=address}}export{NameService as default};
|
|
@@ -0,0 +1 @@
|
|
|
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 Token extends Roles{#name;#symbol;#holders=0;#balances={};#approvals={};#decimals=18;#totalSupply=BigNumber.from(0);constructor(name,symbol,decimals=18,state){if(!name)throw new Error("name undefined");if(!symbol)throw new Error("symbol undefined");super(state?.roles),this.#name=name,this.#symbol=symbol,this.#decimals=decimals}get state(){return{...super.state,holders:this.holders,balances:this.balances,approvals:{...this.#approvals},totalSupply:this.totalSupply}}get totalSupply(){return this.#totalSupply}get name(){return this.#name}get symbol(){return this.#symbol}get holders(){return this.#holders}get balances(){return{...this.#balances}}mint(to,amount){if(!this.hasRole(msg.sender,"MINT"))throw new Error("not allowed");this.#totalSupply=this.#totalSupply.add(amount),this.#increaseBalance(to,amount)}burn(to,amount){if(!this.hasRole(msg.sender,"BURN"))throw new Error("not allowed");this.#totalSupply=this.#totalSupply.sub(amount),this.#decreaseBalance(to,amount)}#beforeTransfer(from,to,amount){if(!this.#balances[from]||this.#balances[from]<amount)throw new Error("amount exceeds balance")}#updateHolders(address,previousBalance){"0x00"===this.#balances[address].toHexString()?this.#holders-=1:"0x00"!==this.#balances[address].toHexString()&&"0x00"===previousBalance.toHexString()&&(this.#holders+=1)}#increaseBalance(address,amount){this.#balances[address]||(this.#balances[address]=BigNumber.from(0));const previousBalance=this.#balances[address];this.#balances[address]=this.#balances[address].add(amount),this.#updateHolders(address,previousBalance)}#decreaseBalance(address,amount){const previousBalance=this.#balances[address];this.#balances[address]=this.#balances[address].sub(amount),this.#updateHolders(address,previousBalance)}balanceOf(address){return this.#balances[address]}setApproval(operator,amount){const owner=globalThis.msg.sender;this.#approvals[owner]||(this.#approvals[owner]={}),this.#approvals[owner][operator]=amount}approved(owner,operator,amount){return this.#approvals[owner][operator]===amount}transfer(from,to,amount){amount=BigNumber.from(amount),this.#beforeTransfer(from,to,amount),this.#decreaseBalance(from,amount),this.#increaseBalance(to,amount)}}class ArtOnline extends Token{constructor(state){super("ArtOnline","ART",18,state)}}export{ArtOnline as default};
|