Welcome to the official Go implementation of DxChain protocol!
gdx
program is built on top of the DxChain protocol. DxChain is a blockchain based P2P network for data storage. The core feature is that user can upload data to the network as storage client or provide data storage service for other peers in the network as a storage host. In addition, DxChain also contains features that are supported by other blockchain, such as distributed ledger and smart contracts.
NOTE: the master
branch will always contain the most active code. However, it is not stable.
Table of contents:
- Go DX
- Section 1. Getting Started
- Section 2. Running
gdx
- Section 3. Tutorial
- Section 4. Basic Console Commands
- License
- Appendix
- Contact
NOTE: currently, we only support MacOS and Linux. Windows is not supported yet.
To build the program from the source code, Golang 1.11 is required. Please follow this link to install Golang on your computer. To check if the program is installed successfully, use the following command:
$ go version
Xcode can be installed from the App Store
Go Vendor is a package management tool used for this project. It can be installed via:
$ go get -u -v github.com/kardianos/govendor
The installation of Docker is optional. Docker is used for cross-platform build meaning if you want to build linux version of gdx
on your MacBook, you have to install Docker. Please follow the following installation guide:
Docker Installation Guide for Mac
Docker Installation Guide for Linux
$ mkdir -p $GOPATH/src/github.com/DxChainNetwork
$ cd $GOPATH/src/github.com/DxChainNetwork
$ git clone git@github.com:DxChainNetwork/godx.git
NOTE: please checkout to the latest release branch by using the following command:
$ git checkout release0.8.0
Required packages can be installed via go vendor,
$ cd $GOPATH/src/github.com/DxChainNetwork/godx
$ govendor sync -v
All packages saved in the godx/vendor/vendor.json
will be downloaded. Please wait for download to finish.
Build for your operating system
$ make gdx
Add gdx
executable to your path by going through the following commands:
$ cd $GOPATH/src/github.com/DxChainNetwork/godx/build/bin
$ export PATH=$PATH:$(pwd)
For each terminal you open, you have to run the above commands. For more advanced users, you can add the export statement in the shell init file like ~/.bash_profile
or ~/.zshrc
In the DxChain Network, a node will always be able to perform mining operation regardless of the role the node choose to be. There are three roles available and each node can choose to become all of them at the same time or one of them only:
- Storage Client
- Storage Host
- Miner
To run the node that is capable of performing all operations, use the following command:
$ gdx
If you do not intend to become neither a storage client nor a storage host, you can start the program by running the following command in the terminal
$ gdx --role miner
By paying DX tokens to storage hosts, storage client is able to rent storage space and store files in the DX network safely and securely. When needed, storage client can download those files from the network.
If you intend to become a storage client only, run the following command in the terminal
$ gdx --role storageclient
Storage host serves as a storage service provider, gaining profit for storing data uploaded by the storage client.
If you intend to become a storage host only, run the following command in the terminal
$ gdx --role storagehost
The basic tutorial can be found here
Once the gdx
program is up and running, you can use the following command to open the gdx
console to perform different operations, such as mining, creating storage contract, uploading files, and etc.
$ gdx attach
Usage | Description |
---|---|
personal.newAccount() | Generate a new account |
Example:
> personal.newAccount()
Passphrase:
Repeat passphrase:
"0x1ec76840382bfde5ec6a03dadd71947d842577e3"
Usage | Description |
---|---|
eth.accounts | Retrieve all accounts |
Example
> eth.accounts
["0x1ec76840382bfde5ec6a03dadd71947d842577e3"]
Usage | Description |
---|---|
personal.unlockAccount(address, passphrase, duration) | Unlock the account |
NOTE: To send transactions, the account must be unlocked. To use storage services, the account must be unlocked permanently because the transactions are made automatically.
The duration is measured in terms of seconds with 300 seconds as its default value. To make an account be permanently unlocked, set the duration to 0.
Example:
> personal.unlockAccount(eth.accounts[0], "", 0)
true
which is equivalent to
> personal.unlockAccount("0x1ec76840382bfde5ec6a03dadd71947d842577e3", "", 0)
true
Usage | Description |
---|---|
eth.getBalance(address) | Check the account balance |
Example:
> eth.getBalance(eth.accounts[0])
0
Usage | Description |
---|---|
miner.start() | Start mining |
Example:
> miner.start()
null
Usage | Description |
---|---|
miner.stop() | Stop mining |
Example:
> miner.stop()
null
Usage | Description |
---|---|
eth.mining | Check if the node is mining |
Example:
> eth.mining
false
Usage | Description |
---|---|
eth.blockNumber | Current block height |
Example:
> eth.blockNumber
12
Usage | Description |
---|---|
admin.peers | Number of nodes connected |
Example:
> admin.peers
[{
caps: ["eth/63", "eth/64"],
enode: "enode://fdac7145904eba296b91b21dbc2fb75c114ab3a4e2cf5076ea95ae278e142d9b40da8b7c061beb179523781b8d4207de69266862090ac7b24e3afa62e5bb9629@35.164.203.139:36000",
id: "578c262796d0c566e968cef804e502bbf16b8ae27af2bf8ac3b7cc10cfbd04ea",
name: "gdx/v0.7.0-unstable-b710fae7/linux-amd64/go1.11.1",
network: {
inbound: false,
localAddress: "192.168.0.109:50855",
remoteAddress: "35.164.203.139:36000",
static: true,
trusted: false
},
protocols: {
eth: {
difficulty: 1048576,
head: "0xfc27079037c07c16646518b7f5067ae5e07df0657c2e949ed84e0d6e2e4f7577",
version: 64
}
}
}]
Usage | Description |
---|---|
admin.nodeInfo | Detailed local node information |
Example:
> admin.nodeInfo
{
enode: "enode://72c61072be163425f780ce1c54bf62835116bf471e8c6551dfb5bdb16128ab546c3bab8fc0f820e090d5cb523ca3ad2bc1d88435e6ce3b1e095c9893ff5ac4a9@192.168.7.99:36000",
enr: "0xf89cb8403553c1046074ce413afdcd70e42429df7570c8c45855666b8f0a06af071503036e25b748834d8e7b3718dd50d02128a041b6fc1ad84b165019724d92e78a47220483636170ccc5836574683fc5836574684082696482763482697084c0a8076389736563703235366b31a10372c61072be163425f780ce1c54bf62835116bf471e8c6551dfb5bdb16128ab5483746370828ca083756470828ca0",
id: "6ae04b801cf80310b48a10b55fbb478bfb977e159e96ea3b0a9d0a52ae8164ec",
ip: "192.168.7.99",
listenAddr: "[::]:36000",
name: "gdx/v0.7.0-unstable-9437f7c7/darwin-amd64/go1.11.12",
ports: {
discovery: 36000,
listener: 36000
},
protocols: {
eth: {
config: {
byzantiumBlock: 0,
chainId: 1,
eip150Block: 0,
eip150Hash: "0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d",
eip155Block: 0,
eip158Block: 0,
ethash: {},
homesteadBlock: 0
},
difficulty: 13055408,
genesis: "0xfc27079037c07c16646518b7f5067ae5e07df0657c2e949ed84e0d6e2e4f7577",
head: "0x14eaa4d7901af0b65fb815ee8623c0ffd11f762a39f73a6b887284480c2ce6c5",
network: 1
}
}
}
NOTE: To be able to use the following commands, the storage client module must be enabled when you start the gdx
program. Otherwise, error will be returned.
Usage | Description |
---|---|
sclient.host.ls | Retrieve the available storage hosts |
Example:
> sclient.host.ls
[{
acceptingContracts: true,
baseRPCPrice: 100000000000,
contractPrice: 50000000000000000,
deposit: 1000,
downloadBandwidthPrice: 100000000,
enodeid: "578c262796d0c566e968cef804e502bbf16b8ae27af2bf8ac3b7cc10cfbd04ea",
enodeurl: "enode://fdac7145904eba296b91b21dbc2fb75c114ab3a4e2cf5076ea95ae278e142d9b40da8b7c061beb179523781b8d4207de69266862090ac7b24e3afa62e5bb9629@35.164.203.139:36000",
filtered: false,
firstseen: 15,
historicdowntime: 0,
historicfailedinteractions: 0,
historicsuccessfulinteractions: 0,
historicuptime: 0,
ip: "35.164.203.139",
ipnetwork: "35.164.203.0/24",
lasthistoricupdate: 0,
lastipnetworkchange: "2019-08-01T11:17:24.527496-07:00",
maxDeposit: 9000000000000000000,
maxDownloadBatchSize: 17825792,
maxDuration: 172800,
maxReviseBatchSize: 17825792,
nodepubkey: "BP2scUWQTropa5GyHbwvt1wRSrOk4s9QduqVrieOFC2bQNqLfAYb6xeVI3gbjUIH3mkmaGIJCseyTjr6YuW7lik=",
paymentAddress: "0x3c15440003892ad2a755459a66ccb3197234d7e2",
recentfailedinteractions: 0,
recentsuccessfulinteractions: 1,
remainingStorage: 0,
scanrecords: [{
success: true,
timestamp: "2019-08-01T11:07:24.576446-07:00"
}, {
success: true,
timestamp: "2019-08-01T11:17:24.576447-07:00"
}],
sectorAccessPrice: 10000000000000,
sectorSize: 4194304,
storagePrice: 1000,
totalStorage: 0,
uploadBandwidthPrice: 10000000,
version: "1.0.1",
windowSize: 1200
}]
NOTE: length can be attach to the end of the command to get number of storage hosts that the client learnt from the network. If error returned, meaning that there are no hosts available.
> sclient.host.ls.length
1
Usage | Description |
---|---|
sclient.paymentAddr | Retrieve the account used for storage service |
NOTE: By default, the first account user generated will be used as the storage service payment address. All the storage cost will be spent from this account.
Example:
> sclient.paymentAddr
"0x792e6b278ef8ec562b9530bf5df70064a55c3744"
Usage | Description |
---|---|
sclient.setPaymentAddr(address) | Register the account address to be used for the storage service |
Example:
> sclient.setPaymentAddr(eth.accounts[1])
true
Usage | Description |
---|---|
sclient.setConfig(config) | Configure the client settings used for contract creation and etc. |
The following is a list of supported configuration:
Config | Type | Description |
---|---|---|
period | Duration | file storage duration |
hosts | Number | number of storage hosts that the client want to sign contract with |
renew | Duration | time that the contract will automatically be renewed |
fund | Currency | amount of money the client wants to be used for the storage service within one period |
NOTE: units must be included when config the storage client configuration, please refer to Units for available units
Before setting the client config, please make sure that you have enough balance in your payment account. Please refer to 4.1.4. eth.getBalance to check balance.
In addition, the payment account must be permanently unlocked first. To unlock the account, please refer to 4.1.3. personal.unlockAccount
Example:
> sclient.setConfig({"fund":"1dx", "hosts":"3", "period":"2d", "renew":"36h"})
"Successfully set the storage client setting"
the following command uses the default settings
> sclient.setConfig({})
"Successfully set the storage client setting"
Default Setting:
Fund: 1 DX
Hosts: 3 Hosts
Renew: 36 Hours
Period: 2 Days
NOTE: once the client configuration is settled, the contracts will be automatically created.
Usage | Description |
---|---|
sclient.config | Current storage client settings used for the storage service |
Example:
> sclient.config
{
IP Violation Check Status: "Disabled: storage client can sign contract with storage hosts from the same network",
Max Download Speed: "Unlimited",
Max Upload Speed: "Unlimited",
RentPayment Setting: {
Expected Download: "578703 B/block",
Expected Redundancy: "2 Copies",
Expected Storage: "976562500 KiB",
Expected Upload: "1157407 B/block",
Fund: "1 DX",
Number of Storage Hosts: "3 Hosts",
Renew Time: "12 Hour(s)",
Storage Time: "3 Day(s)"
}
}
Usage | Description |
---|---|
sclient.contracts | Active storage contracts signed by the storage client |
Example:
> sclient.contracts
[{
AbleToRenew: true,
AbleToUpload: true,
Canceled: false,
ContractID: "0x527924bc4e7316382601662527dbc327a7854918bed725522a633bd383257df0",
HostID: "578c262796d0c566e968cef804e502bbf16b8ae27af2bf8ac3b7cc10cfbd04ea"
}]
to get the number of contracts that the storage client signed
> sclient.contracts.length
1
Usage | Description |
---|---|
sclient.contract(contractID) | Detailed contract information based on the provided contract ID |
Example:
> sclient.contract("0x527924bc4e7316382601662527dbc327a7854918bed725522a633bd383257df0")
{
Canceled: "the contract is still active",
ContractBalance: "0.06111111111111111 DX",
ContractFee: "0.05 DX",
DownloadCost: "0 Camel",
EndHeight: "17843 b",
EnodeID: "578c262796d0c566e968cef804e502bbf16b8ae27af2bf8ac3b7cc10cfbd04ea",
GasCost: "0 Camel",
ID: "0x527924bc4e7316382601662527dbc327a7854918bed725522a633bd383257df0",
LatestContractRevision: {
Signatures: ["BUl14sSzxbciCt4Wg/9ouy80qygRRQIKbDwGOfG/MxtnDh5m2b+ENR+hqCglInyTDdsO6/vqwoaimFves2jUMgA=", "Seh6lPZTnp8yI0bjc3x44gIgnu+dcgj4aonMV6gF0Ap21qCMMhqino2ueghtVbZyILANAkhdbwW36TgggL0g1gA="],
newfilemerkleroot: "0x0000000000000000000000000000000000000000000000000000000000000000",
newfilesize: 0,
newmissedproofoutputs: [{
Address: "0x792e6b278ef8ec562b9530bf5df70064a55c3744",
Value: 61111111111111110
}, {
Address: "0x3c15440003892ad2a755459a66ccb3197234d7e2",
Value: 111111111111111000
}],
newrevisionnumber: 1,
newunlockhash: "0x2f58aa5ab70e1d6844d829948070b34b5f4bcf93cdc66dac72bf8e3b6ae56f26",
newvalidproofoutputs: [{
Address: "0x792e6b278ef8ec562b9530bf5df70064a55c3744",
Value: 61111111111111110
}, {
Address: "0x3c15440003892ad2a755459a66ccb3197234d7e2",
Value: 111111111111111000
}],
newwindowend: 19043,
newwindowstart: 17843,
parentid: "0x527924bc4e7316382601662527dbc327a7854918bed725522a633bd383257df0",
unlockconditions: {
paymentaddress: ["0x792e6b278ef8ec562b9530bf5df70064a55c3744", "0x3c15440003892ad2a755459a66ccb3197234d7e2"],
signaturesrequired: 2
}
},
RenewAbility: "the contract can be used for data downloading",
StartHeight: "563 b",
StorageCost: "0 Camel",
TotalCost: "0.1111111111111111 DX",
UploadAbility: "the contract can be used for data uploading",
UploadCost: "0 Camel"
}
Usage | Description |
---|---|
sclient.upload(source, destination) | Upload the file specified by the storage client to storage hosts |
NOTE: both source and destination path must be absolute path
Example:
> sclient.upload("/Users/mzhang/upload1.file", "download.file")
"success"
Usage | Description |
---|---|
sclient.download(source, destination) | Download the file specified by the client to the local machine |
NOTE: both source and destination path must be absolute path
Example:
> sclient.download("download.file", "download.file")
"File downloaded successfully"
Usage | Description |
---|---|
sclient.file.ls | Files uploaded by the storage client |
Example:
> sclient.file.ls
[{
dxpath: "download.file",
status: "healthy",
uploadProgress: 100
}]
Usage | Description |
---|---|
sclient.file.rename(oldName, newName) | Rename the file uploaded |
Example:
> sclient.file.rename("download.file", "newfile.file")
"File download.file renamed to newfile.file"
Usage | Description |
---|---|
sclient.file.delete(file) | Delete the file |
Example:
> sclient.file.delete("newfile.file")
"File newfile.file deleted"
NOTE: To be able to use the following commands, the storage host module must be enabled when you start the gdx
program. Otherwise, error will be returned.
Usage | Description |
---|---|
shost.config | Storage host configurations used for storage service |
NOTE: if the configuration is not set, default configuration will be used.
Example:
> shost.config
{
acceptingContracts: "false",
baseRPCPrice: "100 Gcamel",
contractPrice: "0.05 DX/contract",
deposit: "1000 Camel/byte/block",
depositBudget: "10000 DX/contract",
downloadBandwidthPrice: "0.1 Gcamel/byte",
maxDeposit: "100 DX",
maxDownloadBatchSize: "17 MiB/block",
maxDuration: "1 Month(s)",
maxReviseBatchSize: "17 MiB/block",
paymentAddress: "0x0000000000000000000000000000000000000000",
sectorAccessPrice: "10000 Gcamel/sector",
storagePrice: "1000 Camel/byte/block",
uploadBandwidthPrice: "0.01 Gcamel/byte",
windowSize: "5 Hour(s)"
}
Usage | Description |
---|---|
shost.setConfig(config) | Set the storage host configurations |
The following is a list of available configurations:
Config | Type | Description |
---|---|---|
acceptingContracts | Boolean | whether the host accepts new contracts |
maxDuration | Duration | max duration for a storage contract |
deposit | Currency | deposit price per block per byte |
contractPrice | Currency | price that client must be paid when creating contract |
downloadPrice | Currency | download bandwidth price per byte |
uploadPrice | Currency | upload bandwidth price per byte |
storagePrice | Currency | storage price per block per byte |
depositBudget | Currency | the maximum deposit for all contracts |
maxDeposit | Currency | the max deposit for a single storage contract |
paymentAddress | Address | account address used for the storage service |
NOTE for available units, please refer to Units
Example:
> shost.setConfig({"acceptingContracts":"true", "deposit":"2gcamel"})
"Successfully set the host config"
Usage | Description |
---|---|
shost.paymentAddr | Retrieve the account used for storage service |
NOTE: By default, the first account user generated will be used as the storage service payment address. All the storage cost will be spent from this account. All the profit will be saved in this account as well
Example:
> shost.paymentAddr
"0x792e6b278ef8ec562b9530bf5df70064a55c3744"
Usage | Description |
---|---|
shost.announce | Announce the node as storage host node |
NOTE: there is no limitation on number of announcements. However, each announcement will cost a small amount of transaction fee. Before making announcement, please make sure that you have enough balance in your payment account. Please refer to 4.1.4. eth.getBalance to check balance.
In addition, the payment account must be permanently unlocked first. To unlock the account, please refer to 4.1.3. personal.unlockAccount
Example:
> shost.announce()
"Announcement transaction: 0x3e3466bab9476d997ab4fc8a8a68c0893ecd373646e6bbc98137cd343b169881"
to check the transaction detail, use the following command
> eth.getTransaction("0x3e3466bab9476d997ab4fc8a8a68c0893ecd373646e6bbc98137cd343b169881")
{
blockHash: "0xcd3f13a85c129ebc4d77d4b3c65db7a37921e3c16d40e816daf0cacb32e6191f",
blockNumber: 1745,
from: "0x792e6b278ef8ec562b9530bf5df70064a55c3744",
gas: 90000,
gasPrice: 1000000000,
hash: "0x3e3466bab9476d997ab4fc8a8a68c0893ecd373646e6bbc98137cd343b169881",
input: "0xf8e0b89b656e6f64653a2f2f3936333438326236643764353433623335316439396464633833373031336166336239646438363230346465623930313165306663363561656163383039666137353833663061633063323261366262633364383861343262346430346266373262326265373635653039653164643763313664396237646432623563336166403139322e3136382e372e39393a3336303030b8415978fcb1e3d366450f1dfde82a8aab4e1dc5c8675f79314dc0a6f13ebfe007bd73e5e16c92323f32d073e09404889ad8939c3b0e35b3bfa536b80a3d93dc645a00",
nonce: 2,
r: "0xc579aa9e6bbcbf7e466c39d8d077a5b9d5c1de73f9a4a598689c88eb6869ae74",
s: "0xf980116eb2a47fc7f18054fd87bcdbef8dc8f67b7eb2b17a283d744e2704951",
to: "0x0000000000000000000000000000000000000009",
transactionIndex: 0,
v: "0x25",
value: 0
}
Usage | Description |
---|---|
shost.folder.add(path, size) | Allocate disk space for saving data uploaded by the storage client |
NOTE: for supported storage size unit, please refer to Units
Example:
> shost.folder.add("~/temp", "1gb")
"successfully added the storage folder"
Usage | Description |
---|---|
shost.folder.ls | Information of folders created for storing data uploaded by client |
Example:
> shost.folder.ls
[{
path: "/Users/mzhang/temp",
totalSectors: 238,
usedSectors: 0
}]
Usage | Description |
---|---|
shost.folder.resize(folder, size) | Resize the disk space allocated for saving data uploaded by the storage client |
Example:
> shost.folder.resize("/Users/mzhang/temp", "500mb")
"successfully resize the storage folder"
Usage | Description |
---|---|
shost.folder.delete(folder) | Free up the disk space used for saving data uploaded by the storage client |
NOTE: this command will not delete the directory created on your local machine
Example:
> shost.folder.delete("/Users/mzhang/temp")
"successfully delete the storage folder"
GoDx is released under the Apache 2.0 License. See LICENSE for more information.
Duration:
Duration/Time | Representation |
---|---|
b | block |
h | hour |
d | day |
w | week |
m | month |
y | year |
Currency:
Currency | Transfer Rate |
---|---|
camel | smallest currency unit |
Gcamel | 1e9 camel |
DX | 1e18 camel |
Storage Size:
Storage Size | Representation |
---|---|
kb | 1e3 bytes |
mb | 1e6 bytes |
gb | 1e9 bytes |
tb | 1e12 bytes |
kib | 1 << 10 bytes |
mib | 1 << 20 bytes |
gib | 1 << 30 bytes |
tib | 1 << 40 bytes |
- To form a bug report, Bug Report Template must be followed
- To request a new feature, Feature Request Template must be followed
- To submit a pull request, Pull Request Template must be followed
Contribution is welcome, see Contributing for more details
Thank you so much for your support and your confidence in this project. If you have any question, please do not hesitated to contact us via support@dxchain.com