@blinklabs/dingo 0.85.0 → 0.88.0
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/README.md +1 -1
- package/npm/checksums.json +6 -6
- package/npm/install.js +101 -5
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
<a href="https://discord.gg/5fPRZnX4qW"><img src="https://img.shields.io/badge/Discord-7289DA?style=flat&logo=discord&logoColor=white" alt="Discord"></a>
|
|
9
9
|
</div>
|
|
10
10
|
|
|
11
|
-
> ⚠️ **WARNING: Dingo is under heavy active development and is not yet ready for mainnet block production use. It should only be used on testnets (preview, preprod, musashi) and devnets. Do not use Dingo on mainnet for block production with real funds.**
|
|
11
|
+
> ⚠️ **WARNING: Dingo is under heavy active development and is not yet ready for mainnet block production use. It should only be used on testnets (preview, preprod, musashi, dijkstra) and devnets. Do not use Dingo on mainnet for block production with real funds.**
|
|
12
12
|
|
|
13
13
|
Dingo is Blink Labs' Cardano node implementation in Go. It implements the
|
|
14
14
|
Ouroboros networking and consensus protocols, validates ledger state, and
|
package/npm/checksums.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
|
-
"dingo-v0.
|
|
3
|
-
"dingo-v0.
|
|
4
|
-
"dingo-v0.
|
|
5
|
-
"dingo-v0.
|
|
6
|
-
"dingo-v0.
|
|
7
|
-
"dingo-v0.
|
|
2
|
+
"dingo-v0.88.0-darwin-amd64.tar.gz": "79d7415714c60bbeef7d2c5fb7c97de9b7d99c97abad25298df7d2a3dde53aa8",
|
|
3
|
+
"dingo-v0.88.0-darwin-arm64.tar.gz": "11b33bd6ab0f67ef14f1a8c2856b57856561d0ca8d70bc9e3ee1130a2df32e6c",
|
|
4
|
+
"dingo-v0.88.0-freebsd-amd64.tar.gz": "b88d9fb5cdcdac7ae85c5486ab2260feec966235d6cd75e0ceb646e32c066d9e",
|
|
5
|
+
"dingo-v0.88.0-freebsd-arm64.tar.gz": "a5f44c93a95a8bcb244d3ca93211d19975dbf359c59c29fa05bebe9a1035418c",
|
|
6
|
+
"dingo-v0.88.0-linux-amd64.tar.gz": "06113229e0d2eb3c222dec1e4b2be07ab8313857cbbc7e1c568a19c001329cb1",
|
|
7
|
+
"dingo-v0.88.0-linux-arm64.tar.gz": "b8cfe72c8cf75173155e9975597800df6098fe1607e45578c52b641f69e04a81"
|
|
8
8
|
}
|
package/npm/install.js
CHANGED
|
@@ -13,9 +13,11 @@
|
|
|
13
13
|
'use strict';
|
|
14
14
|
|
|
15
15
|
const crypto = require('node:crypto');
|
|
16
|
+
const dns = require('node:dns');
|
|
16
17
|
const fs = require('node:fs');
|
|
17
18
|
const fsp = require('node:fs/promises');
|
|
18
19
|
const https = require('node:https');
|
|
20
|
+
const net = require('node:net');
|
|
19
21
|
const os = require('node:os');
|
|
20
22
|
const path = require('node:path');
|
|
21
23
|
const { spawn } = require('node:child_process');
|
|
@@ -25,6 +27,97 @@ const { pipeline } = require('node:stream/promises');
|
|
|
25
27
|
const MAX_ARCHIVE_BYTES = 256 * 1024 * 1024;
|
|
26
28
|
const MAX_BINARY_BYTES = 512 * 1024 * 1024;
|
|
27
29
|
const RETRY_DELAYS_MS = [100, 500];
|
|
30
|
+
const RELEASE_HOSTS = new Set([
|
|
31
|
+
'github.com',
|
|
32
|
+
'github-releases.githubusercontent.com',
|
|
33
|
+
'objects.githubusercontent.com',
|
|
34
|
+
'release-assets.githubusercontent.com',
|
|
35
|
+
]);
|
|
36
|
+
|
|
37
|
+
// The two families are kept in separate lists because a Node BlockList matches
|
|
38
|
+
// every IPv4 address against an IPv6 rule covering ::ffff:0:0/96, which would
|
|
39
|
+
// reject all IPv4 answers. IPv4-mapped IPv6 answers are unmapped instead and
|
|
40
|
+
// checked against the IPv4 rules.
|
|
41
|
+
const blockedIPv4 = new net.BlockList();
|
|
42
|
+
for (const [network, prefix] of [
|
|
43
|
+
['0.0.0.0', 8], ['10.0.0.0', 8], ['100.64.0.0', 10], ['127.0.0.0', 8],
|
|
44
|
+
['169.254.0.0', 16], ['172.16.0.0', 12], ['192.0.0.0', 24], ['192.0.2.0', 24],
|
|
45
|
+
['192.88.99.0', 24], ['192.168.0.0', 16], ['198.18.0.0', 15],
|
|
46
|
+
['198.51.100.0', 24], ['203.0.113.0', 24], ['224.0.0.0', 4], ['240.0.0.0', 4],
|
|
47
|
+
]) blockedIPv4.addSubnet(network, prefix, 'ipv4');
|
|
48
|
+
const blockedIPv6 = new net.BlockList();
|
|
49
|
+
for (const [network, prefix] of [
|
|
50
|
+
['::', 128], ['::1', 128], ['64:ff9b::', 96], ['64:ff9b:1::', 48],
|
|
51
|
+
['100::', 64], ['2001:2::', 48], ['2001:db8::', 32], ['2001:10::', 28],
|
|
52
|
+
['fc00::', 7], ['fe80::', 10], ['ff00::', 8],
|
|
53
|
+
]) blockedIPv6.addSubnet(network, prefix, 'ipv6');
|
|
54
|
+
|
|
55
|
+
function mappedIPv4(address) {
|
|
56
|
+
let host;
|
|
57
|
+
try {
|
|
58
|
+
// URL serialization canonicalizes every IPv6 spelling to compressed hex.
|
|
59
|
+
host = new URL(`http://[${address}]`).hostname;
|
|
60
|
+
} catch {
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
const match = /^\[::ffff:([0-9a-f]{1,4}):([0-9a-f]{1,4})\]$/.exec(host);
|
|
64
|
+
if (!match) return null;
|
|
65
|
+
const high = parseInt(match[1], 16);
|
|
66
|
+
const low = parseInt(match[2], 16);
|
|
67
|
+
return `${high >> 8}.${high & 255}.${low >> 8}.${low & 255}`;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function disallowedAddress(address) {
|
|
71
|
+
try {
|
|
72
|
+
if (net.isIPv4(address)) return blockedIPv4.check(address, 'ipv4');
|
|
73
|
+
if (!net.isIPv6(address)) return true;
|
|
74
|
+
const ipv4 = mappedIPv4(address);
|
|
75
|
+
if (ipv4) return blockedIPv4.check(ipv4, 'ipv4');
|
|
76
|
+
return blockedIPv6.check(address, 'ipv6');
|
|
77
|
+
} catch {
|
|
78
|
+
return true;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function validateReleaseURL(parsed) {
|
|
83
|
+
if (parsed.protocol !== 'https:') {
|
|
84
|
+
throw new Error('Dingo release downloads require HTTPS');
|
|
85
|
+
}
|
|
86
|
+
if (parsed.username || parsed.password || (parsed.port && parsed.port !== '443')) {
|
|
87
|
+
throw new Error('Dingo release download URL is not allowed');
|
|
88
|
+
}
|
|
89
|
+
if (!RELEASE_HOSTS.has(parsed.hostname.toLowerCase())) {
|
|
90
|
+
throw new Error('Dingo release download host is not allowed');
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function publicLookup(hostname, options, callback) {
|
|
95
|
+
const lookupOptions = typeof options === 'object' ? options : {};
|
|
96
|
+
dns.lookup(hostname, {
|
|
97
|
+
family: lookupOptions.family,
|
|
98
|
+
hints: lookupOptions.hints,
|
|
99
|
+
all: true,
|
|
100
|
+
verbatim: true,
|
|
101
|
+
}, (error, addresses) => {
|
|
102
|
+
if (error) {
|
|
103
|
+
callback(error);
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
if (addresses.length === 0 || addresses.some(({ address }) => disallowedAddress(address))) {
|
|
107
|
+
callback(new Error('Dingo release host resolved to a disallowed address'));
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
if (lookupOptions.all) {
|
|
111
|
+
callback(null, addresses);
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
callback(null, addresses[0].address, addresses[0].family);
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
function secureGet(url, callback) {
|
|
119
|
+
return https.get(url, { lookup: publicLookup }, callback);
|
|
120
|
+
}
|
|
28
121
|
|
|
29
122
|
function releaseTarget(version, platform = process.platform, arch = process.arch) {
|
|
30
123
|
const targets = {
|
|
@@ -64,9 +157,12 @@ function byteLimit(maxBytes, description) {
|
|
|
64
157
|
|
|
65
158
|
function downloadOnce(url, destination, get, redirects, maxBytes) {
|
|
66
159
|
return new Promise((resolve, reject) => {
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
160
|
+
let parsed;
|
|
161
|
+
try {
|
|
162
|
+
parsed = new URL(url);
|
|
163
|
+
validateReleaseURL(parsed);
|
|
164
|
+
} catch (error) {
|
|
165
|
+
reject(error);
|
|
70
166
|
return;
|
|
71
167
|
}
|
|
72
168
|
const request = get(parsed, (response) => {
|
|
@@ -109,7 +205,7 @@ function downloadOnce(url, destination, get, redirects, maxBytes) {
|
|
|
109
205
|
});
|
|
110
206
|
}
|
|
111
207
|
|
|
112
|
-
async function download(url, destination, get =
|
|
208
|
+
async function download(url, destination, get = secureGet, options = {}) {
|
|
113
209
|
const delays = options.retryDelays ?? RETRY_DELAYS_MS;
|
|
114
210
|
const wait = options.wait ?? ((milliseconds) => new Promise((resolve) => {
|
|
115
211
|
setTimeout(resolve, milliseconds);
|
|
@@ -208,4 +304,4 @@ async function install(packageRoot, options = {}) {
|
|
|
208
304
|
}
|
|
209
305
|
}
|
|
210
306
|
|
|
211
|
-
module.exports = { binaryPath, download, install, releaseURL };
|
|
307
|
+
module.exports = { binaryPath, download, install, publicLookup, releaseURL };
|