Donate via Zerocracy

EO principles respected here Managed by Zerocracy DevOps By Rultor.com We recommend RubyMine

Build Status Build status PDD status Gem Version Test Coverage

Yard Docs Maintainability

NOTICE: It's an experiment and a very early draft! Please, feel free to submit your ideas and/or pull requests.

Here is the White Paper.

Join our Telegram group to discuss it all live.

The license is MIT.

The web wallet is here: wts.zold.io.

How to Use

First, install Ruby 2.3+, Rubygems, and the gem. Here is how.

To make sure it's installed, try:

$ zold --help

You will need RSA private and public keys in ~/.ssh. If you don't have them yet, run this in order to generate a new pair (just hit Enter when it asks you for a password):

$ ssh-keygen -t rsa -b 4096

Then, create a new wallet (instead of 5f96e731e48ae21f there will be your personal wallet ID, use it everywhere below):

$ zold create
5f96e731e48ae21f

Then, push it to the network:

$ zold push 5f96e731e48ae21f

Then, give this ID to your friend, who is going to pay you. When the payment is sent, ask him or her for the ID of the wallet the payment has been sent from and then fetch that wallet (let's say it is 5555444433332222):

$ zold fetch 5555444433332222
5.00 ZLD added to 5f96e731e48ae21f: To my friend!

Now, you have the money in your wallet!

Next, you can pay your friend back:

$ zold pay 5f96e731e48ae21f 5555444433332222 2.50 'Here is a refund'
-2.50 ZLD added to 5f96e731e48ae21f: Here is a refund

Finally, you have to push your wallet to the network so that your friend knows about the payment:

$ zold push 5f96e731e48ae21f

That's it.

How to Start a Node

You also can contribute to Zold by running a node on your server. In order to do that just run (with your own wallet ID, of course):

$ zold node --invoice=5f96e731e48ae21f

Then, open the page localhost:4096 in your browser (you may need to open the inbound port at your IP firewall). If you see a simple JSON document, everything is fine. Next, hit Ctrl+c and run it again, but with --nohup:

$ zold node --nohup --invoice=5f96e731e48ae21f

Now you can close the console; the software will work in the background, saving the output logs to zold.log. The software will update itself automatically to new versions. The software will never stop, even if it crashes internally with any error. In order to terminate it forcefully, do:

$ killall -9 zold

Grateful users of the system will pay "taxes" to your wallet for the maintenance of their wallets, and the system will occasionally send you bonuses for keeping the node online (approximately 1 ZLD per day).

If you are lost, run this:

$ zold node --help

You can run a node in a docker container also, using yegor256/zold built from this Dockerfile.

docker run -d -p 4096:4096 yegor256/zold /node.sh --host=<your host IP> --invoice=5f96e731e48ae21f

To store zold data between container restarts create a volume or bind a directory from host:

docker volume create zold
docker run -d -p 4096:4096 -v zold:/zold yegor256/zold /node.sh --host=<your host IP> --invoice=5f96e731e48ae21f

You may find this blog post useful: How to Run Zold Node?

If Your File System is on Fire (or How to Reduce Your Hard Disk Usage)

At the moment, the file system is utilised too aggressively and if you like to calm this process down and have a bit of spare memory, you may find the following approach handy (directly applicable to FreeBSD OS).

The application data can be moved to a memory-backed memory disk with a periodical syncing of farm, zold.log and .zolddata to the hard disk.

The /etc/fstab entry:

md /usr/home/zold/app-in-mem mfs rw,-M,-n,-s512m,-wzold:zold,-p0755 2 0

The /etc/crontab entry:

*/10    *       *       *       *       zold    /usr/local/bin/rsync -aubv /usr/home/zold/app-in-mem/farm /usr/home/zold/app-in-mem/zold.log /usr/home/zold/app-in-mem/.zoldata /usr/home/zold/app/

Frequently Asked Questions

Where are my RSA private/public keys?

They are in ~/.ssh/id_rsa (private key) and ~/.ssh/id_rsa.pub (public key). Make sure you have a copy of your private key in some safe place. If you lose the public key, it's not a problem, since your wallet has it. But the private key is your personal asset. Anyone can use your wallet if they have the private key. Keep it safe and secure!

What is the best way to check the balance of the rewards collected by nodes?

You just do zold pull <Wallet_ID> and the rewards (taxes) will be visible there.

Can I setup multiple nodes with one wallet address?

Yes, you can run many nodes with the same wallet ID.

Is there a way to increase the number of threads in order to maximize computing power of multiple core machines?

Yes, you can use --threads command line argument for your node and the number of threads will be as big as you wish.

JSON Details

When you open up the front web page of your node, you will see a JSON document with a lot of technical details. Here is the explanation of the majority of them:

version is the current version of the running software. The node is supposed to update update itself automatically (if you run it via zold-nohup) every time it discovers another node with a higher version.

network is the name of the network the node belongs to. The production network's name is zold. For testing purposes you can start a node in a test network, using --network=test.

score is the current score your node is exposing to the network now. All other nodes are using this information in order to decide how much they can trust your node with the information it provides, about wallets. The higher the score, the better.

  • value is the amount of suffixes the score contains; this is the number all other nodes rely on.

  • host is the host name of the node, it must be equal to the public IP or domain name of the node; it is provided in --host command line option of zold-nohup.

  • port is the TCP port number, which usually is equal to 4096; it is provided in --port command line option.

  • invoice is the address of your wallet, where the system will send you rewards for keeping the node online and some users will pay taxes; it is provided in --invoice command line option.

  • time is the ISO-8601 UTC date and time of when your node started to calculate the score.

  • strength is the amount of tailing zeros the hash contains.

  • hash is the SHA-256 hash of the score text.

  • minutes is the age of the score, in minutes since the moment it was created.

pid is the Unix process ID of the running software.

cpus is the amount of CPUs detected on the server.

threads is the amount of running threads vs. the total amount of threads in the Ruby process. If the second number is over 100 there is definitely something wrong with the software.

wallets is the total number of wallets managed by the server. The bigger the number, the better. When the server starts, the number is small and it starts growing when other nodes are pushing wallets to your node.

remotes is the total number of remote nodes your node is aware of. The bigger the number, the more "connected" your node is to the network. You can see the full list of nodes at /remotes URL of your node.

farm is the score calculating software.

  • threads is the amount of threads this software module is using. This number is configured via the --threads command line option. The bigger the number, the more intensively the software will use your CPUs. It is recommended to make this number equal to the number of CPUs available.

  • pipeline is ... something not important to you.

  • best is the list of scores known to the farm at the moment (with their ages in minutes).

entrance is the place where all new wallets arive and get merged and pushed further. The health of this point is critical to the entire node. Some numbers it includes must be watched carefully.

To be continued...

date is the current date and time on the server.

hours_alive is the time in hours your server is alive without a reboot.

SDK

Here is how you use Zold SDK from your Ruby app. First, you should add zold gem to your Gemfile or just:

$ gem install zold

Then, you will need a directory where wallets and other supplementary data will be kept. This can be any directory, including a temporary one. If it doesn't exist, it will automatically be created:

home = '/tmp/my-zold-dir'

Then, you need to create three objects:

require 'zold/wallets'
require 'zold/sync_wallets'
require 'zold/remotes'
wallets = Zold::SyncWallets.new(Zold::Wallets.new(home))
remotes = Zold::Remotes.new(File.join(home, 'remotes'))
copies = File.join(home, 'copies')

The first step is to update the list of remote nodes, in order to be properly connected to the network:

require 'zold/commands/remote'
Zold::Remote.new(remotes: remotes).run(['remote', 'update'])

Now you are ready to create a wallet:

require 'zold/commands/create'
Zold::Create.new(wallets: wallets, remotes: remotes).run(
  ['create', '--public-key=/tmp/id_rsa.pub', '--skip-test']
)

Here --public-key=/tmp/id_rsa.pub points to the absolute location of a public RSA key for the wallet you want to create.

You can also pull a wallet from the network:

require 'zold/commands/pull'
Zold::Pull.new(wallets: wallets, remotes: remotes, copies: copies).run(['pull', '00000000000ff1ce'])

Then, you can make a payment:

require 'zold/commands/pay'
Zold::Pay.new(wallets: wallets).run(
  ['pay', '17737fee5b825835', '00000000000ff1ce', '19.99', 'For a pizza', '--private-key=/tmp/id_rsa']
)

Here --private-key=/tmp/id_rsa points to the absolute location of the private RSA key of the paying wallet.

Finally, you can push a wallet to the network:

require 'zold/commands/push'
Zold::Push.new(wallets: wallets, remotes: remotes).run(%w[push 17737fee5b825835])

By default, all commands will work quietly, reporting absolutely nothing to the console. To change that, you can use log argument of their constructors. For example, Zold::Log::Verbose will print a lot of information to the console:

require 'zold/commands/push'
Zold::Push.new(wallets: wallets, remotes: remotes, log: Zold::Log::VERBOSE).run(['push'])

Also, all commands by default assume that you are working in a test network. This is done in order to protect our production network from your test cases. In order to instruct them to deal with real data and real nodes, you should give them --network=zold argument, for example:

require 'zold/commands/push'
Zold::Push.new(wallets: wallets, remotes: remotes).run(%w[push 17737fee5b825835 --network=zold])

If anything doesn't work as explained above, please submit at ticket or join our Telegram group and complain there.

How to Contribute

It is a Ruby command line gem. First, install Ruby 2.3+, Rubygems, and Bundler. Then:

$ bundle update
$ bundle exec rake

The build has to be clean. If it's not, submit an issue.

Then, make your changes, make sure the build is still clean, and submit a pull request.

If some test fails and you need to run it individually, check the logging configuration inside test__helper.rb and make sure the Verbose log is assigned to $log. Then, run, for example:

$ ruby test/commands/test_node.rb

If you need to run a single test method, do this:

$ ruby test/test_wallet.rb -n test_adds_transaction