@leofcoin/peernet 0.8.5 → 0.8.9

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.
@@ -89,15 +89,16 @@ globalThis.pubsub = globalThis.pubsub || new PubSub__default['default']({verbose
89
89
  class PeernetClient {
90
90
  constructor(options = {}) {
91
91
  if (!options.id) options.id = Buffer.from('00000000000000000000000000000000');
92
-
92
+ if (!options.networkVersion) options.networkVersion = 'v0.1.0';
93
+ if (!options.networkName) options.networkName = 'peernet';
93
94
  this.id = options.id;
94
95
 
95
- this.topic = Buffer.from(sha256__default['default']('peernet-v0.1.0').toString());
96
+ this.topic = Buffer.from(sha256__default['default'](`${option.networkName}-${options.networkVersion}`).toString());
96
97
 
97
98
  const trackers = [
98
99
  'wss://star.leofcoin.org:7575',
99
100
  'wss://tracker.openwebtorrent.com',
100
- 'wss://tracker.sloppyta.co:443/announce',
101
+ // 'wss://tracker.sloppyta.co:443/announce',
101
102
  ];
102
103
  this.p2p = new P2P__default['default'](trackers, this.topic.slice(0, 20));
103
104
  this.p2p.on('peerconnect', (peer) => {
@@ -107,77 +108,13 @@ class PeernetClient {
107
108
  });
108
109
 
109
110
  this.p2p.on('peerclose', (peer) => {
111
+ // TODO: close peernetPeer
110
112
  connections.delete(peer.id);
111
113
  pubsub.publish('peer:disconnected', peer);
112
114
  });
113
115
 
114
116
  this.p2p.start();
115
117
 
116
-
117
- // this.sw.join(this.topic.slice(0, 32))
118
- //
119
- // const arrayOfPeers = this.sw.getPeers()
120
- //
121
- // this.sw.on('connection', async (connection, info) => {
122
- // // connected
123
- // const id = info.id.toString()
124
- // if (id === this.id.toString()) return
125
- //
126
- // const channel = connection.channelName
127
- // let channels = [channel]
128
- // let peer
129
- // if (connections.has(id)) {
130
- // const value = connections.get(id)
131
- // const _channels = value.channels
132
- // channels = [...channels, ..._channels]
133
- // peer = value.peer
134
- // } else {
135
- // peer = new PeernetPeer(id, connection)
136
- // pubsub.publish('peer:connected', peer)
137
- // }
138
- // connections.set(id, {channels, peer})
139
- // // connection.on('data', (data) => console.log({data}))
140
- // // connection.write('peerId')
141
- // });
142
- //
143
- // this.sw.on('candidates-updated', async (channel, candidates) => {
144
- // // TODO: Channels ...
145
- // for (const candidate of candidates) {
146
- // const id = candidate.toString()
147
- // let channels = [channel]
148
- // if (id === this.id.toString()) return
149
- //
150
- // if (!connections.has(id)) {
151
- // try {
152
- // const connection = await this.sw.connect(channel, candidate)
153
- // const peer = new PeernetPeer(id, connection)
154
- // connections.set(id, {channels, peer})
155
- // if (recentConnections.has(id)) {
156
- // setTimeout(() => {
157
- // pubsub.publish('peer:connected', peer)
158
- // }, 1000)
159
- // } else {
160
- // pubsub.publish('peer:connected', peer)
161
- // }
162
- // } catch (e) {
163
- // console.warn(e);
164
- // }
165
- // } else {
166
- // const value = connections.get(id)
167
- // const _channels = value.channels
168
- // channels = [...channels, ..._channels]
169
- // connections.set(id, {channels, peer: value.peer})
170
- // }
171
- // }
172
- // })
173
- //
174
- // this.sw.on('connection-closed', (connection, info) => {
175
- // if (!recentConnections.has(info.id.toString())) {
176
- // recentConnections.set(info.id.toString(), new Date().getTime())
177
- // }
178
- // if (connections.has(info.id.toString())) connections.delete(info.id.toString())
179
- // })
180
- //
181
118
  if (globalThis.process) {
182
119
  process.on('SIGINT', async () => {
183
120
  console.log('Caught interrupt signal');
@@ -327,7 +264,7 @@ class LeofcoinStorage$1 {
327
264
 
328
265
  }
329
266
 
330
- var version = "0.8.4";
267
+ var version = "0.8.9";
331
268
 
332
269
  var api$1 = {
333
270
  version: ({send}) => send({client: '@peernet/api/http', version}),
@@ -1435,605 +1372,605 @@ const nothingFoundError = (hash) => {
1435
1372
  return new Error(`nothing found for ${hash}`)
1436
1373
  };
1437
1374
 
1438
- globalThis.leofcoin = globalThis.leofcoin || {};
1439
- globalThis.globalSub = globalThis.globalSub || new PubSub__default['default']({verbose: true});
1440
-
1441
- /**
1442
- * @access public
1443
- * @example
1444
- * const peernet = new Peernet();
1445
- */
1446
- class Peernet {
1447
- /**
1448
- * @access public
1449
- * @param {Object} options
1450
- * @param {String} options.network - desired network
1451
- * @param {String} options.root - path to root directory
1452
- * @param {String} options.storePrefix - prefix for datatores (lfc)
1453
- *
1454
- * @return {Promise} instance of Peernet
1455
- *
1456
- * @example
1457
- * const peernet = new Peernet({network: 'leofcoin', root: '.leofcoin'});
1458
- */
1459
- constructor(options = {}) {
1460
- this._discovered = [];
1461
- /**
1462
- * @property {String} network - current network
1463
- */
1464
- this.network = options.network || 'leofcoin';
1465
- const parts = this.network.split(':');
1466
-
1467
- if (!options.storePrefix) options.storePrefix = 'lfc';
1468
- if (!options.port) options.port = 2000;
1469
- if (!options.root) {
1470
- if (parts[1]) options.root = `.${parts[0]}/peernet/${parts[1]}`;
1471
- else options.root = `.${this.network}/peernet`;
1472
- }
1473
- globalThis.peernet = this;
1474
- return this._init(options)
1475
- }
1476
-
1477
- get defaultStores() {
1478
- return ['account', 'wallet', 'block', 'transaction', 'chain', 'data']
1479
- }
1480
-
1481
- addProto(name, proto) {
1482
- if (!globalThis.peernet.protos[name]) globalThis.peernet.protos[name] = proto;
1483
- }
1484
-
1485
- addCodec(name, proto) {
1486
- if (!globalThis.peernet.codecs[name]) globalThis.peernet.codecs[name] = proto;
1487
- }
1488
-
1489
- async addStore(name, prefix, root, isPrivate = true) {
1490
- if (name === 'block' || name === 'transaction' || name === 'chain' ||
1491
- name === 'data') isPrivate = false;
1492
-
1493
- let Storage;
1494
- if (this.hasDaemon) {
1495
- Storage = LeofcoinStorageClient;
1496
- } else {
1497
- Storage = LeofcoinStorage$1;
1498
- }
1499
- globalThis[`${name}Store`] = globalThis[`${name}Store`] ||
1500
- await new Storage(`${prefix}-${name}`, root);
1501
-
1502
- globalThis[`${name}Store`].private = isPrivate;
1503
- if (!isPrivate) this.stores.push(name);
1504
- }
1505
-
1506
-
1507
- /**
1508
- * @see MessageHandler
1509
- */
1510
- prepareMessage(to, data) {
1511
- return this._messageHandler.prepareMessage(this.id, to, data)
1512
- }
1513
-
1514
- get peers() {
1515
- return [...connections.values()]
1516
- }
1517
-
1518
- /**
1519
- * @private
1520
- *
1521
- * @param {Object} options
1522
- * @param {String} options.root - path to root directory
1523
- *
1524
- * @return {Promise} instance of Peernet
1525
- */
1526
- async _init(options) {
1527
- // peernetDHT aka closesPeer by coordinates
1528
- /**
1529
- * @type {Object}
1530
- * @property {Object} peer Instance of Peer
1531
- */
1532
- this.dht = new DhtEarth();
1533
- this.peerMap = new Map();
1534
- this.stores = [];
1535
-
1536
- /**
1537
- * proto Object containing protos
1538
- * @type {Object}
1539
- * @property {PeernetMessage} protos[peernet-message] messageNode
1540
- * @property {DHTMessage} protos[peernet-dht] messageNode
1541
- * @property {DHTMessageResponse} protos[peernet-dht-response] messageNode
1542
- * @property {DataMessage} protos[peernet-data] messageNode
1543
- * @property {DataMessageResponse} protos[peernet-data-response] messageNode
1544
- */
1545
- globalThis.peernet.protos = {
1546
- 'peernet-request': request,
1547
- 'peernet-response': response,
1548
- 'peernet-peer': PeerMessage,
1549
- 'peernet-peer-response': PeerMessageResponse,
1550
- 'peernet-message': peernetMessage,
1551
- 'peernet-dht': dht,
1552
- 'peernet-dht-response': dhtResponse,
1553
- 'peernet-data': DataMessage,
1554
- 'peernet-data-response': DataMessageResponse,
1555
- 'peernet-ps': PsMessage,
1556
- };
1557
- this.protos = globalThis.peernet.protos;
1558
-
1559
- this._messageHandler = new MessageHandler(this.network);
1560
-
1561
-
1562
- const {daemon, environment} = await target();
1563
- this.hasDaemon = daemon;
1564
-
1565
- if (this.hasDaemon) {
1566
- globalThis.peernet.client = await httpClient({
1567
- protocol: 'peernet-v0.1.0', host: '127.0.0.1', port: options.port,
1568
- });
1569
- } else {
1570
- if (environment !== 'browser') http(options);
1571
- }
1572
-
1573
- for (const store of this.defaultStores) {
1574
- await this.addStore(store, options.storePrefix, options.root);
1575
- }
1576
-
1577
- try {
1578
- const pub = await accountStore.get('public');
1579
- this.id = pub.walletId;
1580
- } catch (e) {
1581
- if (e.code === 'ERR_NOT_FOUND') {
1582
- const wallet = {};
1583
- const {identity, accounts, config} = await generateAccount(this.network);
1584
- wallet.identity = identity;
1585
- wallet.accounts = accounts;
1586
- wallet.version = 1;
1587
- walletStore.put(wallet);
1588
- await accountStore.put('config', config);
1589
- await accountStore.put('public', {walletId: wallet.identity.walletId});
1590
-
1591
- this.id = wallet.identity.walletId;
1592
- } else {
1593
- throw e
1594
- }
1595
- }
1596
- this._peerHandler = new PeerDiscovery(this.id);
1597
- // peernet id
1598
- const id = Buffer.from(this.id.slice(0, 32));
1599
- this.peerId = id;
1600
-
1601
- pubsub.subscribe('peer:discovered', async (peer) => {
1602
- this._peerHandler.discover(peer);
1603
- peer.on('peernet.data', async (message) => {
1604
- const id = message.id;
1605
- message = new peernetMessage(Buffer.from(message.data.data));
1606
- const proto = protoFor(message.decoded.data);
1607
- await this._protoHandler({id, proto}, peer);
1608
- const fulldId = this._getPeerId(peer.id);
1609
- if (fulldId && this._discovered.indexOf(peer.id) === -1) {
1610
- this._discovered.push(peer.id);
1611
- pubsub.publish('peer:connected', peer);
1612
- }
1613
- });
1614
- });
1615
- pubsub.subscribe('peer:disconnected', async (peer) => {
1616
- let index = this._discovered.indexOf(peer.id);
1617
- if (index !== -1) this._discovered.splice(index, 1);
1618
- const id = this._getPeerId(peer.id);
1619
- let peerIds = this.peerMap.get(id);
1620
-
1621
- if (peerIds) {
1622
- index = peerIds.indexOf(peer.id);
1623
- if (index !== -1) peerIds.splice(index, 1);
1624
- } else {
1625
- peerIds = [];
1626
- }
1627
-
1628
- if (peerIds.length === 0) this.peerMap.delete(id);
1629
- else this.peerMap.set(id, peerIds);
1630
- });
1631
- pubsub.subscribe('peer:connected', async (peer) => {
1632
- console.log({connected: peer.id, as: this._getPeerId(peer.id) });
1633
- // peer.on('peernet.data', async (message) => {
1634
- // const id = message.id
1635
- // message = new PeernetMessage(Buffer.from(message.data.data))
1636
- // const proto = protoFor(message.decoded.data)
1637
- // this._protoHandler({id, proto}, peer)
1638
- // })
1639
- });
1640
-
1641
- /**
1642
- * @access public
1643
- * @type {PeernetClient}
1644
- */
1645
- this.client = new PeernetClient({...options, id});
1646
- return this
1647
- }
1648
-
1649
- _getPeerId(id) {
1650
- for (const entry of [...this.peerMap.entries()]) {
1651
- for (const _id of entry[1]) {
1652
- if (_id === id) return entry[0]
1653
- }
1654
- }
1655
- }
1656
-
1657
- /**
1658
- * @private
1659
- *
1660
- * @param {Buffer} message - peernet message
1661
- * @param {PeernetPeer} peer - peernet peer
1662
- */
1663
- async _protoHandler(message, peer) {
1664
- const {id, proto} = message;
1665
- if (proto.name === 'peernet-peer') {
1666
- const from = proto.decoded.id;
1667
- if (!this.peerMap.has(from)) this.peerMap.set(from, [peer.id]);
1668
- else {
1669
- const connections = this.peerMap.get(from);
1670
- if (connections.indexOf(peer.id) === -1) {
1671
- connections.push(peer.id);
1672
- this.peerMap.set(from, connections);
1673
- }
1674
- }
1675
- const data = new PeerMessageResponse({id: this.id});
1676
- const node = await this.prepareMessage(from, data.encoded);
1677
-
1678
- peer.write(Buffer.from(JSON.stringify({id, data: node.encoded})));
1679
- } else if (proto.name === 'peernet-peer-response') {
1680
- const from = proto.decoded.id;
1681
- if (!this.peerMap.has(from)) this.peerMap.set(from, [peer.id]);
1682
- else {
1683
- const connections = this.peerMap.get(from);
1684
- if (connections.indexOf(peer.id) === -1) {
1685
- connections.push(peer.id);
1686
- this.peerMap.set(from, connections);
1687
- }
1688
- }
1689
- } else {
1690
- let from = this._getPeerId(peer.id);
1691
- if (!from) {
1692
- const data = new PeerMessage({id: this.id});
1693
- const node = await this.prepareMessage(peer.id, data.encoded);
1694
-
1695
- let response = await peer.request(node.encoded);
1696
- response = protoFor(response);
1697
- response = new PeerMessageResponse(response.decoded.data);
1698
-
1699
- from = response.decoded.id;
1700
- if (!this.peerMap.has(from)) this.peerMap.set(from, [peer.id]);
1701
- else {
1702
- const connections = this.peerMap.get(from);
1703
- if (connections.indexOf(peer.id) === -1) {
1704
- connections.push(peer.id);
1705
- this.peerMap.set(from, connections);
1706
- }
1707
- }
1708
- }
1709
- if (proto.name === 'peernet-dht') {
1710
- let { hash, store } = proto.decoded;
1711
- let has;
1712
-
1713
- if (!store) {
1714
- has = await this.has(hash);
1715
- } else {
1716
- store = globalThis[`${store}Store`];
1717
- if (store.private) has = false;
1718
- else has = await store.has(hash);
1719
- }
1720
- const data = new dhtResponse({hash, has});
1721
- const node = await this.prepareMessage(from, data.encoded);
1722
-
1723
- peer.write(Buffer.from(JSON.stringify({id, data: node.encoded})));
1724
- } else if (proto.name === 'peernet-data') {
1725
- let { hash, store } = proto.decoded;
1726
- let data;
1727
-
1728
- if (!store) {
1729
- data = await this.get(hash);
1730
- } else {
1731
- store = globalThis[`${store}Store`];
1732
- if (store.private) {
1733
- // TODO: ban
1734
- return
1735
- } else data = await store.get(hash);
1736
- }
1737
-
1738
- if (data) {
1739
- data = new DataMessageResponse({hash, data: Buffer.from(data)});
1740
-
1741
- const node = await this.prepareMessage(from, data.encoded);
1742
- peer.write(Buffer.from(JSON.stringify({id, data: node.encoded})));
1743
- }
1744
- } else if (proto.name === 'peernet-peer') {
1745
- const from = proto.decoded.id;
1746
- if (!this.peerMap.has(from)) this.peerMap.set(from, [peer.id]);
1747
- else {
1748
- const connections = this.peerMap.get(from);
1749
- connections.push(peer.id);
1750
- this.peerMap.set(from, connections);
1751
- }
1752
- const data = new PeerMessage({id: this.id});
1753
- const node = await this.prepareMessage(from, data.encoded);
1754
-
1755
- peer.write(Buffer.from(JSON.stringify({id, data: node.encoded})));
1756
- } else if (proto.name === 'peernet-request') {
1757
- // TODO: make dynamic
1758
- // exposeddevapi[proto.decoded.request](proto.decoded.params)
1759
- let response$1;
1760
- if (proto.decoded.request === 'lastBlock') {
1761
- const height = await chainStore.get('localIndex');
1762
- const hash = await chainStore.get('localBlock');
1763
- response$1 = JSON.stringify({ height: height.toString(), hash: hash.toString() });
1764
- const data = new response({ response: response$1 });
1765
- const node = await this.prepareMessage(from, data.encoded);
1766
-
1767
- peer.write(Buffer.from(JSON.stringify({id, data: node.encoded})));
1768
- }
1769
- } else if (proto.name === 'peernet-ps' &&
1770
- this._getPeerId(peer.id) !== this.id.toString()) {
1771
- globalSub.publish(proto.decoded.topic.toString(), proto.decoded.data.toString());
1772
- }
1773
- }
1774
- }
1775
-
1776
- /**
1777
- * performs a walk and resolves first encounter
1778
- *
1779
- * @param {String} hash
1780
- */
1781
- async walk(hash) {
1782
- if (!hash) throw new Error('hash expected, received undefined')
1783
- const data = new dht({hash});
1784
- this.client.id;
1785
- for (const peer of this.peers) {
1786
- const node = await this.prepareMessage(peer.id, data.encoded);
1787
-
1788
- const result = await peer.request(node.encoded);
1789
-
1790
- let proto = protoFor(result.data);
1791
-
1792
- if (proto.name !== 'peernet-message') throw encapsulatedError()
1793
- const from = proto.decoded.from;
1794
- proto = protoFor(proto.decoded.data);
1795
-
1796
- if (proto.name !== 'peernet-dht-response') throw dhtError(proto.name)
1797
-
1798
- // TODO: give ip and port (just used for location)
1799
- if (!peer.connection.remoteAddress || !peer.connection.localAddress) {
1800
- peer.connection.remoteFamily = 'ipv4';
1801
- peer.connection.remoteAddress = '127.0.0.1';
1802
- peer.connection.remotePort = '0000';
1803
- }
1804
-
1805
- const peerInfo = {
1806
- family: peer.connection.remoteFamily || peer.connection.localFamily,
1807
- address: peer.connection.remoteAddress || peer.connection.localAddress,
1808
- port: peer.connection.remotePort || peer.connection.localPort,
1809
- id: from,
1810
- };
1811
-
1812
- if (proto.decoded.has) this.dht.addProvider(peerInfo, proto.decoded.hash);
1813
- }
1814
- return
1815
- }
1816
-
1817
- /**
1818
- * Override DHT behavior, try's finding the content three times
1819
- *
1820
- * @param {String} hash
1821
- */
1822
- async providersFor(hash) {
1823
- let providers = await this.dht.providersFor(hash);
1824
- // walk the network to find a provider
1825
- if (!providers || providers.length === 0) {
1826
- await this.walk(hash);
1827
- providers = await this.dht.providersFor(hash);
1828
- // second walk the network to find a provider
1829
- if (!providers || providers.length === 0) {
1830
- await this.walk(hash);
1831
- providers = await this.dht.providersFor(hash);
1832
- }
1833
- // last walk
1834
- if (!providers || providers.length === 0) {
1835
- await this.walk(hash);
1836
- providers = await this.dht.providersFor(hash);
1837
- }
1838
- }
1839
- // undefined if no providers given
1840
- return providers
1841
- }
1842
-
1843
- get block() {
1844
- return {
1845
- get: async (hash) => {
1846
- const data = await blockStore.has(hash);
1847
- if (data) return await blockStore.get(hash)
1848
- return this.requestData(hash)
1849
- },
1850
- put: async (hash, data) => {
1851
- if (await blockStore.has(hash)) return
1852
- return await blockStore.put(hash, data)
1853
- },
1854
- has: async (hash) => await blockStore.has(hash, 'block'),
1855
- }
1856
- }
1857
-
1858
- get transaction() {
1859
- return {
1860
- get: async (hash) => {
1861
- const data = await transactionStore.has(hash);
1862
- if (data) return await transactionStore.get(hash)
1863
- return this.requestData(hash, 'transaction')
1864
- },
1865
- put: async (hash, data) => {
1866
- if (await transactionStore.has(hash)) return
1867
- return await transactionStore.put(hash, data)
1868
- },
1869
- has: async (hash) => await transactionStore.has(hash),
1870
- }
1871
- }
1872
-
1873
- async requestData(hash, store) {
1874
- const providers = await this.providersFor(hash);
1875
- if (!providers || providers.size === 0) throw nothingFoundError(hash)
1876
- debug(`found ${providers.size} provider(s) for ${hash}`);
1877
- // get closest peer on earth
1878
- const closestPeer = await this.dht.closestPeer(providers);
1879
- // get peer instance by id
1880
- if (!closestPeer || !closestPeer.id) return this.requestData(hash, store)
1881
-
1882
- const id = closestPeer.id.toString();
1883
- if (this.peers) {
1884
- let closest = this.peers.filter((peer) => {
1885
- if (this._getPeerId(peer.id) === id) return peer
1886
- });
1887
-
1888
- let data = new DataMessage({hash, store});
1889
-
1890
- const node = await this.prepareMessage(id, data.encoded);
1891
- if (closest[0]) data = await closest[0].request(node.encoded);
1892
- else {
1893
- closest = this.peers.filter((peer) => {
1894
- if (peer.id.toString() === id) return peer
1895
- });
1896
- if (closest[0]) data = await closest[0].request(node.encoded);
1897
- }
1898
- if (data.data) {
1899
- let proto = protoFor(Buffer.from(data.data));
1900
- proto = protoFor(proto.decoded.data);
1901
- return proto.decoded.data
1902
- }
1903
-
1904
- // this.put(hash, proto.decoded.data)
1905
- }
1906
- return null
1907
- }
1908
-
1909
- get data() {
1910
- return {
1911
- /**
1912
- * Get content for given data hash
1913
- *
1914
- * @param {String} hash
1915
- */
1916
- get: async (hash) => {
1917
- debug(`get data ${hash}`);
1918
- const data = await dataStore.has(hash);
1919
- if (data) return await dataStore.get(hash)
1920
- return this.requestData(hash, 'data')
1921
- },
1922
- /**
1923
- * put data content
1924
- *
1925
- * @param {String} hash
1926
- * @param {Buffer} data
1927
- */
1928
- put: async (hash, data) => await dataStore.put(hash, data),
1929
- /**
1930
- * @param {String} hash
1931
- * @return {Boolean}
1932
- */
1933
- has: async (hash) => await dataStore.has(hash),
1934
- }
1935
- }
1936
-
1937
- /**
1938
- * goes trough given stores and tries to find data for given hash
1939
- * @param {Array} stores
1940
- * @param {string} hash
1941
- */
1942
- async whichStore(stores, hash) {
1943
- let store = stores.pop();
1944
- store = globalThis[`${store}Store`];
1945
- if (store) {
1946
- const has = await store.has(hash);
1947
- if (has) return store
1948
- if (stores.length > 0) return this.whichStore(stores, hash)
1949
- } else return null
1950
- }
1951
-
1952
- /**
1953
- * Get content for given hash
1954
- *
1955
- * @param {String} hash
1956
- */
1957
- async get(hash, store) {
1958
- debug(`get ${hash}`);
1959
- let data;
1960
- if (store) store = globalThis[`${store}Store`];
1961
- if (!store) store = await this.whichStore([...this.stores], hash);
1962
- if (store && await store.has(hash)) data = await store.get(hash);
1963
- if (data) return data
1964
-
1965
- return this.requestData(hash, 'data')
1966
- }
1967
-
1968
- /**
1969
- * put content
1970
- *
1971
- * @param {String} hash
1972
- * @param {Buffer} data
1973
- */
1974
- async put(hash, data, store = 'data') {
1975
- store = globalThis[`${store}Store`];
1976
- return await store.put(hash, data)
1977
- }
1978
-
1979
- /**
1980
- * @param {String} hash
1981
- * @return {Boolean}
1982
- */
1983
- async has(hash) {
1984
- const store = await this.whichStore([...this.stores], hash);
1985
- if (store) {
1986
- if (store.private) return false
1987
- else return true
1988
- }
1989
- return false
1990
- }
1991
-
1992
- /**
1993
- *
1994
- * @param {String} topic
1995
- * @param {String|Object|Array|Boolean|Buffer} data
1996
- */
1997
- async publish(topic, data) {
1998
- // globalSub.publish(topic, data)
1999
-
2000
-
2001
- if (!Buffer.isBuffer(topic)) topic = Buffer.from(topic);
2002
- if (!Buffer.isBuffer(data)) data = Buffer.from(data);
2003
- const id = Math.random().toString(36).slice(-12);
2004
- data = new PsMessage({data, topic});
2005
- for (const peer of this.peers) {
2006
- if (peer.connection._connected && peer.id.toString() !== this.peerId.toString()) {
2007
- const node = await this.prepareMessage(peer.id, data.encoded);
2008
- peer.write(Buffer.from(JSON.stringify({id, data: node.encoded})));
2009
- } else {
2010
- this.removePeer(peer);
2011
- }
2012
- // TODO: if peer subscribed
2013
- }
2014
- }
2015
-
2016
- /**
2017
- *
2018
- * @param {String} topic
2019
- * @param {Method} cb
2020
- */
2021
- async subscribe(topic, cb) {
2022
- // TODO: if peer subscribed
2023
- globalSub.subscribe(topic, cb);
2024
- }
2025
-
2026
- async removePeer(peer) {
2027
- connections.delete(peer.id);
2028
- }
2029
- // async block(index) {
2030
- // const _values = []
2031
- // for (const peer of this.peers) {
2032
- // const value = await peer.request({type: 'block', index})
2033
- // console.log(value);
2034
- // }
2035
- //
2036
- // }
1375
+ globalThis.leofcoin = globalThis.leofcoin || {};
1376
+ globalThis.globalSub = globalThis.globalSub || new PubSub__default['default']({verbose: true});
1377
+
1378
+ /**
1379
+ * @access public
1380
+ * @example
1381
+ * const peernet = new Peernet();
1382
+ */
1383
+ class Peernet {
1384
+ /**
1385
+ * @access public
1386
+ * @param {Object} options
1387
+ * @param {String} options.network - desired network
1388
+ * @param {String} options.root - path to root directory
1389
+ * @param {String} options.storePrefix - prefix for datatores (lfc)
1390
+ *
1391
+ * @return {Promise} instance of Peernet
1392
+ *
1393
+ * @example
1394
+ * const peernet = new Peernet({network: 'leofcoin', root: '.leofcoin'});
1395
+ */
1396
+ constructor(options = {}) {
1397
+ this._discovered = [];
1398
+ /**
1399
+ * @property {String} network - current network
1400
+ */
1401
+ this.network = options.network || 'leofcoin';
1402
+ const parts = this.network.split(':');
1403
+
1404
+ if (!options.storePrefix) options.storePrefix = 'lfc';
1405
+ if (!options.port) options.port = 2000;
1406
+ if (!options.root) {
1407
+ if (parts[1]) options.root = `.${parts[0]}/peernet/${parts[1]}`;
1408
+ else options.root = `.${this.network}/peernet`;
1409
+ }
1410
+ globalThis.peernet = this;
1411
+ return this._init(options)
1412
+ }
1413
+
1414
+ get defaultStores() {
1415
+ return ['account', 'wallet', 'block', 'transaction', 'chain', 'data']
1416
+ }
1417
+
1418
+ addProto(name, proto) {
1419
+ if (!globalThis.peernet.protos[name]) globalThis.peernet.protos[name] = proto;
1420
+ }
1421
+
1422
+ addCodec(name, proto) {
1423
+ if (!globalThis.peernet.codecs[name]) globalThis.peernet.codecs[name] = proto;
1424
+ }
1425
+
1426
+ async addStore(name, prefix, root, isPrivate = true) {
1427
+ if (name === 'block' || name === 'transaction' || name === 'chain' ||
1428
+ name === 'data') isPrivate = false;
1429
+
1430
+ let Storage;
1431
+ if (this.hasDaemon) {
1432
+ Storage = LeofcoinStorageClient;
1433
+ } else {
1434
+ Storage = LeofcoinStorage$1;
1435
+ }
1436
+ globalThis[`${name}Store`] = globalThis[`${name}Store`] ||
1437
+ await new Storage(`${prefix}-${name}`, root);
1438
+
1439
+ globalThis[`${name}Store`].private = isPrivate;
1440
+ if (!isPrivate) this.stores.push(name);
1441
+ }
1442
+
1443
+
1444
+ /**
1445
+ * @see MessageHandler
1446
+ */
1447
+ prepareMessage(to, data) {
1448
+ return this._messageHandler.prepareMessage(this.id, to, data)
1449
+ }
1450
+
1451
+ get peers() {
1452
+ return [...connections.values()]
1453
+ }
1454
+
1455
+ /**
1456
+ * @private
1457
+ *
1458
+ * @param {Object} options
1459
+ * @param {String} options.root - path to root directory
1460
+ *
1461
+ * @return {Promise} instance of Peernet
1462
+ */
1463
+ async _init(options) {
1464
+ // peernetDHT aka closesPeer by coordinates
1465
+ /**
1466
+ * @type {Object}
1467
+ * @property {Object} peer Instance of Peer
1468
+ */
1469
+ this.dht = new DhtEarth();
1470
+ this.peerMap = new Map();
1471
+ this.stores = [];
1472
+
1473
+ /**
1474
+ * proto Object containing protos
1475
+ * @type {Object}
1476
+ * @property {PeernetMessage} protos[peernet-message] messageNode
1477
+ * @property {DHTMessage} protos[peernet-dht] messageNode
1478
+ * @property {DHTMessageResponse} protos[peernet-dht-response] messageNode
1479
+ * @property {DataMessage} protos[peernet-data] messageNode
1480
+ * @property {DataMessageResponse} protos[peernet-data-response] messageNode
1481
+ */
1482
+ globalThis.peernet.protos = {
1483
+ 'peernet-request': request,
1484
+ 'peernet-response': response,
1485
+ 'peernet-peer': PeerMessage,
1486
+ 'peernet-peer-response': PeerMessageResponse,
1487
+ 'peernet-message': peernetMessage,
1488
+ 'peernet-dht': dht,
1489
+ 'peernet-dht-response': dhtResponse,
1490
+ 'peernet-data': DataMessage,
1491
+ 'peernet-data-response': DataMessageResponse,
1492
+ 'peernet-ps': PsMessage,
1493
+ };
1494
+ this.protos = globalThis.peernet.protos;
1495
+
1496
+ this._messageHandler = new MessageHandler(this.network);
1497
+
1498
+
1499
+ const {daemon, environment} = await target();
1500
+ this.hasDaemon = daemon;
1501
+
1502
+ if (this.hasDaemon) {
1503
+ globalThis.peernet.client = await httpClient({
1504
+ protocol: 'peernet-v0.1.0', host: '127.0.0.1', port: options.port,
1505
+ });
1506
+ } else {
1507
+ if (environment !== 'browser') http(options);
1508
+ }
1509
+
1510
+ for (const store of this.defaultStores) {
1511
+ await this.addStore(store, options.storePrefix, options.root);
1512
+ }
1513
+
1514
+ try {
1515
+ const pub = await accountStore.get('public');
1516
+ this.id = pub.walletId;
1517
+ } catch (e) {
1518
+ if (e.code === 'ERR_NOT_FOUND') {
1519
+ const wallet = {};
1520
+ const {identity, accounts, config} = await generateAccount(this.network);
1521
+ wallet.identity = identity;
1522
+ wallet.accounts = accounts;
1523
+ wallet.version = 1;
1524
+ walletStore.put(wallet);
1525
+ await accountStore.put('config', config);
1526
+ await accountStore.put('public', {walletId: wallet.identity.walletId});
1527
+
1528
+ this.id = wallet.identity.walletId;
1529
+ } else {
1530
+ throw e
1531
+ }
1532
+ }
1533
+ this._peerHandler = new PeerDiscovery(this.id);
1534
+ // peernet id
1535
+ const id = Buffer.from(this.id.slice(0, 32));
1536
+ this.peerId = id;
1537
+
1538
+ pubsub.subscribe('peer:discovered', async (peer) => {
1539
+ this._peerHandler.discover(peer);
1540
+ peer.on('peernet.data', async (message) => {
1541
+ const id = message.id;
1542
+ message = new peernetMessage(Buffer.from(message.data.data));
1543
+ const proto = protoFor(message.decoded.data);
1544
+ await this._protoHandler({id, proto}, peer);
1545
+ const fulldId = this._getPeerId(peer.id);
1546
+ if (fulldId && this._discovered.indexOf(peer.id) === -1) {
1547
+ this._discovered.push(peer.id);
1548
+ pubsub.publish('peer:connected', peer);
1549
+ }
1550
+ });
1551
+ });
1552
+ pubsub.subscribe('peer:disconnected', async (peer) => {
1553
+ let index = this._discovered.indexOf(peer.id);
1554
+ if (index !== -1) this._discovered.splice(index, 1);
1555
+ const id = this._getPeerId(peer.id);
1556
+ let peerIds = this.peerMap.get(id);
1557
+
1558
+ if (peerIds) {
1559
+ index = peerIds.indexOf(peer.id);
1560
+ if (index !== -1) peerIds.splice(index, 1);
1561
+ } else {
1562
+ peerIds = [];
1563
+ }
1564
+
1565
+ if (peerIds.length === 0) this.peerMap.delete(id);
1566
+ else this.peerMap.set(id, peerIds);
1567
+ });
1568
+ pubsub.subscribe('peer:connected', async (peer) => {
1569
+ console.log({connected: peer.id, as: this._getPeerId(peer.id) });
1570
+ // peer.on('peernet.data', async (message) => {
1571
+ // const id = message.id
1572
+ // message = new PeernetMessage(Buffer.from(message.data.data))
1573
+ // const proto = protoFor(message.decoded.data)
1574
+ // this._protoHandler({id, proto}, peer)
1575
+ // })
1576
+ });
1577
+
1578
+ /**
1579
+ * @access public
1580
+ * @type {PeernetClient}
1581
+ */
1582
+ this.client = new PeernetClient({...options, id});
1583
+ return this
1584
+ }
1585
+
1586
+ _getPeerId(id) {
1587
+ for (const entry of [...this.peerMap.entries()]) {
1588
+ for (const _id of entry[1]) {
1589
+ if (_id === id) return entry[0]
1590
+ }
1591
+ }
1592
+ }
1593
+
1594
+ /**
1595
+ * @private
1596
+ *
1597
+ * @param {Buffer} message - peernet message
1598
+ * @param {PeernetPeer} peer - peernet peer
1599
+ */
1600
+ async _protoHandler(message, peer) {
1601
+ const {id, proto} = message;
1602
+ if (proto.name === 'peernet-peer') {
1603
+ const from = proto.decoded.id;
1604
+ if (!this.peerMap.has(from)) this.peerMap.set(from, [peer.id]);
1605
+ else {
1606
+ const connections = this.peerMap.get(from);
1607
+ if (connections.indexOf(peer.id) === -1) {
1608
+ connections.push(peer.id);
1609
+ this.peerMap.set(from, connections);
1610
+ }
1611
+ }
1612
+ const data = new PeerMessageResponse({id: this.id});
1613
+ const node = await this.prepareMessage(from, data.encoded);
1614
+
1615
+ peer.write(Buffer.from(JSON.stringify({id, data: node.encoded})));
1616
+ } else if (proto.name === 'peernet-peer-response') {
1617
+ const from = proto.decoded.id;
1618
+ if (!this.peerMap.has(from)) this.peerMap.set(from, [peer.id]);
1619
+ else {
1620
+ const connections = this.peerMap.get(from);
1621
+ if (connections.indexOf(peer.id) === -1) {
1622
+ connections.push(peer.id);
1623
+ this.peerMap.set(from, connections);
1624
+ }
1625
+ }
1626
+ } else {
1627
+ let from = this._getPeerId(peer.id);
1628
+ if (!from) {
1629
+ const data = new PeerMessage({id: this.id});
1630
+ const node = await this.prepareMessage(peer.id, data.encoded);
1631
+
1632
+ let response = await peer.request(node.encoded);
1633
+ response = protoFor(response);
1634
+ response = new PeerMessageResponse(response.decoded.data);
1635
+
1636
+ from = response.decoded.id;
1637
+ if (!this.peerMap.has(from)) this.peerMap.set(from, [peer.id]);
1638
+ else {
1639
+ const connections = this.peerMap.get(from);
1640
+ if (connections.indexOf(peer.id) === -1) {
1641
+ connections.push(peer.id);
1642
+ this.peerMap.set(from, connections);
1643
+ }
1644
+ }
1645
+ }
1646
+ if (proto.name === 'peernet-dht') {
1647
+ let { hash, store } = proto.decoded;
1648
+ let has;
1649
+
1650
+ if (!store) {
1651
+ has = await this.has(hash);
1652
+ } else {
1653
+ store = globalThis[`${store}Store`];
1654
+ if (store.private) has = false;
1655
+ else has = await store.has(hash);
1656
+ }
1657
+ const data = new dhtResponse({hash, has});
1658
+ const node = await this.prepareMessage(from, data.encoded);
1659
+
1660
+ peer.write(Buffer.from(JSON.stringify({id, data: node.encoded})));
1661
+ } else if (proto.name === 'peernet-data') {
1662
+ let { hash, store } = proto.decoded;
1663
+ let data;
1664
+
1665
+ if (!store) {
1666
+ data = await this.get(hash);
1667
+ } else {
1668
+ store = globalThis[`${store}Store`];
1669
+ if (store.private) {
1670
+ // TODO: ban
1671
+ return
1672
+ } else data = await store.get(hash);
1673
+ }
1674
+
1675
+ if (data) {
1676
+ data = new DataMessageResponse({hash, data: Buffer.from(data)});
1677
+
1678
+ const node = await this.prepareMessage(from, data.encoded);
1679
+ peer.write(Buffer.from(JSON.stringify({id, data: node.encoded})));
1680
+ }
1681
+ } else if (proto.name === 'peernet-peer') {
1682
+ const from = proto.decoded.id;
1683
+ if (!this.peerMap.has(from)) this.peerMap.set(from, [peer.id]);
1684
+ else {
1685
+ const connections = this.peerMap.get(from);
1686
+ connections.push(peer.id);
1687
+ this.peerMap.set(from, connections);
1688
+ }
1689
+ const data = new PeerMessage({id: this.id});
1690
+ const node = await this.prepareMessage(from, data.encoded);
1691
+
1692
+ peer.write(Buffer.from(JSON.stringify({id, data: node.encoded})));
1693
+ } else if (proto.name === 'peernet-request') {
1694
+ // TODO: make dynamic
1695
+ // exposeddevapi[proto.decoded.request](proto.decoded.params)
1696
+ let response$1;
1697
+ if (proto.decoded.request === 'lastBlock') {
1698
+ const height = await chainStore.get('localIndex');
1699
+ const hash = await chainStore.get('localBlock');
1700
+ response$1 = JSON.stringify({ height: height.toString(), hash: hash.toString() });
1701
+ const data = new response({ response: response$1 });
1702
+ const node = await this.prepareMessage(from, data.encoded);
1703
+
1704
+ peer.write(Buffer.from(JSON.stringify({id, data: node.encoded})));
1705
+ }
1706
+ } else if (proto.name === 'peernet-ps' &&
1707
+ this._getPeerId(peer.id) !== this.id.toString()) {
1708
+ globalSub.publish(proto.decoded.topic.toString(), proto.decoded.data.toString());
1709
+ }
1710
+ }
1711
+ }
1712
+
1713
+ /**
1714
+ * performs a walk and resolves first encounter
1715
+ *
1716
+ * @param {String} hash
1717
+ */
1718
+ async walk(hash) {
1719
+ if (!hash) throw new Error('hash expected, received undefined')
1720
+ const data = new dht({hash});
1721
+ this.client.id;
1722
+ for (const peer of this.peers) {
1723
+ const node = await this.prepareMessage(peer.id, data.encoded);
1724
+
1725
+ const result = await peer.request(node.encoded);
1726
+
1727
+ let proto = protoFor(result.data);
1728
+
1729
+ if (proto.name !== 'peernet-message') throw encapsulatedError()
1730
+ const from = proto.decoded.from;
1731
+ proto = protoFor(proto.decoded.data);
1732
+
1733
+ if (proto.name !== 'peernet-dht-response') throw dhtError(proto.name)
1734
+
1735
+ // TODO: give ip and port (just used for location)
1736
+ if (!peer.connection.remoteAddress || !peer.connection.localAddress) {
1737
+ peer.connection.remoteFamily = 'ipv4';
1738
+ peer.connection.remoteAddress = '127.0.0.1';
1739
+ peer.connection.remotePort = '0000';
1740
+ }
1741
+
1742
+ const peerInfo = {
1743
+ family: peer.connection.remoteFamily || peer.connection.localFamily,
1744
+ address: peer.connection.remoteAddress || peer.connection.localAddress,
1745
+ port: peer.connection.remotePort || peer.connection.localPort,
1746
+ id: from,
1747
+ };
1748
+
1749
+ if (proto.decoded.has) this.dht.addProvider(peerInfo, proto.decoded.hash);
1750
+ }
1751
+ return
1752
+ }
1753
+
1754
+ /**
1755
+ * Override DHT behavior, try's finding the content three times
1756
+ *
1757
+ * @param {String} hash
1758
+ */
1759
+ async providersFor(hash) {
1760
+ let providers = await this.dht.providersFor(hash);
1761
+ // walk the network to find a provider
1762
+ if (!providers || providers.length === 0) {
1763
+ await this.walk(hash);
1764
+ providers = await this.dht.providersFor(hash);
1765
+ // second walk the network to find a provider
1766
+ if (!providers || providers.length === 0) {
1767
+ await this.walk(hash);
1768
+ providers = await this.dht.providersFor(hash);
1769
+ }
1770
+ // last walk
1771
+ if (!providers || providers.length === 0) {
1772
+ await this.walk(hash);
1773
+ providers = await this.dht.providersFor(hash);
1774
+ }
1775
+ }
1776
+ // undefined if no providers given
1777
+ return providers
1778
+ }
1779
+
1780
+ get block() {
1781
+ return {
1782
+ get: async (hash) => {
1783
+ const data = await blockStore.has(hash);
1784
+ if (data) return await blockStore.get(hash)
1785
+ return this.requestData(hash)
1786
+ },
1787
+ put: async (hash, data) => {
1788
+ if (await blockStore.has(hash)) return
1789
+ return await blockStore.put(hash, data)
1790
+ },
1791
+ has: async (hash) => await blockStore.has(hash, 'block'),
1792
+ }
1793
+ }
1794
+
1795
+ get transaction() {
1796
+ return {
1797
+ get: async (hash) => {
1798
+ const data = await transactionStore.has(hash);
1799
+ if (data) return await transactionStore.get(hash)
1800
+ return this.requestData(hash, 'transaction')
1801
+ },
1802
+ put: async (hash, data) => {
1803
+ if (await transactionStore.has(hash)) return
1804
+ return await transactionStore.put(hash, data)
1805
+ },
1806
+ has: async (hash) => await transactionStore.has(hash),
1807
+ }
1808
+ }
1809
+
1810
+ async requestData(hash, store) {
1811
+ const providers = await this.providersFor(hash);
1812
+ if (!providers || providers.size === 0) throw nothingFoundError(hash)
1813
+ debug(`found ${providers.size} provider(s) for ${hash}`);
1814
+ // get closest peer on earth
1815
+ const closestPeer = await this.dht.closestPeer(providers);
1816
+ // get peer instance by id
1817
+ if (!closestPeer || !closestPeer.id) return this.requestData(hash, store)
1818
+
1819
+ const id = closestPeer.id.toString();
1820
+ if (this.peers) {
1821
+ let closest = this.peers.filter((peer) => {
1822
+ if (this._getPeerId(peer.id) === id) return peer
1823
+ });
1824
+
1825
+ let data = new DataMessage({hash, store});
1826
+
1827
+ const node = await this.prepareMessage(id, data.encoded);
1828
+ if (closest[0]) data = await closest[0].request(node.encoded);
1829
+ else {
1830
+ closest = this.peers.filter((peer) => {
1831
+ if (peer.id.toString() === id) return peer
1832
+ });
1833
+ if (closest[0]) data = await closest[0].request(node.encoded);
1834
+ }
1835
+ if (data.data) {
1836
+ let proto = protoFor(Buffer.from(data.data));
1837
+ proto = protoFor(proto.decoded.data);
1838
+ return proto.decoded.data
1839
+ }
1840
+
1841
+ // this.put(hash, proto.decoded.data)
1842
+ }
1843
+ return null
1844
+ }
1845
+
1846
+ get data() {
1847
+ return {
1848
+ /**
1849
+ * Get content for given data hash
1850
+ *
1851
+ * @param {String} hash
1852
+ */
1853
+ get: async (hash) => {
1854
+ debug(`get data ${hash}`);
1855
+ const data = await dataStore.has(hash);
1856
+ if (data) return await dataStore.get(hash)
1857
+ return this.requestData(hash, 'data')
1858
+ },
1859
+ /**
1860
+ * put data content
1861
+ *
1862
+ * @param {String} hash
1863
+ * @param {Buffer} data
1864
+ */
1865
+ put: async (hash, data) => await dataStore.put(hash, data),
1866
+ /**
1867
+ * @param {String} hash
1868
+ * @return {Boolean}
1869
+ */
1870
+ has: async (hash) => await dataStore.has(hash),
1871
+ }
1872
+ }
1873
+
1874
+ /**
1875
+ * goes trough given stores and tries to find data for given hash
1876
+ * @param {Array} stores
1877
+ * @param {string} hash
1878
+ */
1879
+ async whichStore(stores, hash) {
1880
+ let store = stores.pop();
1881
+ store = globalThis[`${store}Store`];
1882
+ if (store) {
1883
+ const has = await store.has(hash);
1884
+ if (has) return store
1885
+ if (stores.length > 0) return this.whichStore(stores, hash)
1886
+ } else return null
1887
+ }
1888
+
1889
+ /**
1890
+ * Get content for given hash
1891
+ *
1892
+ * @param {String} hash
1893
+ */
1894
+ async get(hash, store) {
1895
+ debug(`get ${hash}`);
1896
+ let data;
1897
+ if (store) store = globalThis[`${store}Store`];
1898
+ if (!store) store = await this.whichStore([...this.stores], hash);
1899
+ if (store && await store.has(hash)) data = await store.get(hash);
1900
+ if (data) return data
1901
+
1902
+ return this.requestData(hash, 'data')
1903
+ }
1904
+
1905
+ /**
1906
+ * put content
1907
+ *
1908
+ * @param {String} hash
1909
+ * @param {Buffer} data
1910
+ */
1911
+ async put(hash, data, store = 'data') {
1912
+ store = globalThis[`${store}Store`];
1913
+ return await store.put(hash, data)
1914
+ }
1915
+
1916
+ /**
1917
+ * @param {String} hash
1918
+ * @return {Boolean}
1919
+ */
1920
+ async has(hash) {
1921
+ const store = await this.whichStore([...this.stores], hash);
1922
+ if (store) {
1923
+ if (store.private) return false
1924
+ else return true
1925
+ }
1926
+ return false
1927
+ }
1928
+
1929
+ /**
1930
+ *
1931
+ * @param {String} topic
1932
+ * @param {String|Object|Array|Boolean|Buffer} data
1933
+ */
1934
+ async publish(topic, data) {
1935
+ // globalSub.publish(topic, data)
1936
+
1937
+
1938
+ if (!Buffer.isBuffer(topic)) topic = Buffer.from(topic);
1939
+ if (!Buffer.isBuffer(data)) data = Buffer.from(data);
1940
+ const id = Math.random().toString(36).slice(-12);
1941
+ data = new PsMessage({data, topic});
1942
+ for (const peer of this.peers) {
1943
+ if (peer.connection._connected && peer.id.toString() !== this.peerId.toString()) {
1944
+ const node = await this.prepareMessage(peer.id, data.encoded);
1945
+ peer.write(Buffer.from(JSON.stringify({id, data: node.encoded})));
1946
+ } else {
1947
+ this.removePeer(peer);
1948
+ }
1949
+ // TODO: if peer subscribed
1950
+ }
1951
+ }
1952
+
1953
+ /**
1954
+ *
1955
+ * @param {String} topic
1956
+ * @param {Method} cb
1957
+ */
1958
+ async subscribe(topic, cb) {
1959
+ // TODO: if peer subscribed
1960
+ globalSub.subscribe(topic, cb);
1961
+ }
1962
+
1963
+ async removePeer(peer) {
1964
+ connections.delete(peer.id);
1965
+ }
1966
+ // async block(index) {
1967
+ // const _values = []
1968
+ // for (const peer of this.peers) {
1969
+ // const value = await peer.request({type: 'block', index})
1970
+ // console.log(value);
1971
+ // }
1972
+ //
1973
+ // }
2037
1974
  }
2038
1975
 
2039
1976
  module.exports = Peernet;