Skip to content

Commit 92af843

Browse files
committed
Merge branch 'release/0.1.6'
2 parents 4b4ea2a + 22851cb commit 92af843

File tree

8 files changed

+248
-70
lines changed

8 files changed

+248
-70
lines changed

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,14 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
77

88
## [Unreleased]
99

10+
## [0.1.5] - 2018-03-27
11+
12+
### Added
13+
14+
* Multiple Field Servers support
15+
* Donation Seed and Address checking
16+
* Custom IP address binding
17+
1018
## [0.1.5] - 2018-02-17
1119

1220
### Changed

README.md

Lines changed: 37 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -197,17 +197,36 @@ You can provide one or more of the following options in your ini file. Example:
197197
```
198198
[field]
199199
name = MyField
200+
; Optional, which IP to bind the node on
201+
bindAddress = 0.0.0.0
202+
port = 21310
203+
; If you want Field to generate a custom id, instead of using machine-id.
204+
; This is the safest and favored way:
205+
customFieldId = true
206+
207+
; You can choose which Field(s) to connect to:
208+
fieldHostname[] = field.carriota.com:80
209+
; It can be several Fields. Just repeat:
210+
; fieldHostname[] = field.carriota.com:80
211+
; fieldHostname[] = another.field.com:8080
212+
; fieldHostname[] = mytest.field.com:5000
213+
214+
; IRI connection details:
200215
IRIPort = 14265
201216
IRIHostname = localhost
217+
202218
address = SOZAIPJMQUBOFCTDTJJDXCZEKNIYZGIGVDLFMH9FFBAYK9SWGTBCWVUTFHXDOUESZAXRJJCJESJPIEQCCKBUTVQPOW
203219
; Alternatively to address, you can provide a (NEW) seed
204-
; In this case, the Field cient will be generating new, unused addresses dynamically.
220+
; In this case, the Field client will be generating new, unused addresses dynamically.
205221
; seed = XYZ
206-
port = 21310
222+
223+
; What jobs your node should be able to accept:
224+
; both true - only attachToTangle jobs accepted
225+
; disableIRI false - all jobs accepted
226+
; pow false - no jobs accepted
227+
; both false - all jobs except attachToTangle accepted
207228
pow = true
208229
disableIRI = false
209-
; If you want Field to generate a custom id, instead of using machine-id
210-
customFieldId = true
211230
```
212231

213232
### Command line options
@@ -217,19 +236,20 @@ Some have additional short versions.
217236

218237
### Options description
219238

220-
| Option | Description | Default |
221-
| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------- |
222-
| --name | Name your node. This identifier will appear on the CarrIOTA Field Dashboard | CarrIOTA Field |
223-
| --address, -a | Optional IOTA address for donations. | |
224-
| --seed, -b | Optional. If no donation address is provided, you can provide a seed. In that case the field client will generate new, unused addresses dynamically. WARNING! Please do not use your usual, main seed. Generate a new one for this occasion. It is easy and adds up to everyone's security. | |
225-
| --config, -c | Path to Field configuration file. | |
226-
| --disableIRI, -d | Do not allow jobs to be passed from the Field load balancer. Just send the statistics about my node. | false |
227-
| --iriHostname, -h | Hostname where your IRI instance is running. | localhost |
228-
| --iriPort, -i | API port of your IRI instance. | 14265 |
229-
| --port, -p | Field port to be used | 21310 |
230-
| --silent, -s | Do not print log messages | false |
231-
| --pow, -w | Allow attachToTangle jobs to be passed from the Field server load balancer. When disableIRI and pow are true, only PoW work will be passed to IRI. | false |
232-
| --customFieldId, -y | If you want Field to generate a custom id, instead of using machine-id. This is required for VPS and servers created from an image, which often have the same machine ID. | false |
239+
| Option | Description | Default |
240+
| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------- |
241+
| --name | Name your node. This identifier will appear on the CarrIOTA Field Dashboard | CarrIOTA Field |
242+
| --address, -a | Optional IOTA address for donations. | |
243+
| --seed, -b | Optional. If no donation address is provided, you can provide a seed. In that case the field client will generate new, unused addresses dynamically. WARNING! Please do not use your usual, main seed. Generate a new one for this occasion. It is easy and adds up to everyone's security. | |
244+
| --config, -c | Path to Field configuration file. | |
245+
| --disableIRI, -d | Do not allow jobs to be passed from the Field load balancer. Just send the statistics about my node. | false |
246+
| --fieldHostname, -f | Field Server hostname (including port) or a space-separated list of multiple Field Server hostnames. | field.carriota.com:80 |
247+
| --iriHostname, -h | Hostname where your IRI instance is running. | localhost |
248+
| --iriPort, -i | API port of your IRI instance. | 14265 |
249+
| --port, -p | Field port to be used | 21310 |
250+
| --silent, -s | Do not print log messages | false |
251+
| --pow, -w | Allow attachToTangle jobs to be passed from the Field server load balancer. When disableIRI and pow are true, only PoW work will be passed to IRI. | false |
252+
| --customFieldId, -y | If you want Field to generate a custom id, instead of using machine-id. This is required for VPS and servers created from an image, which often have the same machine ID. | false |
233253

234254
### Run PoW jobs only
235255

config.ini.example

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,32 @@
11
[field]
22
name = MyField
3+
; Optional, which IP to bind the node on
4+
bindAddress = 0.0.0.0
5+
port = 21310
6+
; If you want Field to generate a custom id, instead of using machine-id.
7+
; This is the safest and favored way:
8+
customFieldId = true
9+
10+
; You can choose which Field(s) to connect to:
11+
fieldHostname[] = field.carriota.com:80
12+
; It can be several Fields. Just repeat:
13+
; fieldHostname[] = field.carriota.com:80
14+
; fieldHostname[] = another.field.com:8080
15+
; fieldHostname[] = mytest.field.com:5000
16+
17+
; IRI connection details:
318
IRIPort = 14265
419
IRIHostname = localhost
20+
521
address = SOZAIPJMQUBOFCTDTJJDXCZEKNIYZGIGVDLFMH9FFBAYK9SWGTBCWVUTFHXDOUESZAXRJJCJESJPIEQCCKBUTVQPOW
6-
port = 21310
22+
; Alternatively to address, you can provide a (NEW) seed
23+
; In this case, the Field client will be generating new, unused addresses dynamically.
24+
; seed = XYZ
25+
26+
; What jobs your node should be able to accept:
27+
; both true - only attachToTangle jobs accepted
28+
; disableIRI false - all jobs accepted
29+
; pow false - no jobs accepted
30+
; both false - all jobs except attachToTangle accepted
731
pow = true
32+
disableIRI = false

dist/field.js

Lines changed: 37 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ var fieldIDFilePath = path.join(os.homedir(), '.carriota-field.id');
3939
var DEFAULT_OPTIONS = {
4040
name: null,
4141
port: 21310,
42-
fieldHostname: 'field.carriota.com',
42+
fieldHostname: ['field.carriota.com'],
4343
IRIHostname: 'localhost',
4444
IRIPort: 14265,
4545
logIdent: 'FIELD',
@@ -81,12 +81,19 @@ var Field = function (_Base) {
8181
_this.iriData = null;
8282
_this.id = id;
8383
_this.publicId = publicId;
84-
_this.log(('Field Client v.' + version).bold.green);
85-
_this.log('Field ID: ' + _this.id);
86-
_this.log('Public ID: ' + _this.publicId);
87-
if (_this.opts.disableIRI) {
88-
_this.log('Public IRI access through the Field is disabled');
84+
85+
_this.log(('Field Client v.' + version).bold.green);
86+
_this.log('Field ID: ' + _this.id + ' (do NOT share online!)');
87+
_this.log('Public ID: ' + _this.publicId);
88+
_this.log('Field Server(s): ' + _this.opts.fieldHostname.join(' '));
89+
_this.log('Donations: ' + (_this.opts.seed || _this.opts.address ? 'ENABLED' : 'DISABLED'));
90+
if (_this.opts.seed || _this.opts.address) {
91+
var donationsString = _this.opts.address ? 'Static IOTA donations address: ' + _this.opts.address : 'Seed for dynamic IOTA address generation: ' + _this.opts.seed.slice(0, 3) + '*****';
92+
_this.log('Donations: ' + donationsString);
8993
}
94+
_this.log('IRI: Public access through the Field is ' + (_this.opts.disableIRI ? 'DISABLED' : 'ENABLED'));
95+
_this.log('IRI: PoW (attachToTangle) jobs are ' + (_this.opts.pow ? 'ENABLED' : 'DISABLED'));
96+
9097
_this.connRefused = function (reason) {
9198
if (reason.code === 'ECONNREFUSED') {
9299
_this.log(('Proxy error: IRI connection refused: http://' + _this.opts.IRIHostname + ':' + _this.opts.IRIPort).red);
@@ -165,7 +172,10 @@ var Field = function (_Base) {
165172
}, 20000);
166173

167174
return new Promise(function (resolve) {
168-
_this2.checkIRI(resolve);
175+
_this2.checkIRI(function () {
176+
_this2.sendUpdates();
177+
resolve();
178+
});
169179
});
170180
}
171181

@@ -251,15 +261,22 @@ var Field = function (_Base) {
251261
address: address
252262
}
253263
};
254-
request({
255-
url: 'http://' + _this4.opts.fieldHostname + '/api/v1/update',
256-
method: 'POST',
257-
json: json
258-
}, function (err, resp, body) {
259-
if (err || resp.statusCode !== 200) {
260-
_this4.log(('Field update error to ' + _this4.opts.fieldHostname + ':').red, resp && resp.statusCode, err && err.code, body);
261-
}
262-
//this.log('Update response:', body);
264+
_this4.opts.fieldHostname.forEach(function (fieldHostname) {
265+
request({
266+
url: 'http://' + fieldHostname + '/api/v1/update',
267+
method: 'POST',
268+
json: json
269+
}, function (err, resp, body) {
270+
if (err || resp.statusCode !== 200) {
271+
_this4.log(('ERROR pinging Field Server ' + fieldHostname + ':').red);
272+
if (err && err.code) {
273+
_this4.log('- LOCAL Client error message: ' + err.code);
274+
}
275+
if (body && body.error) {
276+
_this4.log('- REMOTE Server error message (HTTP Code ' + (resp && resp.statusCode) + '): ' + body.error);
277+
}
278+
}
279+
});
263280
});
264281
});
265282
}
@@ -282,6 +299,10 @@ var Field = function (_Base) {
282299
resolve(null);
283300
}
284301
_this5.api.getNewAddress(_this5.opts.seed, { checksum: true }, function (err, address) {
302+
if (err) {
303+
_this5.log('ERROR: Could not generate a donation address with your seed:', err);
304+
_this5.log('...pinging without a donation address');
305+
}
285306
resolve(err ? null : address);
286307
});
287308
});

dist/index.js

Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,25 +4,52 @@
44
require('colors');
55

66
var ini = require('ini');
7+
8+
var _require = require('iota.lib.js/lib/utils/inputValidator'),
9+
isTrytes = _require.isTrytes;
10+
11+
var _require2 = require('iota.lib.js/lib/utils/utils'),
12+
isValidChecksum = _require2.isValidChecksum;
13+
714
var fs = require('fs');
815
var program = require('commander');
916

10-
var _require = require('./field'),
11-
DEFAULT_OPTIONS = _require.DEFAULT_OPTIONS,
12-
Field = _require.Field;
17+
var _require3 = require('./field'),
18+
DEFAULT_OPTIONS = _require3.DEFAULT_OPTIONS,
19+
Field = _require3.Field;
1320

14-
var _require2 = require('./base'),
15-
DEFAULT_BASE_OPTIONS = _require2.DEFAULT_OPTIONS;
21+
var _require4 = require('./base'),
22+
DEFAULT_BASE_OPTIONS = _require4.DEFAULT_OPTIONS;
1623

1724
var version = require('../package.json').version;
1825

1926
var parseNumber = function parseNumber(v) {
2027
return parseInt(v);
2128
};
29+
var parseServers = function parseServers(val) {
30+
return val.split(' ');
31+
};
32+
var parseSeed = function parseSeed(seed) {
33+
if (seed && !isTrytes(seed, 81)) {
34+
throw new Error('Wrong seed format provided! Has to be a 81-trytes string!');
35+
}
36+
return seed;
37+
};
38+
39+
var parseAddress = function parseAddress(address) {
40+
if (address) {
41+
if (!isTrytes(address, 90)) {
42+
throw new Error('Wrong donation address provided. Has to be a 90-trytes string (81+checksum)!');
43+
}
44+
if (!isValidChecksum(address)) {
45+
throw new Error('Please check your donation address: wrong checksum!');
46+
}
47+
}
48+
return address;
49+
};
2250

2351
// TODO: write tests
24-
// TODO: write README
25-
program.version(version).option('-a, --address [value]', 'Optional IOTA address for donations', null).option('-b, --seed [value]', 'Optional IOTA seed for automatic donation address generation', null).option('-c, --config [value]', 'Config file path', null).option('-d, --disableIRI [value]', 'Do not allow public IRI connections through the Field', DEFAULT_OPTIONS.disableIRI).option('-f, --fieldHostname [value]', 'Hostname of the Field endpoint', process.env.FIELD_HOSTNAME || DEFAULT_OPTIONS.fieldHostname).option('-h, --IRIHostname [value]', 'IRI API hostname', process.env.IRI_HOSTNAME || DEFAULT_OPTIONS.IRIHostname).option('-i, --IRIPort [value]', 'IRI API port', parseNumber, process.env.IRI_PORT || DEFAULT_OPTIONS.IRIPort).option('-n, --name [value]', 'Name of your node instance', DEFAULT_OPTIONS.name).option('-p, --port [value]', 'Field port', parseNumber, DEFAULT_OPTIONS.port).option('-s, --silent [value]', 'Silent', DEFAULT_BASE_OPTIONS.silent).option('-w, --pow [value]', 'Allow attachToTange / PoW', DEFAULT_OPTIONS.pow).option('-y, --customFieldId [value]', 'Generate a custom field ID, instead of using machine ID').parse(process.argv);
52+
program.version(version).option('-a, --address [value]', 'Optional IOTA address for donations', parseAddress, null).option('-b, --seed [value]', 'Optional IOTA seed for automatic donation address generation', parseSeed, null).option('-c, --config [value]', 'Config file path', null).option('-d, --disableIRI [value]', 'Do not allow public IRI connections through the Field', DEFAULT_OPTIONS.disableIRI).option('-f, --fieldHostname [value]', 'Hostname of the Field endpoint', parseServers, process.env.FIELD_HOSTNAME ? parseServers(process.env.FIELD_HOSTNAME) : DEFAULT_OPTIONS.fieldHostname).option('-h, --IRIHostname [value]', 'IRI API hostname', process.env.IRI_HOSTNAME || DEFAULT_OPTIONS.IRIHostname).option('-i, --IRIPort [value]', 'IRI API port', parseNumber, process.env.IRI_PORT || DEFAULT_OPTIONS.IRIPort).option('-n, --name [value]', 'Name of your node instance', DEFAULT_OPTIONS.name).option('-p, --port [value]', 'Field port', parseNumber, DEFAULT_OPTIONS.port).option('-s, --silent [value]', 'Silent', parseSeed, DEFAULT_BASE_OPTIONS.silent).option('-w, --pow [value]', 'Allow attachToTange / PoW', DEFAULT_OPTIONS.pow).option('-y, --customFieldId [value]', 'Generate a custom field ID, instead of using machine ID').parse(process.argv);
2653

2754
var configPath = process.env.FIELD_CONFIG || program.config;
2855

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "field.cli",
3-
"version": "0.1.5",
3+
"version": "0.1.6",
44
"description": "CarrIOTA Field Client",
55
"main": "dist/field.js",
66
"homepage": "https://semkodev.com",

0 commit comments

Comments
 (0)