nodesNet

In the previous chapter, we introduced the node network of DMC. In this chapter, we will join this network and become a node to experience the charm of the blockchain network firsthand.

dmc-nodes

dmc-nodes is a script tool provided by the DMC community for quickly launching DMC mainnet nodes. It helps developers to quickly start three different types of nodes.

address:https://github.com/datamallchain/dmc-nodes

install

1
2
git clone git@github.com:datamallchain/dmc-nodes.git
cd dmc-nodes

start

1
2
3
dmc seed.js // sync node

dmc bp.js // producer node

Default data, configuration storage location: /blockData/data

Full Node Data Synchronization For Mainnet

Synchronizing full node block data can be time-consuming. The DMC community provides the latest mirror image startup service, greatly reducing the block synchronization time.

Service address:http://backups.dmctech.io:2748/

Usage Instructions

  1. Download the data:

    Visit http://backups.dmctech.io:2748/ and select the desired data package file, then click on the download link.

    Alternatively, obtain the file URL and use the wget command to download it.

    1
    wget http://backups.dmctech.io:2748/data_21395806.tar.gz
  2. Extract the file:

    1
    tar -zxvSf data_21395806.tar.gz
  3. Modify the configuration file config.json of the quick start script:

    Set the data_dir parameter to the path of the data directory where the data files were extracted.

    1
    "data_dir": "data/",
  1. Start full node

    1
    dmc seed.js

Joining the DMC Node Network Manually

If you are not using the dmc-nodes tool to start a node, you can also write your own startup script to join the node network.

Joining the DMC network requires several key pieces of information:

Obtaining the chainId of the node network

TestNet:

1
chainId: 'c102a8115bef9e4a4e751559aac2cdc2859417e6476f8cb6054cd3f7dffe1ce4'

DMC mainnet:

1
chainId : '4d1fb981dd562d2827447dafa89645622bdcd4e29185d60eeb45539f25d2d85d'

Providing the address and port for P2P listening

1
'p2p-listen-endpoint' : '0.0.0.0:9870'

Target Node Information for Block Data Synchronization

Block data synchronization must be performed from running super nodes.

TestNet:

1
2
3
4
5
6
7
8
{
"p2p-peer-address": [
"154.31.0.101:9870",
"154.31.0.101:9901",
"154.31.0.72:5701",
"154.31.0.72:5702"
]
}

DMC mainnet:
All super nodes on the DMC mainnet have been replaced by community nodes. For specific node information, please visit https://github.com/datamallchain/p2p-address/blob/main/p2p_address.json

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
{
"p2p-peer-address": [
"206.2.131.160:8871",
"206.2.131.160:8872",
"206.2.131.160:8873",
"154.216.191.129:8872",
"154.216.191.127:8872",
"154.216.191.128:8872",
"154.39.157.175:8872",
"154.39.157.179:8872",
"154.39.157.176:8872",
"154.39.157.177:8872",
"154.216.191.198:8872",
"154.31.50.146:8872",
"154.31.50.161:8872",
"154.31.50.141:8872",
"154.31.50.142:8872",
"154.39.157.178:8872",
"154.31.50.104:8872",
"154.216.191.199:8872",
"154.216.191.200:8872",
"154.31.50.88:8872",
"154.39.150.161:8872"
]
}

Note: The DMC mainnet BP P2P address provided in the example may change, so please stay updated and pay attention to any changes.

genesis.json file

TestNet:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
{
"initial_timestamp": "2023-06-06T00:00:00.000",
"initial_key": "DM6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"initial_configuration": {
"max_block_net_usage": 1048576,
"target_block_net_usage_pct": 1000,
"max_transaction_net_usage": 524288,
"base_per_transaction_net_usage": 12,
"net_usage_leeway": 500,
"context_free_discount_net_usage_num": 20,
"context_free_discount_net_usage_den": 100,
"max_block_cpu_usage": 200000,
"target_block_cpu_usage_pct": 1000,
"max_transaction_cpu_usage": 150000,
"min_transaction_cpu_usage": 100,
"max_transaction_lifetime": 3600,
"deferred_trx_expiration_window": 600,
"max_transaction_delay": 3888000,
"max_inline_action_size": 4096,
"max_inline_action_depth": 4,
"max_authority_depth": 6
}
}

DMC mainnet:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
{
"initial_timestamp": "2023-01-10T00:00:00.000",
"initial_key": "DM6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"initial_configuration": {
"max_block_net_usage": 1048576,
"target_block_net_usage_pct": 1000,
"max_transaction_net_usage": 524288,
"base_per_transaction_net_usage": 12,
"net_usage_leeway": 500,
"context_free_discount_net_usage_num": 20,
"context_free_discount_net_usage_den": 100,
"max_block_cpu_usage": 200000,
"target_block_cpu_usage_pct": 1000,
"max_transaction_cpu_usage": 150000,
"min_transaction_cpu_usage": 100,
"max_transaction_lifetime": 3600,
"deferred_trx_expiration_window": 600,
"max_transaction_delay": 3888000,
"max_inline_action_size": 4096,
"max_inline_action_depth": 4,
"max_authority_depth": 6
}
}

How to Become a Sync Node

If your node only needs to synchronize DMC block data, it is very simple. Save the following code tosync_node.js:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
var chain = require('chain');
var bp_dir = "./data"

chain.config_dir = bp_dir;
chain.data_dir = bp_dir;
chain.pubkey_prefix = "DM";
chain.name = "dmc";

console.notice("config_dir:", chain.config_dir);
console.notice("data_dir:", chain.data_dir);

chain.load("http", {
"http-server-address": "0.0.0.0:8870",
"access-control-allow-origin": "*",
"http-validate-host": false,
"verbose-http-errors": true //open error
});

chain.load("net", {
"p2p-peer-address": ["206.2.131.160:8871", "206.2.131.160:8872"], // Modifying According to Node Information
"max-clients": 100,
"p2p-listen-endpoint": "0.0.0.0:9870"
});

chain.load("producer", {
'max-transaction-time': 3000,
});


chain.load("chain", {
"contracts-console": true,
"genesis-json": "genesis.json",
"enable-account-queries": true
});

chain.load("chain_api");
chain.load("trace_api", {
"trace-no-abis": "true"
});
chain.start();

In the above code, the p2p-peer-address in the net module is a variable value. Please make sure to modify it accordingly.

To run the synchronization node:

1
dmc sync_node.js

How to become a BP node

(* BP Block Producer)

Important Note: When applying for registration as a Producer, it is highly recommended not to use the same key for your producer key and active key.

If a node needs to apply for registration as a block producer on the DMC mainnet, it involves three aspects:

Configuring Producer Information to Start the DMC Node Service

Only when the amount of PST@datamall reaches a certain value, the DMC node will truly become a Producer with the ability to produce blocks. In other cases, it will only function as a node for synchronizing block data.

The following code demonstrates the configuration of a Producer. Save the code to producer_node.js:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
const dmc = require('chain');
const config = require("./config.json")
console.notice("start dmc producer node");
const DMC = require('dmc.js')
let keys = "";
while (true) {
keys = console.readLine("input the producer-name:private-key! oooo:xxxx\n");
if (keys) break;
}
let public_key = "";
let private_key = "";
let producername = "";
keys = keys.split(":");
producername = keys[0];
private_key = keys[1];

public_key = DMC.ecc.privateToPublic(private_key);
dmc.config_dir = config.config_dir;
dmc.data_dir = config.data_dir;
dmc.pubkey_prefix = "DM";
dmc.name = "dmc";

let chain_config = {
"contracts-console": true,
'chain-state-db-size-mb': 1024 * 1024,
"genesis-json": "genesis.json"
};

console.notice("config_dir:", dmc.config_dir);
console.notice("data_dir:", dmc.data_dir);

dmc.load("http", {
"http-server-address": `0.0.0.0:${config.http_port}`,
"access-control-allow-origin": "*",
"http-validate-host": false,
"verbose-http-errors": true
});

dmc.load("net", {
"max-clients": 100,
"p2p-peer-address": config.p2p_peer_address,
"p2p-listen-endpoint": `0.0.0.0:${config.p2p_port}`
});

dmc.load("producer", {
'producer-name': producername,
'private-key': JSON.stringify([public_key, private_key])
});

dmc.load("chain", chain_config);
dmc.load("chain_api");
dmc.load("producer_api");

dmc.start()

It is strongly recommended to disable external network RPC access for a Block Producer’s API nodes. If RPC access is required for the node, utilizing internal network HTTP is advisable. The corresponding configuration example code is as follows:

1
2
3
dmc.load("http", {
"http-server-address": "127.0.0.1:8870",
});

The contents of config.json are as follows:

1
2
3
4
5
6
7
8
9
10
11
12
{
"chainId": "97f1c8a5826da6959a893a1bb66c9efe74c9a52d60fda4c3eac0af0d021f8256",
"httpEndpoint": "http://154.22.123.188:8870",
"url": "explorer.dmctech.io",
"location": 702,
"config_dir": "./data",
"data_dir": "./data",
"http_port": 8781,
"p2p_port": 8681,
"p2p_peer_address": [
]
}

Parameter explanation:

configuration Item explanation remark
chainId DMC Blockchain Network ID cannot be modified
httpEndpoint RPC interface provided cannot be modified
url URL information for registering BP modify as needed
location address for registering BP modify as needed
config_dir location to save local blockchain configuration not recommended to modify
data_dir location to save local blockchain data not recommended to modify
http_port RPC port for local blockchain to listen and access services is provided modify as needed
p2p_port P2P port for local blockchain to listen for connections from other nodes modify as needed
p2p_peer_address P2P addresses of other nodes to connect to modify as needed

Install dependencies

1
dmc --install dmc.js

Run Producer node:

1
dmc producer_node.js

Enter the private key and block producer name as required. The specific format is as follows:

producer-name:private-key

Taking “testnetbppa4” as an example, enter:

testnetbppa4:5K7NFbDfjxV7khfKdRvPEUt5Ny***cdfiR83p1t3npPEavAegc3

Note: Keep this process running without being closed

Initiating Registration Application as a Producer

Save the following code to register_bp.js :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
var DMC = require('dmc.js');
var config = require("./config.json")
let keys = "";
while (true) {
keys = console.readLine("input the producer-name:private-key! oooo:xxxx\n");
if (keys) break;
}

let public_key = "";
let private_key = "";
let producername = "";
keys = keys.split(":");
producername = keys[0];
private_key = keys[1];
public_key = DMC.ecc.privateToPublic(private_key);

//Initialize the client
let dmc = DMC({
chainId: config.chainId,
keyProvider: private_key,
httpEndpoint: config.httpEndpoint,
logger: {
log: null,
error: null
}
});

dmc.transact_sync({
actions: [
{
account: 'dmc',
name: 'regproducer',
authorization: [{
actor: producername,
permission: 'active',
}],
data: {
producer: producername,
producer_key: public_key,
url: config.url,
location: config.location
}
}]
}, {
blocksBehind: 3,
expireSeconds: 30,
});

let c = dmc.rpc.get_table_rows_sync({
json: true,
code: "dmc",
scope: "dmc",
table: "producers",
lower_bound: producername,
upper_bound: producername,
limit: 1000
});
console.warn(c);

Execute the code

1
dmc register_bp.js

Enter the same content as above

Minting PST@datamall to Become a Producer

Only by holding a sufficient amount of PST@datamall can one become a Producer. The quantity of minted PST is determined by the minting contract and can be calculated using the formula $PST = \frac{DMC}{m’\times p} $.

Save the following code tomint.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
var DMC = require('dmc.js');
var config = require("./config.json")
let keys = "";
let quantity = "";
while (true) {
keys = console.readLine("input the producer-name:private-key! oooo:xxxx\n");
if (keys) break;
}

while (true) {
quantity = console.readLine("input the quantity of PST be minted: e.g. 20 PST\n");
if (quantity) break;
}

let producername = "";
keys = keys.split(":");
producername = keys[0];
let private_key = keys[1];

//Initialize the client
let dmc = DMC({
chainId: config.chainId,
keyProvider: private_key,
httpEndpoint: config.httpEndpoint,
logger: {
log: null,
error: null
}
});

dmc.transact_sync({
actions: [
{
account: 'dmc.token',
name: 'mint',
authorization: [{
actor: producername,
permission: 'active',
}],
data: {
"owner": producername,
"asset": {
"quantity": quantity,
"contract": "datamall"
}
}
}]
}, {
blocksBehind: 3,
expireSeconds: 30,
});

let c = dmc.rpc.get_table_rows_sync({
json: true,
code: "dmc.token",
scope: "dmc.token",
table: "pststats",
lower_bound: producername,
upper_bound: producername,
limit: 10,
}).rows;
console.warn(c);

Execute the code

1
$ dmc mint.js
1
2
3
4
input the producer-name:private-key! oooo:xxxx
> testlfdlzz1t:5KUCoizhwKCmrq4FofXbzbzaBjmH28WZ7nFY4VogM6d7LfYWewf
input the quantity of PST be minted: e.g. 20 PST
> 20 PST

The above example will mint 20 PST@datamall

Component Specification
CPU 8 cores
Memory 16GB RAM
Storage 500GB HDD