Merge repository tezos-modded

This commit is contained in:
Georges Dupéron 2019-05-27 11:57:15 +02:00
commit 681fe53dd6
1393 changed files with 218367 additions and 0 deletions

50
vendors/tezos-modded/.dockerignore vendored Normal file
View File

@ -0,0 +1,50 @@
## /!\ /!\ Update .gitignore accordingly /!\ /!\
.DS_Store
__pycache__
**/*.pyc
_build
_opam
_docker_build
docs/_build
docs/api/tezos-client.html
docs/api/tezos-admin-client.html
tezos-node
tezos-protocol-compiler
tezos-client
tezos-admin-client
tezos-baker-*
tezos-endorser-*
tezos-accuser-*
tezos-signer
scripts/opam-test-all.sh.DONE
scripts/create_genesis/src
docs/introduction/readme.rst
docs/api/errors.rst
docs/api/rpc.rst
docs/api/p2p.rst
src/bin_client/test/LOG.*
**/dune-project
**/*.install
**/.merlin
**/*~
**/\#*\#
**/*.rej
**/*.orig
## Not in .gitignore
.git
.gitignore
.gitlab-ci.yml

4
vendors/tezos-modded/.gitattributes vendored Normal file
View File

@ -0,0 +1,4 @@
.gitignore export-ignore
.gitattributes export-ignore
.gitlab-ci.yml export-ignore
src/lib_base/current_git_info.ml export-subst

View File

@ -0,0 +1 @@
../.gitlab/issue_templates/issues.md

48
vendors/tezos-modded/.gitignore vendored Normal file
View File

@ -0,0 +1,48 @@
## /!\ /!\ Update .dockerignore accordingly /!\ /!\
.DS_Store
__pycache__
*.pyc
/_build
**/_build
/_opam
/_docker_build
/docs/_build
/docs/api/tezos-client.html
/docs/api/tezos-admin-client.html
/tezos-node
/tezos-protocol-compiler
/tezos-client
/tezos-admin-client
/tezos-baker-*
/tezos-endorser-*
/tezos-accuser-*
/tezos-signer
/scripts/opam-test-all.sh.DONE
/scripts/create_genesis/src
/docs/introduction/readme.rst
/docs/api/errors.rst
/docs/api/rpc.rst
/docs/api/p2p.rst
/src/bin_client/test/LOG.*
dune-project
*.install
.merlin
*~
\#*\#
[._]*.s[a-v][a-z]
[._]*.sw[a-p]
[._]s[a-rt-v][a-z]
[._]ss[a-gi-z]
[._]sw[a-p]
*.rej
*.orig

38
vendors/tezos-modded/.gitlab-ci.yml vendored Normal file
View File

@ -0,0 +1,38 @@
before_script:
- apt-get update -qq
# rsync is needed by opam to sync a package installed from a local directory with the copy in ~/.opam
- apt-get -y -qq install rsync libhidapi-dev libcap-dev libev-dev bubblewrap
- wget https://github.com/ocaml/opam/releases/download/2.0.1/opam-2.0.1-x86_64-linux -O opam-2.0.1-x86_64-linux
- cp opam-2.0.1-x86_64-linux /usr/local/bin/opam
- chmod +x /usr/local/bin/opam
- export PATH="/usr/local/bin${PATH:+:}${PATH:-}"
- echo "$PATH"
- printf '' | opam init
- eval $(opam config env)
- printf '' | opam switch create toto ocaml-base-compiler.4.06.1
- eval $(opam config env)
- opam repository add new-tezos-opam-repository https://gitlab.com/ligolang/new-tezos-opam-repository.git
- eval $(opam config env)
# Show versions and current switch
- opam --version
- printf '' | ocaml
- opam switch
default-job:
script:
- (cd src/lib_utils && opam install -y --build-test --working-dir .)
- (cd src/ligo && opam install -y --build-test --working-dir .)
- (cd src/ligo && dune build && dune build -p ligo && dune build @ligo-test)
artifacts:
paths:
- src/ligo/bin/cli.ml
install-from-repo-job:
script:
- opam install -y ligo
# Used in the IDE
#- opam install -y user-setup
#- opam install -y merlin
#- opam install -y ocp-indent
#- opam user-setup install

View File

@ -0,0 +1,56 @@
Before submitting your issue, ask this question: is this a bug in the Tezos codebase or a personal problem for which you need support? Here are a few examples of each:
Personal problem:
* Lost or compromised key
* Fundraiser issues
* Questions about how to use Tezos
* Feature requests
* Questions about the state of development
These sorts of questions should be asked on the [riot chat](https://riot.im/app/#/room/#tezos:matrix.org). People there will be happy to assist you.
Bugs:
* Crashes or exceptions in the node
* Defaults that cause failures
* Missing documentation
* Build failures
Make sure to give your issue a descriptive title. We should get the general idea of the problem just from reading the title. Avoid words like "weird", "strange", and "unexpected". Instead, spell out the strange behavior in as much detail as possible. As an example, "Michelson: lists are reversed" is significantly better than "List handling is weird". Unless your investigations have revealed the source of the bug, do not speculate on its cause or severity. The easier it is for us to understand your bug the easier it is for us to fix.
### Environment (Alphanet, build from source, or both)
Please specify the version of the code you were running when the bug appeared.
If you've built the program from source, you can find the commit hash via the following command:
`git log -1 --format=format:%H`
If you're running the alphanet, the status output is extremely useful:
`./alphanet.sh status`
### Expected behavior
What you expected to happen.
### Actual behavior
What actually happened.
### Steps to reproduce
Please provide the command that led to the issue. Copy and paste the command line and the output into the issue and attach any files we'll need to reproduce the bug. Screenshots are much harder to deal with because we cannot rerun your commands or see the entire setup.
Whenever possible, provide the smallest amount of code needed to produce the bug dependably. If you cannot reproduce the bug, we likely will not be able to either.
If you had a problem while trying to build Tezos from source, please include the output of `opam list -i` and any error messages that you saw while building. If you ran a second command which fixed the problem, provide us with the error you saw initially in addition to telling us how you fixed the bug.
### Logs
Please include logs with your bug report whenever possible.
On the alphanet, you can access the log from the node, baker, and endorser using the following commands:
* `./alphanet.sh node log`
* `./alphanet.sh baker log`
* `./alphanet.sh endorser log`
If you've encountered the bug when using the sandboxed node initialization scripts, there should be a file in the directory called `LOG.N`, where `N` is the number with which you started the node. Please attach that log to the bug report.

1
vendors/tezos-modded/.ocp-indent vendored Normal file
View File

@ -0,0 +1 @@
match_clause = 4

20
vendors/tezos-modded/LICENSE vendored Normal file
View File

@ -0,0 +1,20 @@
Open Source License
Copyright (c) 2018 Dynamic Ledger Solutions, Inc. <contact@tezos.com>
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.

119
vendors/tezos-modded/Makefile vendored Normal file
View File

@ -0,0 +1,119 @@
PACKAGES:=$(patsubst %.opam,%,$(notdir $(shell find src vendors -name \*.opam -print)))
active_protocol_versions := $(shell cat active_protocol_versions)
active_protocol_directories := $(shell tr -- - _ < active_protocol_versions)
current_opam_version := $(shell opam --version)
include scripts/version.sh
ifeq ($(filter ${opam_version}.%,${current_opam_version}),)
$(error Unexpected opam version (found: ${current_opam_version}, expected: ${opam_version}.*))
endif
current_ocaml_version := $(shell opam exec -- ocamlc -version)
all: generate_dune
ifneq (${current_ocaml_version},${ocaml_version})
$(error Unexpected ocaml version (found: ${current_ocaml_version}, expected: ${ocaml_version}))
endif
@dune build \
src/bin_node/main.exe \
src/bin_client/main_client.exe \
src/bin_client/main_admin.exe \
src/bin_signer/main_signer.exe \
src/lib_protocol_compiler/main_native.exe \
$(foreach p, $(active_protocol_directories), src/proto_$(p)/bin_baker/main_baker_$(p).exe) \
$(foreach p, $(active_protocol_directories), src/proto_$(p)/bin_endorser/main_endorser_$(p).exe) \
$(foreach p, $(active_protocol_directories), src/proto_$(p)/bin_accuser/main_accuser_$(p).exe)
@cp _build/default/src/bin_node/main.exe tezos-node
@cp _build/default/src/bin_client/main_client.exe tezos-client
@cp _build/default/src/bin_client/main_admin.exe tezos-admin-client
@cp _build/default/src/bin_signer/main_signer.exe tezos-signer
@cp _build/default/src/lib_protocol_compiler/main_native.exe tezos-protocol-compiler
@for p in $(active_protocol_directories) ; do \
cp _build/default/src/proto_$$p/bin_baker/main_baker_$$p.exe tezos-baker-`echo $$p | tr -- _ -` ; \
cp _build/default/src/proto_$$p/bin_endorser/main_endorser_$$p.exe tezos-endorser-`echo $$p | tr -- _ -` ; \
cp _build/default/src/proto_$$p/bin_accuser/main_accuser_$$p.exe tezos-accuser-`echo $$p | tr -- _ -` ; \
done
PROTOCOLS := genesis alpha demo
DUNE_INCS=$(patsubst %,src/proto_%/lib_protocol/dune.inc, ${PROTOCOLS})
generate_dune: ${DUNE_INCS}
${DUNE_INCS}:: src/proto_%/lib_protocol/dune.inc: \
src/proto_%/lib_protocol/TEZOS_PROTOCOL
dune build @$(dir $@)/runtest_dune_template --auto-promote
touch $@
all.pkg: generate_dune
@dune build \
$(patsubst %.opam,%.install, $(shell find src vendors -name \*.opam -print))
$(addsuffix .pkg,${PACKAGES}): %.pkg:
@dune build \
$(patsubst %.opam,%.install, $(shell find src vendors -name $*.opam -print))
$(addsuffix .test,${PACKAGES}): %.test:
@dune build \
@$(patsubst %/$*.opam,%,$(shell find src vendors -name $*.opam))/runtest
doc-html: all
@dune build @doc
@./tezos-client -protocol ProtoALphaALphaALphaALphaALphaALphaALphaALphaDdp3zK man -verbosity 3 -format html | sed "s#${HOME}#\$$HOME#g" > docs/api/tezos-client.html
@./tezos-admin-client man -verbosity 3 -format html | sed "s#${HOME}#\$$HOME#g" > docs/api/tezos-admin-client.html
@./tezos-signer man -verbosity 3 -format html | sed "s#${HOME}#\$$HOME#g" > docs/api/tezos-signer.html
@./tezos-baker-alpha man -verbosity 3 -format html | sed "s#${HOME}#\$$HOME#g" > docs/api/tezos-baker-alpha.html
@./tezos-endorser-alpha man -verbosity 3 -format html | sed "s#${HOME}#\$$HOME#g" > docs/api/tezos-endorser-alpha.html
@./tezos-accuser-alpha man -verbosity 3 -format html | sed "s#${HOME}#\$$HOME#g" > docs/api/tezos-accuser-alpha.html
@mkdir -p $$(pwd)/docs/_build/api/odoc
@rm -rf $$(pwd)/docs/_build/api/odoc/*
@cp -r $$(pwd)/_build/default/_doc/* $$(pwd)/docs/_build/api/odoc/
@${MAKE} -C docs html
doc-html-and-linkcheck: doc-html
@${MAKE} -C docs all
build-test:
@dune build @buildtest
test:
@dune runtest
@./scripts/check_opam_test.sh
test-indent:
@dune build @runtest_indent
fix-indent:
@src/lib_stdlib/test-ocp-indent.sh fix
build-deps:
@./scripts/install_build_deps.sh
build-dev-deps:
@./scripts/install_build_deps.sh --dev
docker-image:
@./scripts/create_docker_image.sh
install:
@dune build @install
@dune install
uninstall:
@dune uninstall
clean:
@-dune clean
@-rm -f \
tezos-node \
tezos-client \
tezos-signer \
tezos-admin-client \
tezos-protocol-compiler \
$(foreach p, $(active_protocol_versions), tezos-baker-$(p) tezos-endorser-$(p) tezos-accuser-$(p))
@-${MAKE} -C docs clean
@-rm -f docs/api/tezos-{baker,endorser,accuser}-alpha.html docs/api/tezos-{admin-,}client.html docs/api/tezos-signer.html
.PHONY: all test build-deps docker-image clean

47
vendors/tezos-modded/README.md vendored Normal file
View File

@ -0,0 +1,47 @@
Tezos
=====
The Project
-----------
Tezos is a distributed consensus platform with meta-consensus
capability. Tezos not only comes to consensus about the state of its ledger,
like Bitcoin or Ethereum. It also attempts to come to consensus about how the
protocol and the nodes should adapt and upgrade.
- Developer documentation is available online at http://tezos.gitlab.io/master
always in sync with the master branch (which may be desynchronized with
the code running on the live networks, replace `master` in the URL by the
branch of your choice: mainnet, alphanet, zeronet, to make sure you are
consulting the right API version)
- The website https://tezos.com/ contains more information about the project.
- All development happens on GitLab at https://gitlab.com/tezos/tezos
The source code of Tezos is placed under the MIT Open Source License.
The Community
-------------
- Several community built block explorers are available:
- http://tzscan.io
- https://tezos.id
- https://tezex.info
- A few community run websites collect useful Tezos links:
- https://www.tezos.help
- https://tezos.rocks
- There is a matrix channel *Tezos* that you can join `here <https://riot.im/app/#/room/#tezos:matrix.org>`_.
- There is a sub-reddit at https://www.reddit.com/r/tezos/
- There is also a community FAQ at https://github.com/tezoscommunity/faq/wiki/Tezos-Technical-FAQ
- There is a *#tezos* IRC channel on *freenode* that is reserved for technical discussions
The Networks
------------
The Tezos Alpha (test) network has been live and open since February 2017.
The Tezos Beta (experimental) network has been live and open since June 2018.

View File

@ -0,0 +1 @@
alpha

42
vendors/tezos-modded/docs/Makefile vendored Normal file
View File

@ -0,0 +1,42 @@
# You can set these variables from the command line.
SPHINXOPTS = -aE -n
SPHINXBUILD = sphinx-build
SPHINXPROJ = Tezos
SOURCEDIR = .
BUILDDIR = _build
DOCGENDIR = doc_gen
DOCERRORDIR = $(DOCGENDIR)/errors
DOCRPCDIR = $(DOCGENDIR)/rpcs
all: html linkcheck
linkcheck:
$(SPHINXBUILD) -b linkcheck "$(SOURCEDIR)" "$(BUILDDIR)"
api/errors.rst: $(DOCERRORDIR)/error_doc.ml
@cd .. && dune build docs/$(DOCERRORDIR)/error_doc.exe
../_build/default/docs/$(DOCERRORDIR)/error_doc.exe > api/errors.rst
$(DOCGENDIR)/rpc_doc.exe:
@cd .. && dune build docs/$(DOCGENDIR)/rpc_doc.exe
api/rpc.rst: $(DOCGENDIR)/rpc_doc.exe
@dune exec $(DOCGENDIR)/rpc_doc.exe > api/rpc.rst
$(DOCGENDIR)/p2p_doc.exe:
@cd .. && dune build docs/$(DOCGENDIR)/p2p_doc.exe
api/p2p.rst: $(DOCGENDIR)/p2p_doc.exe api/p2p_usage.rst.inc
@dune exec $(DOCGENDIR)/p2p_doc.exe < api/p2p_usage.rst.inc > api/p2p.rst
.PHONY: help Makefile
# Catch-all target: route all unknown targets to Sphinx using the new
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
html: Makefile api/errors.rst api/rpc.rst api/p2p.rst
@$(SPHINXBUILD) -b html "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS)
clean:
@-rm -Rf "$(BUILDDIR)"
@-rm -Rf api/errors.rst api/rpc.rst

64
vendors/tezos-modded/docs/README.rst vendored Normal file
View File

@ -0,0 +1,64 @@
******************************
Building documentation locally
******************************
The documentation is available online at `tezos.gitlab.io <http://tezos.gitlab.io/master/>`_,
always up to date with master on `GitLab <https://gitlab.com/tezos/tezos>`_.
Building instructions
---------------------
To build the documentation, you can use the main Makefile target ``doc-html``
.. code:: bash
make doc-html
The documentation is built by Sphinx, and uses the Read The Docs theme.
On a debian system, you can install the needed dependencies with:
.. code:: bash
sudo apt install \
python3-recommonmark \
python3-sphinx \
python3-sphinx-rtd-theme
Sphinx extensions
-----------------
Some ad-hoc reference kinds are supported.
- ``:package-src:`name``` or ``:package-src:`text<name>``` points
to the gitlab source tree viewer where the `.opam` for the package
is located
- ``:package:`name``` or ``:package:`text<name>``` now points
either to the `odoc` page, or if it doesn't exist, to the gitlab
source tree viewer
- ``:package-name:`name``` or ``:package-name:`text<name>``` just
displays the package name (no link), checking that the package
exists
- ``:src:`/path/to/file/or/dir``` or
``:src:`text</path/to/file/or/dir>``` points to the gitlab source
tree viewer
- ``:opam:`package``` or ``:opam:`text<package>``` points to the
package page on ``opam.ocaml.org``, version number is supported
(``package.version``)
OCaml documentation
-------------------
Odoc is used for OCaml API generation, that you can install with:
.. code:: bash
opam install odoc
Tezos generates the API documentation for all libraries in HTML format. The
generated HTML pages in ``_build/<context>/_doc``. It creates one sub-directory
per public library and generates an ``index.html`` file in each sub-directory.
The documentation is not installed on the system by Tezos. It is meant to be
read locally while developing and then published on the www when releasing
packages.

View File

@ -0,0 +1,77 @@
from docutils import nodes
import os
import os.path
import re
def setup(app):
app.add_role('package', package_role)
app.add_role('package-name', package_role)
app.add_role('package-src', package_role)
app.add_role('opam', opam_role)
app.add_role('src', src_role)
def find_dot_opam(name):
for path, dirs, files in os.walk('..'):
for file in files:
if file == name + '.opam':
return path.lstrip('../')
raise ValueError('opam file ' + name + '.opam does not exist in the odoc')
def package_role(name, rawtext, text, lineno, inliner, options={}, content=[]):
rel_lvl = inliner.document.current_source.replace(os.getcwd(),'').count('/')
parts = re.match("^([^<>]*)<([^<>]*)>$", text)
if parts:
text = parts.group(2)
lib = parts.group(1)
else:
lib = text
src = find_dot_opam(lib)
branch = os.environ.get('CI_COMMIT_REF_NAME', 'master')
project_url = os.environ.get('CI_PROJECT_URL', 'https://gitlab.com/tezos/tezos')
src_url = project_url + "/tree/" + branch + "/" + src
if os.path.isdir('_build/api/odoc/_html/'+lib):
if os.path.isdir(os.path.join('_build','api','odoc','_html',lib,lib.replace('-','_').capitalize())):
lib = lib + '/' + lib.replace('-','_').capitalize()
url = "api/api-inline.html#" + lib + '/index.html'
for i in range(1,rel_lvl):
url = '../' + url
else:
url = src_url
if name == 'package':
node = nodes.reference(rawtext, text, refuri=url, **options)
elif name == 'package-name':
node = nodes.literal(text, text)
elif name == 'package-src':
node = nodes.reference(rawtext, src, refuri=src_url, **options)
return [node], []
def opam_role(name, rawtext, text, lineno, inliner, options={}, content=[]):
rel_lvl = inliner.document.current_source.replace(os.getcwd(),'').count('/')
parts = re.match("^([^<>]*)<([^<>]*)>$", text)
if parts:
text = parts.group(2)
lib = parts.group(1)
else:
lib = text
tagged = re.match('([^.]+)[.].*', lib)
if tagged:
url = "https://opam.ocaml.org/packages/" + tagged.group(1) + "/" + lib
else:
url = "https://opam.ocaml.org/packages/" + lib
node = nodes.reference(rawtext, text, refuri=url, **options)
return [node], []
def src_role(name, rawtext, text, lineno, inliner, options={}, content=[]):
rel_lvl = inliner.document.current_source.replace(os.getcwd(),'').count('/')
parts = re.match("^([^<>]*)<([^<>]*)>$", text)
if parts:
text = parts.group(2)
src = parts.group(1)
else:
src = text
text = text
branch = os.environ.get('CI_COMMIT_REF_NAME', 'master')
project_url = os.environ.get('CI_PROJECT_URL', 'https://gitlab.com/tezos/tezos')
url = project_url + "/tree/" + branch + "/" + src
node = nodes.reference(rawtext, text, refuri=url, **options)
return [node], []

View File

@ -0,0 +1,19 @@
**************************
Online OCaml Documentation
**************************
.. raw:: html
<iframe id="docframe" height="100%" width="100%" src="../api/odoc/_html/index.html"></iframe>
<style>
@media (max-width: 771px) {
#docframe { border:none; position: fixed; top: 70px; bottom: 0; right: 0; left: 0; }
}
@media (min-width: 770px) {
#docframe { border:none; position: fixed; top: 0px; bottom: 0; right: 0; left: 300px; }
}
</style>
<script language="JavaScript">
if (window.location.hash.endsWith(".html"))
document.getElementById('docframe').src = "../api/odoc/_html/" + window.location.hash.slice(1)
</script>

View File

@ -0,0 +1,66 @@
**********************
Command Line Interface
**********************
This document is a prettier output of the documentation produced by
the command line client's ``man`` command. You can obtain similar pages
using the following shell commands.
::
tezos-client -protocol ProtoALphaALph man -verbosity 3
tezos-admin-client man -verbosity 3
.. _client_manual:
Client manual
=============
.. raw:: html
:file: tezos-client.html
.. _admin_client_manual:
Admin-client manual
===================
.. raw:: html
:file: tezos-admin-client.html
.. _signer_manual:
Signer manual
=============
.. raw:: html
:file: tezos-signer.html
.. _baker_manual:
Baker manual
============
.. raw:: html
:file: tezos-baker-alpha.html
.. _endorser_manual:
Endorser manual
===============
.. raw:: html
:file: tezos-endorser-alpha.html
.. _accuser_manual:
Accuser manual
==============
.. raw:: html
:file: tezos-accuser-alpha.html

View File

@ -0,0 +1 @@

181
vendors/tezos-modded/docs/conf.py vendored Normal file
View File

@ -0,0 +1,181 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# Tezos documentation build configuration file, created by
# sphinx-quickstart on Wed Jan 17 18:04:32 2018.
#
# This file is execfile()d with the current directory set to its
# containing dir.
#
# Note that not all possible configuration values are present in this
# autogenerated file.
#
# All configuration values have a default; values that are commented out
# serve to show the default.
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#
# sys.path.insert(0, os.path.abspath('.'))
import os
import sys
import datetime
from os import environ
sys.path.insert(0, os.path.abspath('.') + '/_extensions')
# -- General configuration ------------------------------------------------
# If your documentation needs a minimal Sphinx version, state it here.
#
# needs_sphinx = '1.0'
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = ['sphinx.ext.extlinks', 'tezos_custom_roles']
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
# The suffix(es) of source filenames.
# You can specify multiple suffix as a list of string:
#
# source_suffix = ['.rst', '.md']
source_suffix = '.rst'
# The master toctree document.
master_doc = 'index'
# General information about the project.
project = 'Tezos'
copyright = '2018, Nomadic Labs <contact@nomadic-labs.com>'
author = 'Nomadic Labs <contact@nomadic-labs.com>'
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
#
# The short X.Y version.
version = os.environ.get('CI_COMMIT_REF_NAME', 'local')
# The full version, including alpha/beta/rc tags.
release = '(' + version + ' branch, ' + datetime.datetime.now().strftime(" %Y/%m/%d %H:%M)")
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
#
# This is also used if you do content translation via gettext catalogs.
# Usually you set "language" from the command line for these cases.
language = None
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
# This patterns also effect to html_static_path and html_extra_path
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store', 'doc_gen']
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'sphinx'
# Deactivate syntax highlighting
# - http://www.sphinx-doc.org/en/stable/markup/code.html#code-examples
# - http://www.sphinx-doc.org/en/stable/config.html#confval-highlight_language
highlight_language = 'none'
# TODO write a Pygments lexer for Michelson
# cf. http://pygments.org/docs/lexerdevelopment/ and http://pygments.org/docs/lexers/
# If true, `todo` and `todoList` produce output, else they produce nothing.
todo_include_todos = False
# -- Options for HTML output ----------------------------------------------
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
#
html_theme = "sphinx_rtd_theme"
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
# documentation.
#
html_theme_options = {'logo_only': True}
html_logo = "logo.svg"
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']
# Custom sidebar templates, must be a dictionary that maps document names
# to template names.
#
# This is required for the alabaster theme
# refs: http://alabaster.readthedocs.io/en/latest/installation.html#sidebars
# html_sidebars = {
# '**': [
# 'relations.html', # needs 'show_related': True theme option to display
# 'searchbox.html',
# ]
# }
# -- Options for HTMLHelp output ------------------------------------------
# Output file base name for HTML help builder.
htmlhelp_basename = 'Tezosdoc'
# -- Options for LaTeX output ---------------------------------------------
latex_elements = {
# The paper size ('letterpaper' or 'a4paper').
#
# 'papersize': 'letterpaper',
# The font size ('10pt', '11pt' or '12pt').
#
# 'pointsize': '10pt',
# Additional stuff for the LaTeX preamble.
#
# 'preamble': '',
# Latex figure (float) alignment
#
# 'figure_align': 'htbp',
}
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title,
# author, documentclass [howto, manual, or own class]).
latex_documents = [
(master_doc, 'Tezos.tex', 'Tezos Documentation',
'Nomadic Labs \\textless{}contact@nomadic-labs.com\\textgreater{}', 'manual'),
]
# -- Options for manual page output ---------------------------------------
# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [
(master_doc, 'tezos', 'Tezos Documentation',
[author], 1)
]
# -- Options for Texinfo output -------------------------------------------
# Grouping the document tree into Texinfo files. List of tuples
# (source start file, target name, title, author,
# dir menu entry, description, category)
texinfo_documents = [
(master_doc, 'Tezos', 'Tezos Documentation',
author, 'Tezos', 'One line description of project.',
'Miscellaneous'),
]
# -- Ignore fragments in linkcheck
linkcheck_anchors = False

26
vendors/tezos-modded/docs/doc_gen/dune vendored Normal file
View File

@ -0,0 +1,26 @@
(executables
(names rpc_doc
p2p_doc)
(libraries tezos-base
tezos-stdlib-unix
tezos-shell
tezos-protocol-updater
tezos-embedded-protocol-alpha
re)
(flags (:standard -w -9+27-30-32-40@8
-safe-string
-open Tezos_base__TzPervasives
-open Tezos_stdlib_unix
-open Tezos_shell
-open Tezos_protocol_updater
-linkall)))
(alias
(name buildtest)
(deps rpc_doc.exe
p2p_doc.exe))
(alias
(name runtest_indent)
(deps (glob_files *.ml{,i}))
(action (run bash %{libexec:tezos-stdlib:test-ocp-indent.sh} %{deps})))

View File

@ -0,0 +1,16 @@
(executable
(name error_doc)
(libraries tezos-shell
tezos-client-alpha)
(flags (:standard -w -9+27-30-32-40@8
-open Tezos_base
-open Tezos_error_monad
-open Tezos_data_encoding
-open Tezos_client_alpha
-safe-string
-linkall)))
(alias
(name runtest_indent)
(deps (glob_files *.ml{,i}))
(action (run bash %{libexec:tezos-stdlib:test-ocp-indent.sh} %{deps})))

View File

@ -0,0 +1,263 @@
(*****************************************************************************)
(* *)
(* Open Source License *)
(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. <contact@tezos.com> *)
(* *)
(* Permission is hereby granted, free of charge, to any person obtaining a *)
(* copy of this software and associated documentation files (the "Software"),*)
(* to deal in the Software without restriction, including without limitation *)
(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *)
(* and/or sell copies of the Software, and to permit persons to whom the *)
(* Software is furnished to do so, subject to the following conditions: *)
(* *)
(* The above copyright notice and this permission notice shall be included *)
(* in all copies or substantial portions of the Software. *)
(* *)
(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*)
(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *)
(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *)
(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*)
(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *)
(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *)
(* DEALINGS IN THE SOFTWARE. *)
(* *)
(*****************************************************************************)
open Format
(* TODO: add section descriptions *)
let default_section_id = "default"
let default_section_title = "Miscellaneous"
(* Association list where keys are set of identifier's prefixes that
maps to a section title. The ordering of sections in the rst output
depends on their position in this list.
e.g. : an error which id is 'utils.Timeout' will be documented
under the `Miscellaneous` section which will be displayed at the
bottom of the document. Unprefixed ids or unreferenced prefixes
will default to `Miscellaneous` *)
let section_titles =
[ [ "proto.alpha" ], "Protocol Alpha";
[ "distributed_db" ; "node" ; "raw_store" ; "validator" ; "worker" ], "Shell" ;
[ "micheline" ; "michelson" ], "Michelson parsing/macros" ;
[ "rpc_client" ], "Client" ;
[ "cli"; "utils"; default_section_id ], default_section_title ;
]
let pp_rst_title ~char ppf title =
let sub = String.map (fun _ -> char) title in
fprintf ppf "@[<v 0>%s@\n@]@[<v 0>%s@\n@\n@]" title sub
let pp_rst_h1 = pp_rst_title ~char:'#'
let pp_rst_h2 = pp_rst_title ~char:'*'
(* let pp_rst_h3 = pp_rst_title ~char:'='
* let pp_rst_h4 = pp_rst_title ~char:'`' *)
let string_of_err_category = function
| `Branch -> "branch"
| `Temporary -> "temporary"
| `Permanent -> "permanent"
let make_counter () =
let i = ref 1 in
fun () -> incr i; !i
let count = make_counter ()
let unique_label () =
let label = sprintf "ref%d" (count ()) in
label
let pp_print_html_tab_button fmt ?(default=false) ~shortlabel ~content idref =
fprintf fmt "<button class=\"tablinks%s\" onclick=\"showTab(this, '%s', '%s')\">%s</button>@ "
(if default then " defaultOpen" else "")
(idref ^ shortlabel) idref content
let pp_print_html_tabs fmt { Error_monad.id ; category ; description ; schema ; _ } =
let idref = unique_label () in
let descr_label = "descr" in
let schema_label = "schema" in
fprintf fmt "@[<v 2>.. raw:: html@ @ ";
fprintf fmt "@[<v 2><div class=\"tab\">@ ";
fprintf fmt "%a" (pp_print_html_tab_button ~default:true ~shortlabel:descr_label ~content:"Description") idref;
fprintf fmt "%a" (pp_print_html_tab_button ~default:false ~shortlabel:schema_label ~content:"JSON Schema") idref;
fprintf fmt "@ </div>@ @]";
let description_content =
asprintf "<p>%s</p><p><i>Id</i> : %s<br/><i>Category</i> : %s</p>" description id (string_of_err_category category)
in
open_vbox 2;
(* Print description *)
begin
fprintf fmt "<div id=\"%s\" class=\"%s tabcontent\" style=\"min-height:100px; max-height:200px; overflow:auto\" >@ "
(idref ^ descr_label) idref;
fprintf fmt "%s@ " description_content;
fprintf fmt "</div>@]";
end;
(* Print schema *)
begin
(* Hack: negative offset in order to reduce the <pre>'s content left-margin *)
(* TODO: pretty-(html)-print the schema *)
open_vbox (-8);
fprintf fmt "<div id=\"%s\" class=\"%s tabcontent\" style=\"min-height:100px; max-height:200px; overflow:auto\" >@ "
(idref ^ schema_label) idref;
fprintf fmt "<%s>@ %a</%s>@ " "pre" Json_schema.pp schema "pre";
fprintf fmt "</div>";
close_box ();
end;
close_box ()
let pp_info_to_rst
ppf
(Error_monad.{ title ; _ } as error_info) =
let open Format in
fprintf ppf "**%s**@\n@\n" (if title = "" then "<Untitled>" else title);
fprintf ppf "@[<v>%a@ @ @]" pp_print_html_tabs error_info;
module ErrorSet = Set.Make(struct
type t = Error_monad.error_info
let compare { Error_monad.id ; _ } { Error_monad.id = id' ; _ } =
String.compare id id'
end)
module ErrorPartition = struct
include Map.Make(struct
include String
let titles = List.map snd section_titles
let compare s s' =
let idx s =
let rec loop acc = function
| [] -> assert false
| h::_ when h = s -> acc
| _::t -> loop (acc + 1) t
in loop 0 titles
in
Pervasives.compare (idx s) (idx s')
end)
let add_error (id : key) (error : Error_monad.error_info) (map : 'a t) =
let title =
try
snd
(List.find
(fun (id_set, _) ->
List.exists (fun pattern -> Stringext.find_from id ~pattern = Some 0) id_set)
section_titles)
with
| Not_found -> default_section_title
in
let set =
try find title map with Not_found -> ErrorSet.empty
in
add title (ErrorSet.add error set) map
end
let pp_error_map ppf (map : ErrorSet.t ErrorPartition.t) : unit =
let open Format in
ErrorPartition.iter (fun section_title set ->
fprintf ppf "%a" pp_rst_h2 section_title ;
ErrorSet.iter
(fun error_repr ->
fprintf ppf "@[%a@]@\n@\n" pp_info_to_rst error_repr
) set
) map
let script =
"<script>\
function showTab(elt, tab, ref) {\
var i, tabcontent, tablinks;\
\
tabcontent = document.getElementsByClassName(ref);\
for (i = 0; i < tabcontent.length; i++) {\
tabcontent[i].style.display = 'none';\
}\
\
tablinks = elt.parentNode.children;\
for (i = 0; i < tablinks.length; i++) {\
tablinks[i].className = tablinks[i].className.replace(' active', '');\
}\
\
document.getElementById(tab).style.display = 'block';\
elt.className += ' active';\
}\
\
document.addEventListener('DOMContentLoaded', function(){\
var a = document.getElementsByClassName('defaultOpen');\
for (i = 0; i < a.length; i++) { a[i].click() }\
})\
</script>"
let style =
"<style>\
.tab {\
overflow: hidden;\
border: 1px solid #ccc;\
background-color: #f1f1f1;\
}\
.tab button {\
background-color: inherit;\
float: left;\
border: none;\
outline: none;\
cursor: pointer;\
padding: 5px 10px;\
}\
.tab button:hover {\
background-color: #ddd;\
}\
.tab button.active {\
background-color: #ccc;\
}\
.tabcontent {\
display: none;\
padding: 6px 12px;\
border: 1px solid #ccc;\
border-top: none;\
margin-bottom: 20px;\
}\
pre {\
font-size: 12px\
}</style>"
let print_script ppf =
(* HACK : show/hide JSON schemas + style *)
fprintf ppf "@[<v 2>.. raw:: html@\n@\n" ;
fprintf ppf "@[<v 0>%s%s@]@\n@\n@]@]@." script style
(* Main *)
let () =
let open Format in
let ppf = std_formatter in
(* Header *)
let title = "RPC Errors" in
fprintf ppf "%a" pp_rst_h1 title ;
print_script ppf ;
fprintf ppf
"This document references possible errors that can come \
from RPC calls. It is generated from the OCaml source \
code (master branch).@\n@\n" ;
(* Body *)
let map =
let all_errors =
Error_monad.get_registered_errors () in
List.fold_left
(fun acc ( Error_monad.{ id ; _ } as error ) ->
ErrorPartition.add_error id error acc
) ErrorPartition.empty all_errors
in
fprintf ppf "%a" pp_error_map map

View File

@ -0,0 +1,62 @@
(*****************************************************************************)
(* *)
(* Open Source License *)
(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. <contact@tezos.com> *)
(* *)
(* Permission is hereby granted, free of charge, to any person obtaining a *)
(* copy of this software and associated documentation files (the "Software"),*)
(* to deal in the Software without restriction, including without limitation *)
(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *)
(* and/or sell copies of the Software, and to permit persons to whom the *)
(* Software is furnished to do so, subject to the following conditions: *)
(* *)
(* The above copyright notice and this permission notice shall be included *)
(* in all copies or substantial portions of the Software. *)
(* *)
(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*)
(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *)
(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *)
(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*)
(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *)
(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *)
(* DEALINGS IN THE SOFTWARE. *)
(* *)
(*****************************************************************************)
let genesis : State.Chain.genesis = {
time =
Time.of_notation_exn "2018-04-17T11:46:23Z" ;
block =
Block_hash.of_b58check_exn
"BLockGenesisGenesisGenesisGenesisGenesisa52f8bUWPcg" ;
protocol =
Protocol_hash.of_b58check_exn
"ProtoGenesisGenesisGenesisGenesisGenesisGenesk612im" ;
}
let with_node f =
let run dir =
let (/) = Filename.concat in
let node_config : Node.config = {
genesis ;
patch_context = None ;
store_root = dir / "store" ;
context_root = dir / "context" ;
p2p = None ;
test_chain_max_tll = None ;
checkpoint = None ;
} in
Node.create
node_config
Node.default_peer_validator_limits
Node.default_block_validator_limits
Node.default_prevalidator_limits
Node.default_chain_validator_limits >>=? fun node ->
f node >>=? fun () ->
return () in
Lwt_utils_unix.with_tempdir "tezos_rpcdoc_" run >>= function
| Ok () ->
Lwt.return_unit
| Error err ->
Format.eprintf "%a@." pp_print_error err ;
Pervasives.exit 1

View File

@ -0,0 +1,70 @@
(*****************************************************************************)
(* *)
(* Open Source License *)
(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. <contact@tezos.com> *)
(* *)
(* Permission is hereby granted, free of charge, to any person obtaining a *)
(* copy of this software and associated documentation files (the "Software"),*)
(* to deal in the Software without restriction, including without limitation *)
(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *)
(* and/or sell copies of the Software, and to permit persons to whom the *)
(* Software is furnished to do so, subject to the following conditions: *)
(* *)
(* The above copyright notice and this permission notice shall be included *)
(* in all copies or substantial portions of the Software. *)
(* *)
(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*)
(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *)
(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *)
(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*)
(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *)
(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *)
(* DEALINGS IN THE SOFTWARE. *)
(* *)
(*****************************************************************************)
let protocols = [
"Alpha", "ProtoALphaALphaALphaALphaALphaALphaALphaALphaDdp3zK" ;
]
let main _node =
(* Style : hack *)
Format.printf "%a@." Rst.pp_raw_html Rst.style ;
(* Script : hack *)
Format.printf "%a@." Rst.pp_raw_html Rst.script ;
(* Page title *)
Format.printf "%a" Rst.pp_h1 "P2P message format" ;
(* include/copy usage.rst from input *)
let rec loop () =
let s = read_line () in
Format.printf "%s@\n" s ;
loop () in
begin try loop () with End_of_file -> () end ;
Format.printf "@\n" ;
(* Data *)
Format.printf "%a@\n@\n%a@\n@."
Rst.pp_h2 "Block header (shell)"
Data_encoding.Binary_schema.pp
(Data_encoding.Binary.describe Block_header.encoding) ;
Format.printf "%a@\n@\n%a@\n@."
Rst.pp_h2 "Operation (shell)"
Data_encoding.Binary_schema.pp
(Data_encoding.Binary.describe Operation.encoding) ;
List.iter
(fun (_name, hash) ->
let hash = Protocol_hash.of_b58check_exn hash in
let (module Proto) = Registered_protocol.get_exn hash in
Format.printf "%a@\n@\n%a@\n@."
Rst.pp_h2 "Block_header (alpha-specific)"
Data_encoding.Binary_schema.pp
(Data_encoding.Binary.describe Proto.block_header_data_encoding) ;
Format.printf "%a@\n@\n%a@\n@."
Rst.pp_h2 "Operation (alpha-specific)"
Data_encoding.Binary_schema.pp
(Data_encoding.Binary.describe Proto.operation_data_encoding) ;
)
protocols ;
return ()
let () =
Lwt_main.run (Node_helpers.with_node main)

View File

@ -0,0 +1,314 @@
(*****************************************************************************)
(* *)
(* Open Source License *)
(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. <contact@tezos.com> *)
(* *)
(* Permission is hereby granted, free of charge, to any person obtaining a *)
(* copy of this software and associated documentation files (the "Software"),*)
(* to deal in the Software without restriction, including without limitation *)
(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *)
(* and/or sell copies of the Software, and to permit persons to whom the *)
(* Software is furnished to do so, subject to the following conditions: *)
(* *)
(* The above copyright notice and this permission notice shall be included *)
(* in all copies or substantial portions of the Software. *)
(* *)
(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*)
(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *)
(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *)
(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*)
(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *)
(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *)
(* DEALINGS IN THE SOFTWARE. *)
(* *)
(*****************************************************************************)
let protocols = [
"Alpha", "ProtoALphaALphaALphaALphaALphaALphaALphaALphaDdp3zK" ;
]
let pp_name ppf = function
| [] | [""] -> Format.pp_print_string ppf "/"
| prefix -> Format.pp_print_string ppf (String.concat "/" prefix)
let ref_of_service (prefix, meth) =
Format.asprintf "%s_%s"
(Resto.string_of_meth meth)
(Re.Str.global_replace
(Re.Str.regexp "<\\([^>]*\\)>")
"\\1"
(String.concat "--" prefix))
module Index = struct
let rec pp prefix ppf dir =
let open Resto.Description in
match dir with
| Empty -> Format.fprintf ppf "Empty"
| Static { services ; subdirs = None } ->
pp_services prefix ppf services
| Static { services ; subdirs = Some (Suffixes map) } ->
Format.fprintf ppf "@[<v 2>%a@ @ %a@]"
(pp_services prefix) services
(Format.pp_print_list
~pp_sep:(fun ppf () -> Format.fprintf ppf "@ @ ")
(pp_suffixes prefix))
(Resto.StringMap.bindings map)
| Static { services ; subdirs = Some (Arg (arg, dir)) } ->
let name = Format.asprintf "<%s>" arg.name in
Format.fprintf ppf "@[<v 2>%a@ @ %a@]"
(pp_services prefix) services
(pp_suffixes prefix) (name, dir)
| Dynamic _ ->
Format.fprintf ppf "* %a (<dyn>)" pp_name prefix
and pp_suffixes prefix ppf (name, dir) =
pp (prefix @ [name]) ppf dir
and pp_services prefix ppf services =
match (Resto.MethMap.bindings services) with
| [] ->
Format.fprintf ppf "* %a" pp_name prefix
| _ :: _ as services ->
Format.fprintf ppf "* %a (@[<h>%a@])"
pp_name prefix
(Format.pp_print_list
~pp_sep:Format.pp_print_space
(pp_service_method prefix)) services
and pp_service_method prefix ppf (meth, _service) =
Format.fprintf ppf "`%s <%s_>`_"
(Resto.string_of_meth meth)
(ref_of_service (prefix, meth))
end
module Description = struct
module Query = struct
let pp_arg fmt =
let open RPC_arg in
function { name ; _ } ->
Format.fprintf fmt "<%s>" name
let pp_title_item ppf =
let open RPC_description in
function {name ; kind ; _ } ->
match kind with
| Single arg | Optional arg ->
Format.fprintf ppf "[%s=%a]" name pp_arg arg
| Flag ->
Format.fprintf ppf "[%s]" name
| Multi arg ->
Format.fprintf ppf "(%s=%a)\\*" name pp_arg arg
let pp_title ppf query =
Format.fprintf ppf "%s%a"
(if query = [] then "" else "?")
(Format.pp_print_list
~pp_sep:(fun ppf () -> Format.fprintf ppf "&")
pp_title_item) query
let pp_html_arg fmt =
let open RPC_arg in
function { name ; _ } ->
Format.fprintf fmt "&lt;%s&gt;" name
let pp_item ppf =
let open RPC_description in
function { name ; description ; kind } ->
begin match kind with
| Single arg
| Optional arg
| Multi arg ->
Format.fprintf ppf
"<span class=\"query\">%s = %a</span>"
name pp_html_arg arg
| Flag ->
Format.fprintf ppf
"<span class=\"query\">%s</span>"
name
end ;
begin match description with
| None -> ()
| Some descr -> Format.fprintf ppf " : %s" descr
end
let pp ppf query =
match query with
| [] -> ()
| _ :: _ as query ->
Format.fprintf ppf
"</p> <p>Optional query arguments :<ul><li>%a</li></ul>"
(Format.pp_print_list
~pp_sep:(fun ppf () -> Format.fprintf ppf "</li><li>")
pp_item)
query
end
module Tabs = struct
let pp_tab_div ppf f =
Format.fprintf ppf
"@[<v 2><div class=\"tab\">%a</div>@]"
(fun ppf () -> f ppf) ()
let pp_tabcontent_div ~id ~class_ ppf f =
Format.fprintf ppf
"@[<v 2><div id=\"%s\" class=\"%s tabcontent\">@ \
%a@ \
@]</div>@ "
id class_ (fun ppf () -> f ppf) ()
let pp_button ppf ?(default=false) ~shortlabel ~content target_ref =
Format.fprintf ppf
"<button class=\"tablinks%s\" onclick=\"showTab(this, '%s', '%s')\">%s</button>@ "
(if default then " defaultOpen" else "")
(target_ref ^ shortlabel)
target_ref
content
let pp_content ppf ~tag ~shortlabel target_ref pp_content content =
pp_tabcontent_div
~id:(target_ref ^ shortlabel) ~class_:target_ref ppf
begin fun ppf ->
Format.fprintf ppf "<%s>@ %a</%s>" tag pp_content content tag
end
let pp_description ppf (service : _ RPC_description.service) =
let open RPC_description in
(* TODO collect and display arg description (in path and in query) *)
Format.fprintf ppf "@[<h>%a@]%a"
Format.pp_print_text (Option.unopt ~default:"" service.description)
Query.pp service.query
let pp ppf prefix service =
let open RPC_description in
let target_ref = ref_of_service (prefix, service.meth) in
Rst.pp_html ppf begin fun ppf ->
pp_tab_div ppf begin fun ppf ->
pp_button ppf
~default:true ~shortlabel:"descr" ~content:"Description"
target_ref ;
Option.iter service.input ~f: begin fun _ ->
pp_button ppf
~default:false ~shortlabel:"input.json" ~content:"Json input"
target_ref ;
pp_button ppf
~default:false ~shortlabel:"input.bin" ~content:"Binary input"
target_ref
end ;
pp_button ppf
~default:false ~shortlabel:"output.json" ~content:"Json output"
target_ref ;
pp_button ppf
~default:false ~shortlabel:"output.bin" ~content:"Binary output"
target_ref ;
end ;
pp_content ppf
~tag:"p" ~shortlabel:"descr" target_ref
pp_description service ;
Option.iter service.input ~f: begin fun (schema, bin_schema) ->
pp_content ppf
~tag:"pre" ~shortlabel:"input.json" target_ref
Json_schema.pp schema ;
pp_content ppf
~tag:"pre" ~shortlabel:"input.bin" target_ref
Data_encoding.Binary_schema.pp bin_schema ;
end ;
pp_content ppf
~tag:"pre" ~shortlabel:"output.json" target_ref
Json_schema.pp (fst service.output) ;
pp_content ppf
~tag:"pre" ~shortlabel:"output.bin" target_ref
Data_encoding.Binary_schema.pp (snd service.output) ;
end
end
let rec pp prefix ppf dir =
let open Resto.Description in
match dir with
| Empty -> ()
| Static { services ; subdirs = None } ->
pp_services prefix ppf services
| Static { services ; subdirs = Some (Suffixes map) } ->
pp_services prefix ppf services ;
Format.pp_print_list (pp_suffixes prefix)
ppf (Resto.StringMap.bindings map)
| Static { services ; subdirs = Some (Arg (arg, dir)) } ->
let name = Format.asprintf "<%s>" arg.name in
pp_services prefix ppf services ;
pp_suffixes prefix ppf (name, dir)
| Dynamic _ -> ()
and pp_suffixes prefix ppf (name, dir) =
pp (prefix @ [name]) ppf dir
and pp_services prefix ppf services =
List.iter
(pp_service prefix ppf)
(Resto.MethMap.bindings services)
and pp_service prefix ppf (meth, service) =
Rst.pp_ref ppf (ref_of_service (prefix, meth)) ;
Format.fprintf ppf "**%s %a%a**@\n@\n"
(Resto.string_of_meth meth)
pp_name prefix
Query.pp_title service.query ;
Tabs.pp ppf prefix service
end
let pp_document ppf descriptions =
(* Style : hack *)
Format.fprintf ppf "%a@." Rst.pp_raw_html Rst.style ;
(* Script : hack *)
Format.fprintf ppf "%a@." Rst.pp_raw_html Rst.script ;
(* Index *)
Format.pp_set_margin ppf 10000 ;
Format.pp_set_max_indent ppf 9000 ;
Format.fprintf ppf "%a" Rst.pp_ref "rpc_index" ;
Rst.pp_h2 ppf "RPCs - Index" ;
List.iter
(fun (name, prefix, rpc_dir) ->
Rst.pp_h3 ppf name ;
Format.fprintf ppf "%a@\n@\n" (Index.pp prefix) rpc_dir)
descriptions ;
(* Full description *)
Rst.pp_h2 ppf "RPCs - Full description" ;
Format.pp_print_flush ppf () ;
Format.pp_set_margin ppf 80 ;
Format.pp_set_max_indent ppf 76 ;
List.iter
(fun (name, prefix, rpc_dir) ->
Rst.pp_h3 ppf name ;
Format.fprintf ppf "%a@\n@\n" (Description.pp prefix) rpc_dir)
descriptions
let main node =
let shell_dir = Node.build_rpc_directory node in
let protocol_dirs =
List.map
(fun (name, hash) ->
let hash = Protocol_hash.of_b58check_exn hash in
let (module Proto) = Registered_protocol.get_exn hash in
"Protocol " ^ name,
[".." ; "<block_id>"] ,
RPC_directory.map (fun () -> assert false) @@
Block_directory.build_raw_rpc_directory (module Proto) (module Proto))
protocols in
let dirs = ("Shell", [""], shell_dir) :: protocol_dirs in
Lwt_list.map_p
(fun (name, path, dir) ->
RPC_directory.describe_directory ~recurse:true ~arg:() dir >>= fun dir ->
Lwt.return (name, path, dir))
dirs >>= fun descriptions ->
let ppf = Format.std_formatter in
pp_document ppf descriptions ;
return ()
let () =
Lwt_main.run (Node_helpers.with_node main)

120
vendors/tezos-modded/docs/doc_gen/rst.ml vendored Normal file
View File

@ -0,0 +1,120 @@
(*****************************************************************************)
(* *)
(* Open Source License *)
(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. <contact@tezos.com> *)
(* *)
(* Permission is hereby granted, free of charge, to any person obtaining a *)
(* copy of this software and associated documentation files (the "Software"),*)
(* to deal in the Software without restriction, including without limitation *)
(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *)
(* and/or sell copies of the Software, and to permit persons to whom the *)
(* Software is furnished to do so, subject to the following conditions: *)
(* *)
(* The above copyright notice and this permission notice shall be included *)
(* in all copies or substantial portions of the Software. *)
(* *)
(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*)
(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *)
(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *)
(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*)
(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *)
(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *)
(* DEALINGS IN THE SOFTWARE. *)
(* *)
(*****************************************************************************)
let pp_title ~char ppf title =
let sub = String.map (fun _ -> char) title in
Format.fprintf ppf "@[<v 0>%s@ %s@ @ @]" title sub
let pp_h1 = pp_title ~char:'#'
let pp_h2 = pp_title ~char:'*'
let pp_h3 = pp_title ~char:'='
let pp_h4 = pp_title ~char:'`'
let pp_raw_html ppf str =
Format.fprintf ppf "@[<v>.. raw:: html@ @ %s@ @ @]"
(Re.Str.global_replace (Re.Str.regexp "\n") "\n " str)
let pp_html ppf f =
Format.fprintf ppf
"@[<v 2>.. raw:: html@ @ %a@]@\n@\n"
(fun ppf () -> f ppf) ()
let pp_ref ppf name = Format.fprintf ppf ".. _%s :@\n@\n" name
let style = {css|
<style>
.wy-nav-content {
max-width: 100%;
}
.tab {
overflow: hidden;
border: 1px solid #ccc;
background-color: #f1f1f1;
}
.tab button {
background-color: inherit;
float: left;
border: none;
outline: none;
cursor: pointer;
padding: 5px 10px;
}
.tab button:hover {
background-color: #ddd;
}
.tab button.active {
background-color: #ccc;
}
.tabcontent {
display: none;
padding: 6px 12px;
border: 1px solid #ccc;
border-top: none;
max-height: 40ex;
margin-bottom: 7ex;
overflow: auto;
}
.tabcontent p {
margin-bottom: 12px;
}
pre {
font-size: 12px
}
.rst-content .section ul p {
margin-bottom: 0;
}
span.query {
font-family: monospace;
white-space: pre;
}
</style>
|css}
let script = {script|
<script>
function showTab(elt, tab, ref) {
var i, tabcontent, tablinks;
tabcontent = document.getElementsByClassName(ref);
for (i = 0; i < tabcontent.length; i++) {
tabcontent[i].style.display = 'none';
}
tablinks = elt.parentNode.children;
for (i = 0; i < tablinks.length; i++) {
tablinks[i].className = tablinks[i].className.replace(' active', '');
}
document.getElementById(tab).style.display = 'block';
elt.className += ' active';
}
document.addEventListener('DOMContentLoaded', function() {
var a = document.getElementsByClassName('defaultOpen');
for (i = 0; i < a.length; i++) { a[i].click() }
})
</script>
|script}

160
vendors/tezos-modded/docs/index.rst vendored Normal file
View File

@ -0,0 +1,160 @@
.. Tezos documentation master file, created by
sphinx-quickstart on Sat Nov 11 11:08:48 2017.
You can adapt this file completely to your liking, but it should at least
contain the root `toctree` directive.
Welcome to the Tezos Developer Documentation!
=============================================
The Project
-----------
Tezos is a distributed consensus platform with meta-consensus
capability. Tezos not only comes to consensus about the state of its ledger,
like Bitcoin or Ethereum. It also attempts to come to consensus about how the
protocol and the nodes should adapt and upgrade.
- Developer documentation is available online at
https://tezos.gitlab.io/master . The documentation is automatically
generated for the master branch, the main network `mainnet
<https://tezos.gitlab.io/mainnet>`_ and the test network `alphanet
<https://tezos.gitlab.io/alphanet>`_.
Make sure you are consulting the right version.
- The website https://tezos.com/ contains more information about the project.
- All development happens on GitLab at https://gitlab.com/tezos/tezos
The source code of Tezos is placed under the MIT Open Source License.
The Community
-------------
- The website of the `Tezos Foundation <https://tezos.foundation/>`_.
- `Tezos sub-reddit <https://www.reddit.com/r/tezos/>`_ is an
important meeting point of the community.
- Several community-built block explorers are available:
- https://tzscan.io
- https://tezex.info
- A few community-run websites collect useful Tezos links:
- https://www.tezos.help
- https://tezos.rocks
- More resources can be found in the :ref:`support` page.
The Networks
------------
.. _mainnet:
Mainnet
~~~~~~~
The Tezos network is the current incarnation of the Tezos blockchain.
It runs with real tez that have been allocated to the
donors of July 2017 ICO (see :ref:`activate_fundraiser_account`).
The Tezos network has been live and open since June 30th 2018.
All the instructions in this documentation are valid for Mainnet
however we **strongly** encourage users to first try all the
introduction tutorials on Alphanet to familiarize themselves without
risks.
.. _alphanet:
Alphanet
~~~~~~~~
Tezos Alphanet is a test network for the Tezos blockchain with a
faucet to obtain free tez (see :ref:`faucet`).
It is updated and rebooted rarely and it is running the same code as
the Mainnet.
It is the reference network for developers wanting to test their
software before going to beta and for users who want to familiarize
themselves with Tezos before using their real tez.
We offer support for Alphanet on IRC.
The Tezos Alpha (test) network has been live and open since February 2017.
.. _zeronet:
Zeronet
~~~~~~~
Zeronet is the most cutting-edge development network of Tezos. It is
restarted without notice, possibly several times a day.
This network is mostly used internally by the Tezos developers and may
have *different constants* from Alphanet or Mainnet, for example it
has shorter cycles and a shorter interval between blocks.
We offer no support for the Zeronet.
Getting started
---------------
The best place to start exploring the project is following the How Tos
in the :ref:`introduction <howtoget>`.
.. toctree::
:maxdepth: 2
:caption: Introduction:
introduction/howtoget
introduction/howtouse
introduction/howtorun
introduction/various
introduction/support
introduction/contributing
.. toctree::
:maxdepth: 2
:caption: White doc:
whitedoc/the_big_picture
whitedoc/p2p
whitedoc/validation
whitedoc/michelson
whitedoc/proof_of_stake
whitedoc/voting
.. toctree::
:maxdepth: 2
:caption: Protocols:
protocols/003_PsddFKi3
.. toctree::
:maxdepth: 2
:caption: Developer Tutorials:
tutorials/rpc
tutorials/data_encoding
tutorials/error_monad
tutorials/michelson_anti_patterns
tutorials/entering_alpha
tutorials/protocol_environment
tutorials/profiling
.. toctree::
:maxdepth: 2
:caption: APIs:
README
api/api-inline
api/cli-commands
api/rpc
api/errors
api/p2p
Indices and tables
==================
* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`

View File

@ -0,0 +1,100 @@
How to contribute
=================
Introduction
------------
The purpose of this document is to help contributors get started with
the Tezos OCaml codebase.
Reporting issues
----------------
The simplest way to contribute to Tezos is to report issues that you may
find with the software on `gitlab <https://gitlab.com/tezos/tezos/issues>`__.
If you are unsure about an issue ask on IRC first and always make sure
to search the existing issues before reporting a new one.
Some info that are probably important to include in the description:
the architecture (e.g. *ARM64*), the operating system (e.g. *Debian
Stretch*), the network you are connected to (e.g. *Alphanet*), the
binary or component (e.g. *tezos-node crashes* or *rpc X returns Y
while Z was expected*).
First steps
-----------
First, make sure that you are proficient enough in OCaml. The community
Website http://www.ocaml.org below gives a few pointer for that. In
particular, we use a lot of functors, and a few GADTs in the codebase,
so you may want to make sure that you master these advanced concepts.
Then, if you dont know well about the Lwt library, thats what you want
to learn. This library is used extensively throughout the code base, as
thats the one we use to handle concurrency, and Tezos is a very
concurrent system. You can use the `online documentation <https://ocsigen.org/lwt/3.2.1/manual/manual>`__. The chapter on concurrency of `Real World
OCaml <https://github.com/dkim/rwo-lwt>`__ has also been ported to Lwt.
After that, it is a good idea to read the tutorials for
:ref:`error_monad<error_monad>` and
:ref:`data_encoding <data_encoding>`, two homegrown
libraries that we use pervasively.
Where to start
--------------
While you familiarize yourself with the basics as suggested above, you
can have a look at the :ref:`software architecture
<software_architecture>` of Tezos. It will
give you the main components and their interactions, and links to the
documentations for the various parts.
Our git workflow
----------------
First, the repository is https://gitlab.com/tezos/tezos, the github one
is just a clone that exists for historical reasons. So if you want to
contribute, simply create an account there.
Then, there are many ways to use Git, here is ours.
We use almost only merge requests to push into master. Meaning, nobody
should push directly into master. Once a merge request is ready, it is
reviewed and approved, we merge it using the ``--fast-forward`` option
of Git, in order to maintain a linear history without merge patches.
For that to work, it means that merge requests must be direct suffixes
of the master branch. So whenever ``origin/master`` changes, you have to
rebase your branch on it, so that you patches always sit on top of
master. When that happens, you may have to edit your patches during the
rebase, and then use ``push -f`` in your branch to rewrite the history.
We also enforce a few hygiene rules, so make sure your MR respects them:
- Prefer small atomic commits over a large one that do many things.
- Dont mix refactoring and new features.
- Never mix reindentation, whitespace deletion, or other style changes
with actual code changes.
- Try as much as possible to make every patch compile, not only the
last.
- If you add new functions into a documented interface, dont forget to
extend the documentation for your addition.
- For parts whose specification is in the repository (e.g. Michelson),
make sure to keep it in sync with the implementation.
- Try and mimic the style of commit messages, and for non trivial
commits, add an extended commit message.
As per the hygiene of MRs themselves:
- Give appropriate titles to the MRs, and when non trivial add a
detailed motivated explanation.
- Give meaningful and consistent names to branches.
- Dont forget to put a ``WIP:`` flag when it is a work in progress
Some extra CI tests are only done on demand for branches other that
master. You can (should) activate these tests by including keywords in
the branch name.
- If your MR impacts OPAM packaging, use ``opam`` in the branch name.
- If your MR updates documentation, use ``doc`` in the branch name.

View File

@ -0,0 +1,184 @@
.. _howtoget:
How to get Tezos
================
In this How To we explain how to get up-to-date binaries to run Tezos
for each network.
You can either use the docker images, which is easier, or build from
sources.
Docker images
-------------
The recommended way for running an up-to-date Tezos node is to use the
docker images that are automatically generated from the GitLab
repository and published on `DockerHub
<https://hub.docker.com/r/tezos/tezos/>`_.
The script ``alphanet.sh`` is provided to help download the right
image for each network and run a simple node.
Its only requirement is a working installation of `Docker
<https://www.docker.com/>`__ and docker compose on a machine with
architecture **x86_64**.
Although we only officially support Linux, the script has been tested
with success in the past on windows/mac/linux.
The same script can be used to run Mainnet, Alphanet or Zeronet, it
suffices to rename it as it downloads a different image based on its
name.
For example, to run Alphanet:
::
wget https://gitlab.com/tezos/tezos/raw/master/scripts/alphanet.sh
chmod +x alphanet.sh
Alternatively, to run Mainnet:
::
wget -O mainnet.sh https://gitlab.com/tezos/tezos/raw/master/scripts/alphanet.sh
chmod +x mainnet.sh
In the following we assume you are running Alphanet.
You are now one step away from a working node:
::
./alphanet.sh start
This will download the right docker image for your chosen network,
launch 3 docker containers running the node, the baker and the
endorser.
The first launch might take a few minutes to download the
docker images and synchronize the chain.
Every call to ``alphanet.sh`` will check for updates of the node and
will fail if your node is not up-to-date. For updating the node, simply
run:
::
./alphanet.sh restart
If you prefer to temporarily disable automatic updates, you just have to
set an environment variable:
::
export TEZOS_ALPHANET_DO_NOT_PULL=yes
See ``./alphanet.sh --help`` for more informations about the
script. In particular see ``./alphanet.sh client --help`` or the
:ref:`online manual<client_manual>` for more information about
the client. Every command to the ``tezos-client`` can be
equivalently executed using ``./alphanet.sh client``.
Build from sources
------------------
**TL;DR**: Typically you want to do:
::
sudo apt install -y rsync git m4 build-essential patch unzip bubblewrap wget
wget https://github.com/ocaml/opam/releases/download/2.0.1/opam-2.0.1-x86_64-linux
sudo cp opam-2.0.1-x86_64-linux /usr/local/bin/opam
sudo chmod a+x /usr/local/bin/opam
git clone https://gitlab.com/tezos/tezos.git
cd tezos
git checkout alphanet
opam init --bare
make build-deps
eval $(opam env)
make
export PATH=~/tezos:$PATH
source ./src/bin_client/bash-completion.sh
export TEZOS_CLIENT_UNSAFE_DISABLE_DISCLAIMER=Y
Environment
~~~~~~~~~~~
Currently Tezos is being developed for Linux x86_64, mostly for
Debian/Ubuntu and Archlinux.
The following OSes are reported to work:
- macOS/x86_64
- Linux/armv7h (32 bits) (Raspberry Pi3, etc.)
- Linux/aarch64 (64 bits) (Raspberry Pi3, etc.)
A Windows port is feasible and might be developed in the future.
If ``bubblewrap`` is not available in your distribution you can also
skip it and init opam with ``--disable-sandbox``.
Get the sources
~~~~~~~~~~~~~~~
Tezos *git* repository is hosted at `GitLab
<https://gitlab.com/tezos/tezos/>`_. All development happens here. Do
**not** use our `GitHub mirror <https://github.com/tezos/tezos>`_
which we don't use anymore and only mirrors what happens on GitLab.
You also need to **choose the branch** of the network you want to connect
to: *alphanet*, *zeronet* or *mainnet*.
The *master* branch is where code is merged, but there is no test
network using the master branch directly.
Install OPAM
~~~~~~~~~~~~
To compile Tezos, you need the `OPAM <https://opam.ocaml.org/>`__
package manager, version *2.0*. The build script will take
care of setting-up OPAM, download the right version of the OCaml
compiler, and so on.
Use ``opam init --bare`` to avoid compiling the OCaml compiler now: it
will be done in the next step.
Install Tezos dependencies with OPAM
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Install the OCaml compiler and the libraries which Tezos depends on:
::
make build-deps
Alternatively, if you want to be able to install extra packages
(development packages such as `merlin`), you may use the following
command instead:
::
make build-dev-deps
This command creates a local opam switch ``_opam`` where the right
version of OCaml is compiled and installed (this takes a while but
it's only done once).
After OCaml it will start with Tezos dependencies, OPAM is able to
handle correctly the OCaml libraries but it is not always able to
handle all external C libraries we depend on. On most system, it is
able to suggest a call to the system package manager but it currently
does not handle version check.
Once the dependencies are done we can update opam's environment to
refer to the new switch and compile the project:
::
eval $(opam env)
make
Lastly you can also add Tezos binaries to your ``PATH`` variable,
activate bash autocompletion and after reading the Disclaimer a few
hundred times you are allowed to disable it with
``TEZOS_CLIENT_UNSAFE_DISABLE_DISCLAIMER=Y``.

View File

@ -0,0 +1,302 @@
.. _howtorun:
How to run Tezos
================
In this section we discuss how to take part in the protocol that runs
the network.
There are two main ways to participate in the consensus, delegating
your coins and running a delegate.
To learn more about the protocol refer to :ref:`this section <proof-of-stake>`.
Delegating your coins
---------------------
If you don't want to deal with the complexity of running your own
delegate, you can always take part in the protocol by delegating your
coins to one.
Implicit accounts cannot have a delegate, so the first step is to
originate an account, transfer your tez there and set a delegate.
Notice that an originated account is a special case of a contract
without code, so it is still necessary to pay for its small storage
(see `originated_account`).
::
tezos-client originate account alice_del for alice \
transferring 1000 from alice \
--delegate bob
As done before, we originate a contract *alice_del* with manager
*alice* and we fund it with 1kꜩ.
The interesting part is setting the delegate to *bob*, when
originating a contract the delegate is not set by default.
If you already own contracts that are delegatable you can change
the delegate with the command ``set delegate``.
Notice that, by default, an originated account is not *delegatable*,
which means that you can't change the delegate once the contract is
originated, even if you initially set a delegate.
To be able to change the delegate latter, add the
``--delegatable`` flag.
Notice that only implicit accounts can be delegates, so your delegate
must be a *tz1* address.
Funds in implicit accounts which are not registered as delegates
do not participate in baking.
Running a delegate
------------------
A delegate is responsible for baking blocks, endorsing blocks and
accusing other delegates in case they try to double bake or double
endorse.
In the network, rights for baking and endorsing are randomly assigned
to delegates proportionally to the number of rolls they have been
delegated.
A roll is just a block of 10kꜩ and all computations with rolls are
rounded to the nearest lower integer e.g. if you have 16kꜩ it amounts
to 1 roll.
When you obtain coins from :ref:`the faucet<faucet>`, if you
are lucky to obtain more than one roll, you can register a delegate
using this identity.
Otherwise, you need to ask the faucet for more accounts, originate an
account for each one and delegate them to the first.
Deposits and over-delegation
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
When baking or endorsing a block, a *security deposit* (or *bond*) is
frozen for ``preserved_cycles`` cycles from the account of the
delegate.
Hence a delegate must have enough funds to be able to pay security
deposits for all the blocks it can potentially bake/endorse during
``preserved_cycles``.
The current deposits are *512ꜩ* for baked block and *64ꜩ* for
endorsement.
Note that being delegated coins doesn't mean that a delegate can spend
them, they only add up to its rolls count while all the deposits must
come from the delegate's account.
If a delegate runs out of funds to deposit it won't be able to bake or
endorse, other than being a missed opportunity for them this has also
negative consequences on the network.
Missing baking slots slows the network, as it is necessary to wait one
minute for the baker at priority 2 to bake, while missing endorsements
reduce the fitness of the chain, making it more susceptible to forks.
Running out of funds can happen if a delegate is *over-delegated*,
that is if the amount of rolls it was delegate is disproportionate
with respect to its available funds.
It is the responsibility of every delegator to make sure a delegate is
not already over-delegated (a delegate cannot refuse a delegation) and
each delegate should plan carefully its deposits.
.. _expected_rights:
Expected rights, deposits and rewards
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Let's assume we have 1 roll, we want to estimate our chances to bake
or endorse in order to prepare the funds for our deposits.
Our chances depend on how many rolls are currently active in the
network, once we know that we can estimate how many blocks and
endorsements we could be assigned in a cycle.
The number of active rolls can be computed with two RPCs, first we
list all the active delegates with ``delegates?active``, then we sum
all their ``stacking_balance`` and we simply divide by the size of a
roll, 10kꜩ.
At the time of writing, on Betanet the number of active rolls is ~30k
so for each block we know that the chance that we get selected for
baking is ``1/30k`` while for endorsing is 32 times that.
Given that every draw is with replacement, the distribution that
describes our chances of being selected is the binomial with
probability of success ``p=1/30k``.
The distribution has another parameter ``n`` for the number of times
we draw, in our case in a cycle the draws for baking are ``n_b =
4096`` while for endorsing are ``n_e = 4096 * 32``.
Moreover we could extend ``n`` to cover ``preserved_cycles = 5``.
Once we have ``p`` and ``n``, the expected number of times that we
might get selected is ``p * n`` (the mean of the distribution).
Over many cycles our chances will fall around the mean, in some cycles
we might get unlucky and be assigned fewer rights, but in some cycles we might
get lucky and be assigned more rights!
Clearly we would like to plan ahead and have enough deposits to cover
also the "lucky" cycles so we need to compute a sort of "maximum"
number of rights that is safe for `most cases`.
We can compute this maximum using the inverse of Cumulative
Distribution Function of the Binomial where `most cases` is a value of
confidence that we can put to 95%.
There a simple `Python
script <https://gitlab.com/paracetamolo/utils/blob/master/estimated-rights.py>`_
that does the computation for us and returns the deposits and rewards,
expected and maximum, for a cycle and for `preserved_cycles`.
::
prob success 3.333333e-05
confidence 0.95
----------one-cycle--------------------
blocks
mean 0.14
max 1.00
endorsements
mean 4.37
max 8.00
deposits
mean 69.91 + 279.62
max 512.00 + 512.00
rewards
mean 2.18 + 8.74
max 16.00 + 16.00
----------preserved-cycles-------------
blocks
mean 0.68
max 2.00
endorsements
mean 21.85
max 30.00
deposits
mean 349.53 + 1398.10
max 1024.00 + 1920.00
rewards
mean 10.92 + 43.69
max 32.00 + 60.00
As a rule of thumb if we want to have a very high confidence that we
won't miss any opportunity we should have around ~3kꜩ for deposits,
on the other hand the expected returns will probably be around ~10ꜩ per cycle.
After ``preserved_cycles``, not only the delegate takes back control of
its frozen deposits but it also receives the rewards for its hard work
which amount to 16ꜩ to bake a block and ``ꜩ2 / <block_priority>`` for
endorsing a block.
Additionally a baker also receives the fees of the operations it
included in its blocks.
While fees are unfrozen after ``preserved_cycles`` like deposits and
rewards, they participate in the staking balance of the delegate
immediately after the block has been baked.
Register and check your rights
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In order to run a delegate you first need to register as one using
your implicit account:
::
tezos-client register key bob as delegate
Once registered, you need to wait ``preserved_cycles + 2 = 7`` cycles
for your rights to be considered.
There is a simple rpc that can be used to check your rights for every
cycle, up to 5 cycles in the future.
::
tezos-client rpc get /chains/main/blocks/head/helpers/baking_rights\?cycle=300\&delegate=tz1_xxxxxxxxxxx\&max_priority=2
Sometimes a delegate skips its turn so it is worth considering also
baking rights at priority 2 like in the example above.
There is no priority for endorsements, every missed endorsement is
lost.
Inactive delegates
~~~~~~~~~~~~~~~~~~
If a delegate doesn't show any sign of activity for `preserved_cycles`
it is marked **inactive** and its rights are removed.
This mechanism is important to remove inactive delegates and reallocate
their rights to the active ones so that the network is always working
smoothly.
Normally even a baker with one single roll should perform enough
operations during 5 cycles to remain active.
If for some reason you delegate is marked inactive you can reactivate
it simply by re-registering again like above.
Baker
~~~~~
The baker is a daemon that once connected to an account, computes the
baking rights for that account, collects transactions from the mempool
and bakes a block.
Note that the baker is the only program that needs direct access to
the node data directory for performance reasons.
Let's launch the daemon pointing to the standard node directory and
baking for user *bob*:
::
tezos-baker-alpha run with local node ~/.tezos-node bob
Endorser
~~~~~~~~
The endorser is a daemon that once connected to an account, computes
the endorsing rights for that account and, upon reception of a new
block, verifies the validity of the block and emits an endorsement
operation.
It can endorse for a specific account or if omitted it endorses for
all accounts.
::
tezos-endorser-alpha run
Accuser
~~~~~~~
The accuser is a daemon that monitors all blocks received on all
chains and looks for:
* bakers who signed two blocks at the same level
* endorsers who injected more than one endorsement operation for the
same baking slot (more details :ref:`here<proof-of-stake>`)
Upon finding such irregularity, it will emit respectively a
double-baking or double-endorsing denunciation operation, which will
cause the offender to loose its security deposit.
::
tezos-accuser-alpha run
Remember that having two bakers or endorsers running connected to the
same account could lead to double baking/endorsing and the loss of all
your bonds.
If you are worried about availability of your node when is its turn to
bake/endorse there are other ways than duplicating your credentials.
**Never** use the same account on two daemons.
Docker
~~~~~~
The docker image runs the daemons by default for all your keys.
To know if you baked, just run:
::
./alphanet.sh baker log
./alphanet.sh endorser log
You should see lines such as:
::
Injected block BLxzbB7PBW1axq for bootstrap5 after BLSrg4dXzL2aqq (level 1381, slot 0, fitness 00::0000000000005441, operations 21)
Or:
::
Injected endorsement for block 'BLSrg4dXzL2aqq' (level 1381, slot 3, contract bootstrap5) 'oo524wKiEWBoPD'

View File

@ -0,0 +1,481 @@
.. _howtouse:
How to use Tezos
================
This How To illustrates the use of the various Tezos binaries as well
as some concepts about the network.
The binaries
------------
After a successful compilation, you should have the following binaries:
- ``tezos-node``: the tezos daemon itself;
- ``tezos-client``: a command-line client and basic wallet;
- ``tezos-admin-client``: administration tool for the node;
- ``tezos-{baker,endorser,accuser}-alpha``: daemons to bake, endorse
and accuse on the Tezos network (see :ref:`howtorun`);
- ``tezos-signer``: a client to remotely sign operations or blocks
(see :ref:`signer`);
Note that Alphanet and Zeronet only support the last version of the
protocol which is always called `alpha` while Betanet must also
support all past protocols.
For this reason the name of the 3 daemons in Betanet contains the
incremental number and the partial hash of the protocol they are bound
to, such as ``tezos-{baker,endorser,accuser}-002-PsYLVpVv``.
Read The Friendly Manual
------------------------
The manual of each binary can be obtained with the command ``man`` and
the verbosity can be increased with ``-v``.
To use one specific command, type the command without arguments to see
possible completions and options.
It is also possible to search a keyword in the manual with ``man
keyword``.
The full documentation is also available online :ref:`client_manual`.
::
tezos-client man -v 3
tezos-client transfer
tezos-client man set
Node
----
The node is effectively the Tezos blockchain and it has two main
functions: running the gossip network and the updating the context.
The gossip network is where all Tezos nodes exchange blocks and
operations with each other (see :ref:`tezos-admin-client` to monitor
p2p connections).
Using this peer-to-peer network an operation originated by a user, can
hop several times through other nodes until it finds its way in a
block baked by a baker.
Using the blocks it receives on the gossip network the shell also
keeps up to date the current `context`, that is the full state of
the blockchain shared by all peers.
Approximately every minute a new block is created and, when the shell
receives it, it applies each operation in the block to its current
context and computes a new context.
The last block received on a chain is also called the `head` of that
chain.
Each new head is then advertised by the node to its peers,
disseminating this information to build a consensus across the
network.
Other than passively observing the network, your node can also inject
its own new operations when instructed by the ``tezos-client`` and even
send new blocks when guided by the ``tezos-baker-alpha``.
The node has also a view of the multiple chains that may exist
concurrently and selects the best one based on its fitness (see
:ref:`proof-of-stake`).
Node identity
~~~~~~~~~~~~~
First we need to generate a new identity in order for the node to
connect to the network:
::
tezos-node identity generate
The identity comprises a pair of cryptographic
keys that nodes use to encrypt messages sent to each other, and an
antispam-PoW stamp proving that enough computing power has been
dedicated to creating this identity.
Note that this is merely a network identity and it is not related in
any way to a Tezos address on the blockchain.
Storage
~~~~~~~
All blockchain data is stored under ``$HOME/.tezos-node/``.
If for some reason your node is misbehaving or there has been an
upgrade of the network, it is safe to remove this directory, it just
means that your node will take some time to resync the chain.
You can keep ``identity.json`` if it takes a long time for you to
compute it and only remove the ``store`` and ``context`` directories.
If you are also running a baker make sure that it has access to the
``.tezos-node`` directory of the node.
RPC interface
~~~~~~~~~~~~~
The only interface to the node is through Json RPC calls and it is disabled by
default. A more detailed documentation can be found in the :ref:`RPC index.
<rpc>` The RPC interface must be enabled in order for the clients
to communicate with the node, but is should not be publicly accessible on the
internet. With the following command it is available uniquely on the
`localhost` address of your machine, on the default port ``8732``.
::
tezos-node run --rpc-addr 127.0.0.1
The node listens by default on port ``19732`` so it is advisable to
open incoming connections to that port.
You can read more about the :ref:`node configuration <node-conf>` and
its :ref:`private mode <private-mode>`.
Client
------
Tezos client can be used to interact with the node, it can query its
status or ask the node to perform some actions.
For example after starting your node you can check if it has finished
synchronizing using
::
tezos-client bootstrapped
This call will hang and return only when the node is synchronized.
We can now check what is the current timestamp of the head of the
chain (time is in UTC so it may differ from your local):
::
tezos-client get timestamp
A simple wallet
~~~~~~~~~~~~~~~
The client is also a basic wallet and after the activation above you
will notice that the directory ``.tezos-client`` has been populated with
3 files ``public_key_hashs``, ``public_keys`` and ``secret_keys``.
The content of each file is in json and keeps the mapping between
aliases (``alice`` in our case) and what you would expect from the name
of the file.
Secret keys are stored on disk encrypted with a password except when
using a hardware wallet (see :ref:`ledger`).
An additional file ``contracts`` contains the addresses of `originated
contracts`, which have the form *KT1…*.
We can for example generate a new pair of keys, which can used locally
with the alias *bob*:
::
$ tezos-client gen keys bob
Tezos support three different ECC schemes: *Ed25519*, *secp256k1* (the
one used in Bitcoin), and *P-256* (also called *secp256r1*). The two
latter curves have been added for interoperability with Bitcoin and
Hardware Security Modules (*HSMs*) mostly. Unless your use case
require those, you should probably use *Ed25519*. We use a verified
library for Ed25519, and it is generally recommended over other curves
by the crypto community, for performance and security reasons.
Make sure to make a back-up of this directory and that the password
protecting your secret keys is properly managed.
For more advanced key management we offer :ref:`ledger support
<ledger>` and a :ref:`remote signer<signer>`.
.. _faucet:
Get free tez
~~~~~~~~~~~~
In order to test the networks and help users get familiar with the
system, on Zeronet and Alphanet you can obtain free tez from a
`faucet <https://faucet.tzalpha.net>`__.
This will provide a wallet in the form of a JSON file
``tz1__xxxxxxxxx__.json``, that can be activated with the following
command:
::
tezos-client activate account alice with "tz1__xxxxxxxxx__.json"
If you use the ``alphanet.sh`` script, you should prefix the file
with ``container:`` in order to copy it into the docker image:
``./alphanet.sh client activate account alice with "container:tz1__xxxxxxxxx__.json"``
Let's check the balance of the new account with:
::
tezos-client get balance for alice
Please preserve the JSON file, after each reset of Zeronet or
Alphanet, you will have to reactivate the wallet.
Please drink carefully and don't abuse the faucet: it only contains
30,000 wallets for a total amount of ꜩ760,000,000.
Transactions
~~~~~~~~~~~~
Let's transfer some tez to the new account:
::
tezos-client transfer 1 from alice to bob --fee 0.05
The ``transfer`` command returns a receipt with all the details of the
transaction, including its hash, and then waits for the operation to
be included in one block.
If you want to simulate a transaction without actually sending it to
the network you can use the ``--dry-run`` option.
As in any blockchain it is advisable to wait several blocks to
consider the transaction as final, for an important operation we
advice to wait 60 blocks.
We can do that with:
::
tezos-client wait for <operation hash> to be included
In the rare case when an operation is lost, how can we be sure that it
will not be included in any future block and re-emit it?
After 60 blocks a transaction is considered invalid and can't be
included anymore in a block.
Furthermore each operation has a counter (explained in more detail
later) that prevents replays so it is usually safe to re-emit an
operation that seems lost.
Receipts for operations and blocks
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
After an operation the client prints a `receipt` that recapitulates
the effects of the operation on the blockchain.
It is possible to review the receipt of a transaction with:
::
tezos-client rpc get /chains/main/blocks/head/operations
A manager operation, such as a transaction, has 3 important
parameters: counter, gas and storage limit.
The counter belongs to each account, it increases at each operation
signed by that account and enforces some good intuitive properties:
- each operation is unique: for example if we perform twice the same
transfer from *alice* to *bob*, even if all the data are the
same the counter will be different.
- each operation is applied once: for example if the transfer above
reaches two peers and they both send it to a third peer, it will not
apply the transaction twice.
- operations are applied in order.
- all previous operations have been applied: if we emit operation *n*
and *n+1*, and *n* gets lost then *n+1* cannot be applied.
Additionally each operation needs to declare a gas and storage limit,
if an operation consumes more than these limits it will fail.
Later we'll learn more about the gas and storage model.
Another interesting field of the receipts are the `balance updates`
showing which account was credited or debited.
For the transaction above the updates are symmetrical, *alice* is
debited 1ꜩ and *bob* is credited the same amount.
The same is true for the fees with the difference that the baker is
credited and, more importantly, it is not credited immediately on its
main account but on its frozen fees account, hence the category
`freezer`.
Each delegate has 3 frozen accounts: `deposits`, `fees` and `rewards`.
They are frozen because the delegate can't use them for now, but only
after a number cycles.
It is also possible to review the receipt of the whole block:
::
tezos-client rpc get /chains/main/blocks/head/metadata
Here we always see the deposit that the baker had to put down to bake
the block, which is again a debit on its main account paired with a
credit on its `deposits` account, and the creation of a reward, which
is a single credit to its `rewards` account.
An interesting block receipt is the one produced at the end of a
cycle as many delegates receive back part of their unfrozen accounts.
.. _originated_accounts:
Originated accounts and Contracts
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In Tezos there are two kinds of accounts: *implicit* and *originated*.
The implicit accounts are the *tz1* we have used up to now and to
create them if suffices to have a pair of keys and to transfer some
funds to the public key hash.
Originated accounts have addresses *KT1* and are created through an
origination operation.
One reason to originate an account is to delegate your tokens
(see more :ref:`here. <howtorun>`).
The other main reason is that an originated account can also have
Michelson code, in which case it is called a *contract*.
Let's originate our first contract and call it *id*:
::
tezos-client originate contract id for alice \
transferring 1 from alice \
running ./src/bin_client/test/contracts/id.tz \
--init '"hello"'
We set *alice* as manager, a 1ꜩ starting balance generously provided
by *alice* and the code from the ``id.tz`` Michelson program which
is just the identity.
Every program declares in its first 2 lines the type of its parameter
and storage, for *id* they are both strings so we initialize the
contract with the string ``"hello"`` (the extra quotes are to avoid
the shell expansion).
Gas and storage cost model
~~~~~~~~~~~~~~~~~~~~~~~~~~
A quick look at the balance updates on the receipt shows that on top of
funding the contract with 1ꜩ, *alice* was also charged an extra cost
that is burnt.
This cost comes from the *storage* and is shown in the line
``Paid storage size diff: 46 bytes``, 41 for the contract and 5 for
the string ``"hello"``.
Given that a contract saves its data on the public blockchain that
every node stores, it is necessary to charge a fee per byte to avoid
abuse and encourage lean programs.
Let's see what calling a program with a new argument would look like
with the ``--dry-run`` option:
::
tezos-client transfer 0 from alice to id --arg '"world"' --dry-run
The transaction would successfully update the storage but this time it
wouldn't cost us anything more than the fee, the reason is that the
storage for ``"world"`` is the same as for ``"hello"``, which has
already been paid for.
To store more we'll need to pay more, you can try by passing a longer
string.
The other cost associated with running contracts is the *gas*, which
measures *how long* does a program take to compute.
Contrary to storage there is no cost per gas unit, a transfer can
require as much gas as it wants, however a baker that has to choose
among several transactions is much more likely to include a low gas
one because it's cheaper to run and validate.
At the same time bakers also give priority to high fee transactions.
This means that there is an implicit cost for gas that is related to
the fee offered versus the gas and fees of other transactions.
If you are happy with the gas and storage of your transaction you can
run it for real, however it is always a good idea to set explicit
limit for both. The transaction fails if the limits are passed.
::
tezos-client transfer 0 from alice to id --arg '"world"' \
--gas-limit 1475 \
--storage-limit 46
A baker is more likely to include an operation with lower gas and
storage limits because it takes less resources to execute so it is in
the best interest of the user to pick limits that are as close as
possible to the actual use.
More test contracts can be found in directory
:src:`src/bin_client/test/contracts/`.
An advanced documentation of the smart contract language is available
:ref:`here<michelson>`.
For details and examples, see also https://www.michelson-lang.com/
Validation
~~~~~~~~~~
The node allows to validate an operation before submitting it to the
network by simply simulating the application of the operation to the
current context.
In general if you just send an invalid operation e.g. sending more
tokens that what you own, the node will broadcast it and when it is
included in a block you'll have to pay the usual fee even if it won't
have an affect on the context.
To avoid this case the client first asks the node to validate the
transaction and then sends it.
The same validation is used when you pass the option ``--dry-run``,
the receipt that you see is actually a simulated one.
Another important use of validation is to determine gas and storage
limits.
The node first simulates the execution of a Michelson program and
takes trace of the amount of gas and storage.
Then the client sends the transaction with the right limits for gas
and storage based on that indicated by the node.
This is why we were able to submit transactions without specifying
this limits, they were computed for us.
More information on validation can be found :ref:`here. <validation>`
It's RPCs all the way down
~~~~~~~~~~~~~~~~~~~~~~~~~~
The client communicates with the node uniquely through RPC calls so
make sure that the node is listening and that the ports are
correct.
For example the ``get timestamp`` command above is a shortcut for:
::
tezos-client rpc get /chains/main/blocks/head/header/shell
The client tries to simplify common tasks as much as possible, however
if you want to query the node for more specific informations you'll
have to resort to RPCs.
For example to check the value of important constants in Tezos, which
may differ between Betanet, Alphanet and Zeronet, you can use:
::
tezos-client rpc get /chains/main/blocks/head/context/constants | jq
{
"proof_of_work_nonce_size": 8,
"nonce_length": 32,
"max_revelations_per_block": 32,
"max_operation_data_length": 16384,
"preserved_cycles": 5,
"blocks_per_cycle": 4096,
"blocks_per_commitment": 32,
"blocks_per_roll_snapshot": 256,
"blocks_per_voting_period": 32768,
"time_between_blocks": [
"60",
"75"
],
"endorsers_per_block": 32,
"hard_gas_limit_per_operation": "400000",
"hard_gas_limit_per_block": "4000000",
"proof_of_work_threshold": "70368744177663",
"tokens_per_roll": "10000000000",
"michelson_maximum_type_size": 1000,
"seed_nonce_revelation_tip": "125000",
"origination_burn": "257000",
"block_security_deposit": "48000000",
"endorsement_security_deposit": "6000000",
"block_reward": "0",
"endorsement_reward": "0",
"cost_per_byte": "1000",
"hard_storage_limit_per_operation": "60000"
}
You can find more info in the :ref:`RPCs' page. <rpc>`

View File

@ -0,0 +1,25 @@
.. _support:
Technical Support
=================
If you need help understanding how the Tezos protocol works or if you
have technical questions about the software, here are a few resources
to find answers.
- `This documentation! <http://tezos.gitlab.io/>`_
Make sure to go through this technical documentation before asking
elsewhere, there is also a searchbox on the top left corner.
- Tezos `Stack Exchange <https://tezos.stackexchange.com>`_ is live
(still in beta). If you don't find the answers you are looking for,
feel free to ask questions!
- There is a sub-reddit at https://www.reddit.com/r/tezos/ that is the
main meeting point for the Tezos community, for technical,
economical and just random questions. They also have a nicely
curated list of resources.
- For anything baking related `Obsidian Systems
<https://obsidian.systems>`_ is running a dedicated Slack channel,
contact them to get access.
- There is a *#tezos* IRC channel on *freenode* that is reserved for
technical discussions and is always very active.
- There is a matrix channel *Tezos* that you can join `here <https://riot.im/app/#/room/#tezos:matrix.org>`_.

View File

@ -0,0 +1,613 @@
Various
=======
.. _activate_fundraiser_account:
Activate fundraiser account - Mainnet
-------------------------------------
If you took part in the fundraiser you can activate your account for
the Mainnet on https://check.tezos.com/.
This feature is also included in some wallets.
If you have any question or issue refer to that page or to the `Tezos
foundation <https://tezos.foundation/>`_ for support.
You may also use ``tezos-client`` to activate your account, **be
warned that you should have a very good understanding of key
management in Tezos and be familiar with the command-line.**
The first step is to recover your private key using the following
command which will ask for:
- the email address used during the fundraiser
- the 14 words mnemonic of your paper wallet
- the password used to protect the paper wallet
::
tezos-client import fundraiser key alice
Once you insert all the required information, the client computes
your secret key and it asks to create a new password to store your
secret key on disk encrypted.
If you haven't already activated your account on the website, you can
use this command with the activation code obtained from the Tezos
foundation.
::
tezos-client activate fundraiser account alice with <code>
Like explained above, your keys are stored under ``~/.tezos-client``.
We strongly advice you to first **make a backup** and then
transfer your tokens to a new pair of keys imported from a ledger (see
`ledger`).
Check the balance with:
::
tezos-client get balance for alice
.. _tezos-admin-client:
Admin Client
------------
The admin client gives access to more commands to interact with the
peer-to-peer layer in order to:
- check the status of the connections
- force connections to known peers
- ban/unban peers
A useful command to debug a node that is not syncing is:
::
tezos-admin-client p2p stat
.. _ledger:
Ledger support
--------------
**Disclaimer:** Ledger support is still in development, **the current app
doesn't show all the needed information** for signing securely.
Check frequently for updates.
It is possible and advised to use a hardware wallet to manage your
keys, Tezos' client supports the Ledger Nano S provided that you have
the Tezos app installed.
The app is developed by Obsidian Systems and they provide a comprehensive
`tutorial on how to install it.
<https://github.com/obsidiansystems/ledger-app-tezos>`_
Ledger Manager
~~~~~~~~~~~~~~
The preferred way to set up your Ledger is to install `Ledger
Live
<https://www.ledger.com/pages/ledger-live>`_.
On Linux make sure you correctly set up your `udev` rules as explained
`here <https://github.com/obsidiansystems/ledger-app-tezos#udev-rules-linux-only>`_.
Connect your ledger, unlock it and go the dashboard.
In Ledger Live `install Tezos Wallet` from the applications list and open it on the
device.
Tezos Wallet app
~~~~~~~~~~~~~~~~
Now on the client we can import the keys (make sure the device is
in the Tezos Wallet app):
::
./tezos-client list connected ledgers
You can follow the instructions to import the ledger private key and
you can choose between the root or a derived address.
We can confirm the addition by listing known addresses.
::
./tezos-client import secret key my_ledger ledger://tz1XXXXXXXXXX
./tezos-client list known addresses
Optional: we can check that our ledger signs correctly using the
following command and confirming on the device:
::
tezos-client show ledger path ledger://tz1XXXXXXXXXX
The address can now be used as any other with the exception that
during an operation the device will prompt you to confirm when it's
time to sign an operation.
Tezos Baking app
~~~~~~~~~~~~~~~~
In Ledger Live there is also a `Tezos Baking` app which allows a
delegate to sign non-interactively e.g. there is no need to
manually sign every block or endorsement.
The application however is restricted to sign exclusively blocks and
endorsement operations; it is not possible to sign for example a
transfer.
Furthermore the application keeps track of the last level baked and allows
only to bake for increasing levels.
This prevents signing blocks at levels below the latest
block signed.
If you have tried the app on Alphanet or Zeronet and want to change
network you might need to reset this level with the command:
::
tezos-client set ledger high watermark for ledger://tz1XXXXXXXXXX to 0
.. _private-mode:
Private node
------------
The node can be set in private mode with the option ``--private-mode``
so that:
- it doesn't connects to any peer other than those provided with
``--peer`` or in bootstrap-peers
- the peers connected to a private node don't include it in the list
of peers sent to their neighborhood
This feature is especially useful to hide a sensitive node that signs
operations.
For example we could have a set up with two nodes, a private one
connected uniquely with a public one.
The public node runs on a VPS, connects normally to the network and
keeps an up to date state of the network while the private node runs at
your home and is in charge of injecting and signing operations with a
hardware wallet.
::
tezos-node run --rpc-addr [::] --private-mode \
--no-bootstrap-peers \
--bootstrap-threshold=1 \
--connections 1 \
--peer <public-node-ip>
.. _signer:
Signer
------
Another solution to decouple the node from the signing process is to
use the *remote signer*.
Among the signing scheme supported by the client, that we can list
with ``tezos-client list signing schemes``, there are ``unix``,
``tcp``, ``http`` and ``https``.
These schemes send signing requests over their respective
communication channel towards the ``tezos-signer``, which can run on a
different machine that stores the secret key.
In our home server we can generate a new key pair (or import one from a
:ref:`Ledger<ledger>`) and launch a signer that signs operations using these
keys.
The new keys are store in ``$HOME/.tezos-signer`` in the same format
as ``tezos-client``.
On our internet facing vps we can then import a key with the address
of the signer.
::
home~$ tezos-signer gen keys alice
home~$ cat ~/.tezos-signer/public_key_hashs
[ { "name": "alice", "value": "tz1abc..." } ]
home~$ tezos-signer launch socket signer -a home-ip
vps~$ tezos-client import secret key alice tcp://home-ip:7732/tz1abc...
Every time the client on *vps* needs to sing an operation for
*alice*, it sends a signature request to the remote signer on
*home*.
Note that this setup alone is not secure, **the signer accepts
requests from anybody and happily signs any transaction!**
Secure the connection
~~~~~~~~~~~~~~~~~~~~~
Improving the security of the communication channel can be done at the
system level, setting up a tunnel with ``ssh`` or ``wireguard``
between *home* and *vps*, otherwise the signer already provides an
additional protection.
With the option ``--require-authentication`` the signer requires the
client to authenticate before signing any operation.
First we create a new key on the *vps* and then import it as an
authorized key on *home* where it is stored under
``.tezos-signer/authorized_keys`` (similarly to ``ssh``).
Note that this key is only used to authenticate the client to the
signer and it is not used as a Tezos account.
::
vps~$ tezos-client gen keys vps
vps~$ cat ~/.tezos-client/public_keys
[ { "name": "vps",
"value":
"unencrypted:edpk123456789" } ]
home~$ tezos-signer add authorized key edpk123456789 --name vps
home~$ tezos-signer --require-authentication launch socket signer -a home-ip
All request are now signed with the *vps* key thus you are
guaranteed authenticity and integrity.
This set up **does not guarantee confidentiality**, an evesdropper can
see the transactions that you sign but on a public blockchain this is
less of a concern.
You can still use the ``https`` scheme or the tunnel to encrypt your
traffic.
.. _sandboxed-mode:
Use sandboxed mode
------------------
To run a localhost-only instance of a Tezos network, we provide two
helper scripts:
- ``./src/bin_node/tezos-sandboxed-node.sh``
- ``./src/bin_client/tezos-init-sandboxed-client.sh``
Run a sandboxed node
~~~~~~~~~~~~~~~~~~~~
For instance, if you want to run local network with two nodes, in a
first terminal, the following command will initialize a node listening
for peers on port ``19731`` and listening for RPC on port ``18731``.
::
./src/bin_node/tezos-sandboxed-node.sh 1 --connections 1
This node will store its data in a temporary directory
``/tmp/tezos-node.xxxxxxxx`` which will be removed when the node is
stopped.
The option ``--connections`` is just to remove the spurious “Too few
connections” warnings by lowering the number of expected connection.
To launch the second node, just run the following command, it will
listen on port ``19739`` and ``18739``:
::
./src/bin_node/tezos-sandboxed-node.sh 9 --connections 1
You might replace ``1`` or ``9`` by any number in between if you want to
run more than two nodes.
Use the sandboxed client
~~~~~~~~~~~~~~~~~~~~~~~~
Once your node is running, open a new terminal and initialize the
“sandboxed” client data in a temporary directory:
::
eval `./src/bin_client/tezos-init-sandboxed-client.sh 1`
It also define in the current shell session an alias ``tezos-client``
preconfigured for communicating with the same-numbered node.
When you bootstrap a new network, the network is initialized with a
dummy economic protocol, called `genesis`. If you want to run the same
protocol than the alphanet, ``init-sandboxed-client`` also defines an
alias ``tezos-activate-alpha``, that you need to execute once for
activating the whole network.
For instance:
::
$ tezos-client rpc get /chains/main/blocks/head/metadata
"next_protocol": "Ps9mPmXaRzmzk35gbAYNCAw6UXdE2qoABTHbN2oEEc1qM7CwT9P"
$ tezos-activate-alpha
Injected BMV9KnSPE1yw
$ tezos-client rpc get /chains/main/blocks/head/metadata
"protocol": "Ps9mPmXaRzmzk35gbAYNCAw6UXdE2qoABTHbN2oEEc1qM7CwT9P"
We now have the possibility to send transactions to the sandboxed network.
As the genesis block used to initialize the sandboxed network differs from the
one used in Alphanet and Zeronet, it is not possible to activate
accounts obtained from the faucet. However, we can use the
preconfigured accounts which can be listed with:
::
$ tezos-client list known addresses
activator: tz1TGu6TN5GSez2ndXXeDX6LgUDvLzPLqgYV (unencrypted sk known)
bootstrap5: tz1ddb9NMYHZi5UzPdzTZMYQQZoMub195zgv (unencrypted sk known)
bootstrap4: tz1b7tUupMgCNw2cCLpKTkSD1NZzB5TkP2sv (unencrypted sk known)
bootstrap3: tz1faswCTDciRzE4oJ9jn2Vm2dvjeyA9fUzU (unencrypted sk known)
bootstrap2: tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN (unencrypted sk known)
bootstrap1: tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx (unencrypted sk known)
We can run the following command to transfer some Tez from one account to
another:
::
$ tezos-client transfer 42 from bootstrap1 to bootstrap2 &
...
Waiting for the operation to be included...
You will notice that this command doesn't terminate (hence the ``&``),
as usual it is waiting for the network to include the transaction in a
block.
Given that we are in a sandbox we need to bake a block ourselves and
we can do so with the following command:
::
$ tezos-client bake for bootstrap1
If the previous transaction is valid, the operation is included in the
chain and the transfer terminates returning the usual ticket.
Note that the ``bake for`` command of the client is exclusively for
testing purposes, all baking should be done using the ``tezos-baker``
binary.
Tune protocol alpha parameters
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The ``tezos-active-alpha`` alias use parameters from
``scripts/protocol_parameters.json`` to activate protocol alpha. It can
be useful to tune these parameters when you need to debug something,
for example, change the number of blocks per cycle, the time between
blocks, etc.
.. _node-conf:
Configuration options for the node
----------------------------------
::
./tezos-node config init
This will initialize a configuration file for the node in
`$HOME/.tezos-node/config.json`, using default values. It only
specifies that the node will listen to incoming connections on socket
address ``[::]:9732``.
The easiest way to amend this default configuration is to use
::
# Update the config file
./tezos-node config update <…>
# Start from an empty cfg file
./tezos-node config reset <…>
All blockchain data is stored under ``$HOME/.tezos-node/``. You can
change this by doing `./tezos-node config update --data-dir
</somewhere/in/your/disk>`.
To run multiple nodes on the same machine, you can duplicate and edit
``$HOME/.tezos-node/config.json`` while making sure they don't share
the same ``data-dir``. Then run your node with `./tezos-node
run --config-file=</path/to/alternate_cfg>`.
Here is an example configuration file with all parameters specified.
Most of the time it uses default values, except for cases where the
default is not explanatory enough (i.e. “bootstrap-peers” is an empty
list by default). Comments are not allowed in JSON, so this
configuration file would not parse. They are just provided here to help
writing your own configuration file if needed.
::
{
/* Location of the data dir on disk. */
"data-dir": "/home/tezos/my_data_dir"
/* Configuration of net parameters */
"net": {
/* Floating point number between 0 and 256 that represents a
difficulty, 24 signifies for example that at least 24 leading
zeroes are expected in the hash. */
"expected-proof-of-work": 24.5,
/* List of hosts. Tezos can connect to both IPv6 and IPv4
hosts. If the port is not specified, default port 9732 will be
assumed. */
"bootstrap-peers": ["::1:10732", "::ffff:192.168.1.3:9733", "mynode.tezos.com"],
/* Specify if the node is in private mode or not. A node in
private mode only opens outgoing connections to peers whose
addresses are in [trusted_peers] and only accepts incoming
connections from trusted peers. In addition, it informs these
peers that the identity of the node should not be revealed to
the rest of the network. */
"private-mode": false,
/* Network limits */
"limits": {
/* Delay granted to a peer to perform authentication, in
seconds. */
"authentication-timeout": 5,
/* Strict minimum number of connections (triggers an urgent
maintenance). */
"min-connections": 50,
/* Targeted number of connections to reach when bootstrapping /
maintaining. */
"expected-connections": 100,
/* Maximum number of connections (exceeding peers are
disconnected). */
"max-connections": 200,
/* Number above which pending incoming connections are
immediately rejected. */
"backlog": 20,
/* Maximum allowed number of incoming connections that are
pending authentication. */
"max-incoming-connections": 20,
/* Max download and upload speeds in KiB/s. */
"max-download-speed": 1024,
"max-upload-speed": 1024,
/* Size of the buffer passed to read(2). */
"read-buffer-size": 16384,
}
},
/* Configuration of rpc parameters */
"rpc": {
/* Host to listen to. If the port is not specified, the default
port 8732 will be assumed. */
"listen-addr": "localhost:8733",
/* Cross Origin Resource Sharing parameters, see
https://en.wikipedia.org/wiki/Cross-origin_resource_sharing. */
"cors-origin": [],
"cors-headers": [],
/* Certificate and key files (necessary when TLS is used). */
"crt": "tezos-node.crt",
"key": "tezos-node.key"
},
/* Configuration of log parameters */
"log": {
/* Output for the logging function. Either "stdout", "stderr" or
the name of a log file . */
"output": "tezos-node.log",
/* Verbosity level: one of 'fatal', 'error', 'warn', 'notice',
'info', 'debug'. */
"level": "info",
/* Fine-grained logging instructions. Same format as described in
`tezos-node run --help`, DEBUG section. In the example below,
sections "net" and all sections starting by "client" will have
their messages logged up to the debug level, whereas the rest of
log sections will be logged up to the notice level. */
"rules": "client* -> debug, net -> debug, * -> notice",
/* Format for the log file, see
http://ocsigen.org/lwt/dev/api/Lwt_log_core#2_Logtemplates. */
"template": "$(date) - $(section): $(message)"
},
/* Configuration for the validator and mempool parameters */
"shell": {
/* The number of peers to synchronize with
before declaring the node 'bootstrapped'. */
"bootstrap_threshold": 4
}
}
Environment for writing Michelson contracts
-------------------------------------------
Here is how to setup a practical environment for
writing, editing and debugging Michelson programs.
Install `Emacs <https://www.gnu.org/software/emacs/>`_ with
the `deferred <https://github.com/kiwanami/emacs-deferred>`_ and
`exec-path-from-shell
<https://github.com/purcell/exec-path-from-shell>`_ packages.
The packages can be installed from within Emacs with
``M-x package-install``.
The last package imports the shell path in Emacs and it is needed
because we will run a sandboxed node.
Set up the `Michelson mode
<https://gitlab.com/tezos/tezos/tree/master/emacs>`_ by adding in
your ``.emacs`` :
::
(load "~/tezos/tezos/emacs/michelson-mode.el" nil t)
(setq michelson-client-command "tezos-client")
(setq michelson-alphanet nil)
Note that the Michelson mode will be chosen automatically by Emacs for
files with a ``.tz`` or ``.tez`` extension.
Run a :ref:`sandboxed node<sandboxed-mode>` (and activate the alphanet
protocol with ``tezos-activate-alpha``) so that useful information
about the program can be displayed.
We can now open our favourite contract ``emacs
./src/bin_client/test/contracts/id.tz`` and, when moving the cursor on
a Michelson instruction, in the bottom of the windows Emacs should
display the state of the stack before (left) and after (right) the
application of the instruction.
The Emacs mode automatically type-checks your program and reports
errors; once you are happy with the result you can ask the client to
run it locally:
::
tezos-client run script ./src/bin_client/test/contracts/id.tz \
on storage '"hello"' and input '"world"'
Debugging
---------
It is possible to set independent log levels for different logging
sections in Tezos, as well as specifying an output file for logging. See
the description of log parameters above as well as documentation under
the DEBUG section displayed by `tezos-node run -help`.

129
vendors/tezos-modded/docs/logo.svg vendored Normal file
View File

@ -0,0 +1,129 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="48.739811mm"
height="22.914806mm"
viewBox="0 0 48.739811 22.914806"
version="1.1"
id="svg5074"
inkscape:version="0.92.1 r15371"
sodipodi:docname="logo.svg">
<defs
id="defs5068" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="5.6"
inkscape:cx="152.39587"
inkscape:cy="33.859768"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="2560"
inkscape:window-height="1311"
inkscape:window-x="0"
inkscape:window-y="55"
inkscape:window-maximized="1"
inkscape:measure-start="71.0714,60.5357"
inkscape:measure-end="109.286,25.8929"
inkscape:snap-bbox="true"
inkscape:bbox-paths="true" />
<metadata
id="metadata5071">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-58.404451,-81.16997)">
<path
style="opacity:1;fill:#4d4d4d;fill-opacity:1;stroke-width:1.22451675"
d="m 61.072266,-14.291016 a 32.000002,32.000002 0 0 0 -32,32 32.000002,32.000002 0 0 0 32,32 h 1.21289 94.751954 1.21289 a 32.000002,32.000002 0 0 0 32,-32 32.000002,32.000002 0 0 0 -32,-32 h -1.21289 -94.751954 z"
transform="matrix(0.26458333,0,0,0.26458333,56.807283,87.908796)"
id="path4516"
inkscape:connector-curvature="0" />
<circle
style="opacity:1;fill:#000000;fill-opacity:1;stroke-width:0.35944793"
id="path4529"
cx="69.861855"
cy="92.627373"
r="11.457403" />
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:18.16365242px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.45409128"
x="64.233612"
y="94.434319"
id="text5621"
transform="scale(0.98259142,1.017717)"><tspan
sodipodi:role="line"
id="tspan5619"
x="64.233612"
y="94.434319"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Code2000;-inkscape-font-specification:Code2000;fill:#ffffff;stroke-width:0.45409128">ꜩ</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:10.58333302px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
x="84.777519"
y="86.395416"
id="text5633"><tspan
sodipodi:role="line"
x="84.777519"
y="95.759186"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.88055563px;line-height:0;font-family:sans-serif;-inkscape-font-specification:sans-serif;stroke-width:0.26458332"
id="tspan5650" /></text>
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:3.88055563px;line-height:1.25;font-family:sans-serif;text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.26458332"
x="91.852211"
y="95.18335"
id="text5660"><tspan
sodipodi:role="line"
x="91.852211"
y="95.18335"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0;font-family:Lato;-inkscape-font-specification:Lato;text-align:center;text-anchor:middle;fill:#ffffff;stroke-width:0.26458332"
id="tspan4521">Developer</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:3.88055563px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
x="83.283157"
y="98.462372"
id="text4535"><tspan
sodipodi:role="line"
id="tspan4533"
x="83.283157"
y="98.462372"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Lato;-inkscape-font-specification:Lato;fill:#ffffff;stroke-width:0.26458332">Resources</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:3.88055563px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
x="85.401657"
y="90.288643"
id="text4541"><tspan
sodipodi:role="line"
id="tspan4539"
x="85.401657"
y="90.288643"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.93888903px;font-family:'Roboto Slab';-inkscape-font-specification:'Roboto Slab';fill:#ffffff;stroke-width:0.26458332">Tezos</tspan></text>
</g>
</svg>

After

Width:  |  Height:  |  Size: 5.6 KiB

View File

@ -0,0 +1,236 @@
.. _proto_003:
Protocol 003_PsddFKi3
=====================
Description of the patch
------------------------
Fix to prevent account creation spam
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
While creating accounts currently requires a .257 tez burn, there is
currently no cost to create implicit accounts, despite them occupying
space in the context.
This patch adjusts the cost to .257 tez for both regular (KT1) and
implicit (tz1) accounts.
Error handling for nonce revelation
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In cycle 48, a baker who lost their deposits and rewards due to double
baking also did not inject nonce revelation. The protocol reached an
error condition after trying to take away rewards from an account for
which rewards had already been slashed. As a result, no new blocks
could be accepted unless the nonces were revealed. The patch ensures
correct handling of this scenario.
Add RPCs for voting
~~~~~~~~~~~~~~~~~~~
This patch introduces RPCs to query ballot status, functionality
needed by bakers to interact with proposals to amend the protocol.
They are the following::
Sum of ballots cast so far during a voting period.
GET /chains/<chain_id>/blocks/<block_id>/votes/ballots
Ballots cast so far during a voting period.
GET /chains/<chain_id>/blocks/<block_id>/votes/ballot_list
Current period kind: proposal, testing_vote, testing, promotion_vote.
GET /chains/<chain_id>/blocks/<block_id>/votes/current_period_kind
Current expected quorum.
GET /chains/<chain_id>/blocks/<block_id>/votes/current_quorum
List of delegates with their voting weight, in number of rolls.
GET /chains/<chain_id>/blocks/<block_id>/votes/listings
List of proposals with number of supporters.
GET /chains/<chain_id>/blocks/<block_id>/votes/proposals
Current proposal under evaluation.
GET /chains/<chain_id>/blocks/<block_id>/votes/current_proposal
Correct accounting for approval voting
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The current protocol does not properly count baking rolls during the
approval voting phase. This is corrected in this version.
How to apply the patch
----------------------
If compiling from source, please pull the latest code from the mainnet
branch. From a clone of the git repository, a minimal update command
is ``git checkout mainnet && git pull && eval $(opam env) && make
build-deps && make``.
Tezos binaries (node, client, baker, endorser, etc) should not be
running while you re-compile.
If using the script ``mainnet.sh`` based on docker provided at
https://gitlab.com/tezos/tezos, simply do ``./mainnet.sh restart`` as
every call to mainnet.sh checks for updates and updates if necessary.
The node will automatically switch over to the new protocol at block
height **204762** expected to occur after 2018-11-26T17:30:00 UTC.
After updating, all processes (the node, baker, endorser, and accuser)
should be restarted. The updated node handles multiple protocols but
notice that there are several, protocol-specific, versions of every
other processes.
In order not to miss a block or an endorsement, you may run versions
002_PsYLVpVv and 003_PsddFKi3 of the baker and endorser in parallel.
Versions 003_PsddFKi3 of the baking and endorsement processes will not
start baking or endorsing until the target block height. Version
002_PsYLVpVv will stop by themselves and it will be safe to stop them
at that time. This has been tested and the processes do not attempt to
bake at the same height.
However, as an extra precaution, specially if you do not use a
hardware key or a remote-signer with a high water-mark, you may
consider waiting until the target block height to shut down the old
process and start the new one.)
More details on fees and cost model
-----------------------------------
Protocol:
~~~~~~~~~
The creation of a new tz{1,2,3} address now requires a burn of `ꜩ0.257`,
in-line with the creation of KT account.
Every manager operation now costs at least ``10000`` in gas,
a transaction has a default cost of ``10100`` in gas.
Example::
Reveal:
Consumed gas: 10000
Consumed storage: 0 bytes
Transaction (when the target tz{1,2.3} is empty).
Consumed gas: 10100
Consumed storage: 277 bytes
Transaction (when the target tz{1,2.3} is not empty).
Consumed gas: 10100
Consumed storage: 0 bytes
Baker
~~~~~
The baker and mempool filters now require a minimal fee to propagate
and include operations into blocks. This default is not set at the
protocol level but rather in the configuration of the node and the baker.
Bakers can thus decide of the settings that work best for them
The minimal fee depends on the operation sent (transaction, origination,
revelation, etc)
When considering the injection of an operation in a block, the baker
will check its size and gas and reject it if the associated fees are
too low.
The expected fees are computed using this formula::
fees >= (minimal_fees + minimal_nanotez_per_byte * size + minimal_nanotez_per_gas_unit * gas)
Where the size is the number of bytes of the complete serialized
operation, i.e. including header and signature.
When sending multiple transactions at once (i.e. packed operations),
the baker will require the summed fees of all the operations to match
the summed gas of all the operations and the total size of the packed
operations, still including header and signature.
By default::
minimal_fees = 0.000 1 ꜩ (100 µꜩ)
minimal_nanotez_per_gas_unit = 100 nꜩ/gu (0.000 000 1 ꜩ/gu)
minimal_nanotez_per_byte = 1000 nꜩ/B (0.000 001 ꜩ/B)
For instance, a single transaction to an existing implicit address
will require a transaction fee of at least `0.001 273 ꜩ`
to be included by bakers who choose to follow the default settings.
These settings may be changed by passing the following flags to the baker
(``--minimal-fees <amount in tez>``,
``--minimal-nanotez-per-gas-unit <amount in nanotez>``,
``--minimal-nanotez-per-byte <amount in nanotez>``).
Delegates distributing rewards should be aware of these thresholds
for their transactions to be successfully included.
Node
~~~~
The node also filters operations following the same principles as
above. If an operation does not carry sufficient fees, a node
following the default setting will not include it in its mempool.
Hence an operation without fee won't even propagate through
the network. The constant can be changed with the following RPC
call::
./tezos-client rpc post /chains/main/mempool/filter with '{ "minimal_fees": "0", "minimal_nanotez_per_gas_unit": "0", "minimal_nanotez_per_byte": "0" }'
The constants used by the node and the baker do not need to be equal,
but the node needs to be less restrictive than the baker, otherwise
the baker won't even see the operations.
An injection node (i.e. a specific node targeted by wallet for
injection operation) might deactivate the filter (by using the
previous RPC call) in order to accept any operation and give them a
chance to be propagated to a baker that is willing to accept fee-less
operations.
FAQ
---
Q. Who should apply this patch?
A. Anyone running a node needs to update. If you are using a wallet
that connects to a third party node, you do not need to apply a
patch, but you can inquire with the wallet developers to make sure
they are running a patched node. If you are delegating your tez you
may wish to inquire with your baker that he is running the patched
node in order not to miss any reward.
Q. What are the risks and impact of account creation spam?
A. Over time, account creation spam can make it uneconomical to run a
node due to the amount of disk space required. This would make it
harder for people to participate in the ecosystem.
Q. What happens if I apply the patch early?
A. The patch will automatically activate at a set block-height.
Specifically, block height 204762 (approximately Monday Nov 26 1730
UTC)
Q. What happens if I don't apply the patch?
A. Your node will continue tracking a branch with a known bug which
does not represent the consensus among network participants.
Q. Why not use the governance mechanism to correct these issues?
A. The governance mechanism is a slow, deliberative, procedure for
deciding on the evolution of the code. It is not a substitute for
security patches which require quick deployment.
Q. Why not mandate minimal transaction fees in the protocol?
A. Transaction fees solve a slightly different problem, but they can
help. If bakers wish to filter out transaction with low fees, they
can run the process by passing the flag::
--minimal-fees (default 0.000 1)
--minimal-nanotez-per-byte (default 1000)
--minimal-nanotez-per-gaz-unit (default 100)
1 mutez is equivalent to 1000 nanotez. The patch does include
default minimal fees in the mempool, but individual bakers can
choose to override these.

View File

@ -0,0 +1,207 @@
.. _data_encoding:
The ``data_encoding`` library
=============================
Throughout the Tezos protocol, data is serialized so that it can be used
via RPC, written to disk, or placed in a block. This
serialization/de-serialization is handled via the :package:`tezos-data-encoding`
library by providing a set primitive encodings and a variety of combinators.
Examples/Tutorial
-----------------
Encoding an integer
~~~~~~~~~~~~~~~~~~~
Integers are defined as other concrete data types with a generic
encoding type ``type 'a encoding``. This means that it is an encoding
to/from type ``int``. There are a variety of ways to encode an integer,
depending on what binary serialization you want to achieve:
- ``Data_encoding.int8``
- ``Data_encoding.uint8``
- ``Data_encoding.int16``
- ``Data_encoding.uint16``
- ``Data_encoding.int31``
- ``Data_encoding.int32``
- ``Data_encoding.int64``
For example, an encoding that represents a 31 bit integer has type
``Data_encoding.int31 = int Data_encoding.encoding``.
.. code:: ocaml
let int31_encoding = Data_encoding.int31
Encoding an object
~~~~~~~~~~~~~~~~~~
Encoding a single integer is fairly uninteresting. The `Data_encoding`
library provides a number of combinators that can be used to build more
complicated objects. Consider the type that represents an interval from
the first number to the second:
.. code:: ocaml
type interval = int64 * int64
We can define an encoding for this type as:
.. code:: ocaml
let interval_encoding =
Data_encoding.(obj2 (req "min" int64) (req "max" int64))
In the example above we construct a new value ``interval_encoding`` by
combining two `int64` integers using the ``obj2`` (object with two fields)
constructor.
The library provides different constructors, i.e. for objects that have
no data (``Data_encoding.empty``), constructors for object up to 10
fields, constructors for tuples, list, etc.
These are serialized to binary by converting each internal object to
binary and placing them in the order of the original object and to JSON
as a JSON object with field names.
Lists, arrays, and options
~~~~~~~~~~~~~~~~~~~~~~~~~~
List, arrays and options types can by built on top of ground data types.
.. code:: ocaml
type interval_list = interval list
type interval_array = interval array
type interval_option = interval option
And the encoders for these types as
.. code:: ocaml
let interval_list_encoding = Data_encoding.list interval_encoding
let interval_array_encoding = Data_encoding.array interval_encoding
let interval_option_encoding = Data_encoding.option interval_encoding
Union types
~~~~~~~~~~~
The Tezos codebase makes heavy use of variant types. Consider the
following variant type:
.. code:: ocaml
type variant = B of bool
| S of string
Encoding for this types can be expressed as:
.. code:: ocaml
let variant_encoding =
Data_encoding.(union ~tag_size:`Uint8
[ case
bool
(function B b -> Some b | _ -> None)
(fun b -> B b) ;
case
string
(function S s -> Some s | _ -> None)
(fun s -> S s) ])
This variant encoding is a bit more complicated. Lets look at the parts
of the encoding:
- We include an optimization hint to the binary encoding to inform it
of the number of elements we expect in the tag. In most cases, we can
use :literal:`\`Uint8`, which allows you to have up to 256 possible
cases (default).
- We provide a function to wrap the datatype. The encoding works by
repeatedly trying to decode the datatype using these functions until
one returns ``Some payload``. This payload is then encoded using the
dataencoding specified.
- We specify a function from the encoded type to the actual datatype.
Since the library does not provide an exhaustive check on these
constructors, the user must be careful when constructing union types to
avoid unfortunate runtime failures.
How the Dataencoding module works
---------------------------------
This section is 100% optional. You do not need to understand this
section to use the library.
The library uses GADTs to provide type-safe
serialization/de-serialization. From there, a runtime representation of
JSON objects is parsed into the type-safe version.
First we define an untyped JSON AST:
.. code:: ocaml
type json =
[ `O of (string * json) list
| `Bool of bool
| `Float of float
| `A of json list
| `Null
| `String of string ]
This is then parsed into a typed AST (we eliminate several cases for
clarity):
.. code:: ocaml
type 'a desc =
| Null : unit desc
| Empty : unit desc
| Bool : bool desc
| Int64 : Int64.t desc
| Float : float desc
| Bytes : Kind.length -> MBytes.t desc
| String : Kind.length -> string desc
| String_enum : Kind.length * (string * 'a) list -> 'a desc
| Array : 'a t -> 'a array desc
| List : 'a t -> 'a list desc
| Obj : 'a field -> 'a desc
| Objs : Kind.t * 'a t * 'b t -> ('a * 'b) desc
| Tup : 'a t -> 'a desc
| Union : Kind.t * tag_size * 'a case list -> 'a desc
| Mu : Kind.enum * string * ('a t -> 'a t) -> 'a desc
| Conv :
{ proj : ('a -> 'b) ;
inj : ('b -> 'a) ;
encoding : 'b t ;
schema : Json_schema.schema option } -> 'a desc
| Describe :
{ title : string option ;
description : string option ;
encoding : 'a t } -> 'a desc
| Def : { name : string ;
encoding : 'a t } -> 'a desc
- The first few constructors define all ground types.
- The constructors for ``Bytes``, ``String`` and ``String_enum``
include a length field in order to provide safe binary
serialization.
- The constructors for ``Array`` and ``List`` are used by the
combinators we saw earlier.
- The ``Obj`` and ``Objs`` constructors create JSON objects. These are
wrapped in the ``Conv`` constructor to remove nesting that results
when these constructors are used naively.
- The ``Mu`` constructor is used to create self-referential
definitions.
- The ``Conv`` constructor allows you to clean up a nested definition
or compute another type from an existing one.
- The ``Describe`` and ``Def`` constructors are used to add
documentation
The library also provides various wrappers and convenience functions to
make constructing these objects easier. Reading the documentation in the
`mli file
<../api/odoc/tezos-data-encoding/Tezos_data_encoding/Data_encoding/index.html>`__
should orient you on how to use these functions.

View File

@ -0,0 +1,199 @@
.. _entering_alpha:
How to start reading protocol Alpha
===================================
Protocol Alpha, whose Alpha has nothing to do with the one in Alphanet,
is the name of the initial economic protocol. Alpha is a placeholder
name, while we decide on the naming convention for protocol versions.
Before reading that document, you may want to:
- read the whitepaper,
- read :ref:`how the economic protocol is
sandboxed <protocol_environment>`.
As all protocols, Alpha is made of a series of OCaml interface and
implementation files, accompanied by a ``TEZOS_PROTOCOL`` file.
The ``TEZOS_PROTOCOL`` structure
--------------------------------
If you look at this file in the repository, you will see that it is
composed of the hash of the sources, and the list of its modules, in
linking order.
Protocol Alpha is structured as a tower of abstraction layers, a coding
discipline that we designed to have OCaml check as many invariants as
possible at typing time. You will also see empty lines in
``TEZOS_PROTOCOL`` that denote these layers of abstraction.
These layers follow the linking order: the first modules are the towers
foundation that talk to the raw key-value store, and going forward in
the module list means climbing up the abstraction tower.
The big abstraction barrier: ``Alpha_context``
----------------------------------------------
The proof-of-stake algorithm, as described in the white paper, relies on
an abstract state of the ledger, that is read and transformed during
validation of a block.
Due to the polymorphic nature of Tezos, the ledgers state (that we call
**context** in the code), cannot be specific to protocol Alphas need.
The proof-of-stake is thus implemented over a generic key-value store
whose keys and associated binary data must implement the abstract
structure.
The ``Alpha_context`` module enforces the separation of concerns
between, on one hand, mapping the abstract state of the ledger to the
concrete structure of the key-value store, and, on the other hand,
implementing the proof-of-stake algorithm over this state.
In more practical terms, ``Alpha_context`` defines a type ``t`` that
represents a state of the ledger. This state is an abstracted out
version of the key-value store that can only be manipulated through the
use of the few selected manipulations reexported by ``Alpha_context``,
that always preserve the well-typed aspect and internal consistency
invariants of the state.
When validating a block, the low-level state that result from the
predecessor block is read from the disk, then abstracted out to a
``Alpha_context.t``, which is then only updated by high level operations
that preserve consistency, and finally, the low level state is extracted
to be committed on disk.
This way, we have two well separated parts in the code. The code below
``Alpha_context`` implements the ledgers state storage, while the code
on top of it is the proof-of-stake algorithm. Thanks to this barrier,
the latter can remain nice, readable OCaml that only manipulates plain
OCaml values.
Below the ``Alpha_context``
---------------------------
For this part, in a first discovery of the source code, you can start by
relying mostly on this coarse grained description, with a little bit of
cherry-picking when youre curious about how a specific invariant is
enforced.
The ``*_repr`` modules
~~~~~~~~~~~~~~~~~~~~~~
These modules abstract the values of the raw key-value context by using
:ref:`Data_encoding<data_encoding>`.
These modules define the data types used by the protocol that need to be
serialized (amounts, contract handles, script expressions, etc.). For
each type, it also defines its serialization format using
:ref:`Data_encoding<data_encoding>`.
Above this layer, the code should never see the byte sequences in the
database, the ones of transmitted blocks and operations, or the raw JSON
of data transmitted via RPCs. It only manipulates OCaml values.
The ``Storage`` module and storage functors
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Even with the concrete formats of values in the context abstracted out,
type (or consistency) errors can still occur if the code accesses a
value with a wrong key, or a key bound to another value. The next
abstraction barrier is a remedy to that.
The storage module is the single place in the protocol where key
literals are defined. Hence, it is the only module necessary to audit,
to know that the keys are not colliding.
It also abstracts the keys, so that each kind of key get its own
accessors. For instance, module ``Storage.Contract.Balance`` contains
accessors specific to contracts balances.
Moreover, the keys bear the type of the values they point to. For
instance, only values of type ``Tez_repr.t`` can by stored at keys
``Storage.Contract.Balance``. And in case a key is not a global key, but
a parametric one, this key is parameterized by an OCaml value, and not the
raw key part.
So in the end, the only way to be used when accessing a contract balance
is ``Storage.Contract.Balance.get``, which takes a ``Contract_repr.t``
and gives a ``Tez_repr.t``.
All these well-typed operations are generated by a set of functors, that
come just before ``Storage`` in ``TEZOS_CONTEXT``.
The ``*_storage`` modules
~~~~~~~~~~~~~~~~~~~~~~~~~
The two previous steps ensure that the ledgers state is always accessed
and updated in a well-typed way.
However, it does not enforce that, for instance, when a contract is
deleted, all of the keys that store its state in the context are indeed
deleted.
This last series of modules named ``*_storage`` is there to enforce just
that kind of invariants: ensuring the internal consistency of the
context structure.
These transaction do not go as far as checking that, for instance, when
the destination of a transaction is credited, the source is also
debited, as in some cases, it might not be the case.
Above the ``Alpha_context``
---------------------------
The three next sections describe the main entrypoints to the protocol:
validation of blocks by the shell (that we often also call application),
smart contracts, and RPC services.
The ``Main`` module is the entrypoint thats used by the shell. It
respects the module type that all protocol must follow. For that, its
code is mostly plumbing,
Starting from ``Apply``
~~~~~~~~~~~~~~~~~~~~~~~
This is were you want to start on your first read. Even if some plumbing
code is woven in, such as error cases declaration and registration, most
of the proof-of-stake code has been written in a verbose style, to be
understood with minimum OCaml knowledge.
You want to start from the shell entry points (validation of the block
header, validation of an operation, finalization of a block validation),
and follow the control flow until you hit the ``Alpha_context``
abstraction barrier. This will lead you to reading modules ``Baking``
and ``Amendment``.
Smart contracts
~~~~~~~~~~~~~~~
From ``Apply``, you will also end up in modules ``Script_ir_translator``
and ``Script_interpreter``. The former is the typechecker of Michelson
that is called when creating a new smart contract, and the latter is the
interpreter that is called when transferring tokens to a new smart
contract.
Protocol RPC API
~~~~~~~~~~~~~~~~
Finally, the RPCs specific to Alpha are also defined above the
``Alpha_context`` barrier.
Services are defined in a few modules, divided by theme. Each module
defines the RPC API: URL schemes with the types of parameters, and
input and output JSON schemas. This interface serves three
purposes. As it is thoroughly typed, it makes sure that the handlers
(that are registered in the same file) have the right input and output
types. It is also used by the client to perform RPC calls, to make
sure that the URL schemes and JSON formats and consistent between the
two parties. These two features are extremely useful when refactoring,
as the OCaml typechecker will help us track the effects of an RPC API
change on the whole codebase. The third purpose is of course, to make
automatic documentation generation possible (as in ``tezos client rpc
list/format``). Each service is also accompanied by a caller function,
that can be used from the client to perform the calls, and by the
tests to simulate calls in a fake in-memory context.
It can be useful if you are a third party developer who wants to read
the OCaml definition of the service hierarchy directly, instead of the
automatically generated JSON hierarchy.

View File

@ -0,0 +1,366 @@
.. _error_monad:
The Error Monad
===============
This has been adapted from a blog post on *michelson-lang.com*.
If youre not familiar with monads, go take a few minutes and read a
tutorial. I personally got a lot out of this
`paper <http://homepages.inf.ed.ac.uk/wadler/papers/marktoberdorf/baastad.pdf>`__
by Philip Wadler, but there are a ton of others available online. Find
one that works for you. The error monad isnt terribly scary as Monads
go, so once you feel like you understand the gist, come on back and see
if you can understand whats going on.
Im going to omit some convenience operations that a lot of monads
provide in the examples below. If you want to add them, theyre not
difficult.
Why you want the error monad
----------------------------
In Tezos, we dont want to have the node be crashable by an improper
input. To avoid this possibility, it was decided that the system should
not use exceptions for error handling. Instead, it uses an error monad.
This design forces errors to be handled or carried through before an
output can be used. Exceptions are still occasionally used, but this is
mostly in the client and only for internal errors.
We also mix in the Lwt library, which we use for concurrency. This is
combined with the error monad and is once again used pervasively
throughout the codebase. The Lwt monad is a lot like promises in other
languages.
Without further ado, lets write an error monad.
A simple version of the error monad
-----------------------------------
Heres a very simple error monad.
.. code:: ocaml
module Error : sig
type 'a t
(* Create a value of type t *)
val return : 'a -> 'a t
(* For when a computation fails *)
val error : 'a t
(* Apply an operation to a value in the error monad *)
val (>>?) : 'a t -> ('a -> 'b t) -> 'b t (* bind *)
end = struct
type 'a t = Ok of 'a | Error
let return x = Ok x
let error = Error
let (>>?) value func =
match value with
| Ok x -> func x
| Error -> Error
end
So, is this what Tezos uses? We actually already have a lot of the
structure that well use later. The basic idea is that you return a
value thats correct and return an error if the operation failed.
Outside of the error module, you cant actually introspect an error
value. You can only dispatch on the correctness/incorrectness of the
value using bind.
Whats wrong here?
- We cant report any information about an error case
- We cant report error traces, something thats used to improve the
quality of error messages throughout Tezos
- We cant handle some errors and continue executing
A slight improvement
--------------------
Lets now enhance our error reporting by allowing errors to contain a
description string. Now we can report messages along with our errors. Is
this enough of an improvement? Not really. We dont have any flexibility
about how the printing works. We still cant create error traces and we
cant handle errors and resume executing the program.
.. code:: ocaml
module Error : sig
type 'a t
val return : 'a -> 'a t
val error : string -> 'a t
val (>>?) : 'a t -> ('a -> 'b t) -> 'b t (* bind *)
val print_value : ('a -> string) -> 'a t -> unit
end = struct
type 'a t = Ok of 'a | Error of string
let return x = Ok x
let error s = Error s
let (>>?) value func =
match value with
| Ok x -> func x
| Error s -> Error s
let print_value func = function
| Ok x -> Printf.printf "Success: %s\n" (func x)
| Error s -> Printf.printf "Error: %s\n" s
end
Traces
------
Now that we have the basic structure down, we can add a mechanism to let
us include traces. As a note, the error type I had above is exactly the
``result`` type from the OCaml standard library. The traces are just
lists of error messages. If you have a call you think might fail, and
you want to provide a series of errors, you can wrap that result in the
``trace`` function. If that call fails, an additional error is added.
.. code:: ocaml
module Error : sig
type 'a t
val return : 'a -> 'a t
val error : string -> 'a t
val (>>?) : 'a t -> ('a -> 'b t) -> 'b t (* bind *)
val print_value : ('a -> string) -> 'a t -> unit
val trace : string -> 'a t -> 'a t
end = struct
type 'a t = ('a, string list) result
let return x = Ok x
let error s = Error [ s ]
let (>>?) value func =
match value with
| Ok x -> func x
| Error errs -> Error errs
let print_value func = function
| Ok x -> Printf.printf "Success: %s\n" (func x)
| Error [ s ] -> Printf.printf "Error: %s\n" s
| Error errors -> Printf.printf "Errors:\t%s\n" (String.concat "\n\t" errors)
let trace error = function
| Ok x -> Ok x
| Error errors -> Error (error :: errors)
end
A more descriptive message
--------------------------
Even though traces are nice, we really want to be able to store more
interesting data in the messages. Were going to use an extensible
variant type to do this. Extensible variants allow us to add a new case
to a variant type at the cost of exhaustivity checking. Were going to
need two new mechanisms to make this work well. The first is an error
registration scheme. In the actual error monad, this involves the data
encoding module, which is how all data is encoded/decoded in Tezos. This
module is another decently complicated part of the codebase that should
probably the subject of a future post. Since you can declare arbitrary
new errors, well have a way of adding a printer for each error.
When we add a new error handler, well use the ``register_handler``
function. This function will take a function that takes an error and
returns a ``string option``. These functions will look something like
this:
.. code:: ocaml
type error += Explosion_failure of string * int;;
register_error
(function
| Explosion_failure (s, i) ->
Some (Printf.sprintf "Everything exploded: %s at %d" s i)
| _ -> None)
Im also renaming the ``error`` function to ``fail``. This is the
convention used by the actual `Error_monad` module. Im also exposing the
``'a t`` type so that you can dispatch on it if you need to. This is
used several times in the Tezos codebase.
.. code:: ocaml
module Error : sig
type error = ..
type 'a t = ('a, error list) result
val return : 'a -> 'a t
val fail : error -> 'a t
val (>>?) : ('a -> 'b t) -> 'a t -> 'b t (* bind *)
val print_value : ('a -> string) -> 'a t -> unit
val trace : error -> 'a t -> 'a t
end = struct
type error = ..
type 'a t = ('a, error list) result
let fail error = Error [ error ]
let return x = Ok x
let (>>?) func = function
| Ok x -> func x
| Error errs -> Error errs
let registered = ref []
let register_error handler =
registered := (handler :: !registered)
let default_handler error =
"Unregistered error: " ^ Obj.(extension_name @@ extension_constructor error)
let to_string error =
let rec find_handler = function
| [] -> default_handler error
| handler :: handlers ->
begin match handler error with
| None -> find_handler handlers
| Some s -> s
end
in find_handler !registered
let print_value func = function
| Ok x -> Printf.printf "Success: %s\n" (func x)
| Error [ s ] -> Printf.printf "Error: %s\n" (to_string s)
| Error errors -> Printf.printf "Errors:\t%s\n" (String.concat "\n\t" (List.map to_string errors))
let trace error = function
| Ok x -> Ok x
| Error errors -> Error (error :: errors)
end
Putting ``Lwt.t`` in the mix
----------------------------
Tezos uses the `Lwt library <https://ocsigen.org/lwt/3.2.1/manual/manual>`__ for threading.
The Lwt monad is mixed in with the error monad module. This requires us
to add some extra combinators and reexport some functions from Lwt.
Im also renaming the type ``t`` to ``tzresult``, as used in the Tezos
codebase.
.. code:: ocaml
module Error : sig
type error = ..
type 'a tzresult = ('a, error list) result
val ok : 'a -> 'a tzresult
val return : 'a -> 'a tzresult Lwt.t
val error : error -> 'a tzresult
val fail : error -> 'a tzresult Lwt.t
val (>>?) : 'a tzresult -> ('a -> 'b tzresult) -> 'b tzresult (* bind *)
val (>>=?) : 'a tzresult Lwt.t -> ('a -> 'b tzresult Lwt.t) -> 'b tzresult Lwt.t
val (>>=) : 'a Lwt.t -> ('a -> 'b Lwt.t) -> 'b Lwt.t
val print_value : ('a -> string) -> 'a tzresult Lwt.t -> unit Lwt.t
val trace : error -> 'a tzresult Lwt.t -> 'a tzresult Lwt.t
end = struct
type error = ..
type 'a tzresult = ('a, error list) result
let fail error = Lwt.return (Error [ error ])
let error error = (Error [ error ])
let ok x = Ok x
let return x = Lwt.return (ok x)
let (>>?) value func =
match value with
| Ok x -> func x
| Error errs -> Error errs
let (>>=) = Lwt.bind
let (>>=?) value func =
value >>= function
| Ok x -> func x
| Error errs -> Lwt.return (Error errs)
let registered = ref []
let register_error handler =
registered := (handler :: !registered)
let default_handler error =
"Unregistered error: " ^ Obj.(extension_name @@ extension_constructor error)
let to_string error =
let rec find_handler = function
| [] -> default_handler error
| handler :: handlers ->
begin match handler error with
| None -> find_handler handlers
| Some s -> s
end
in find_handler !registered
let print_value func value =
value >>= fun value ->
begin match value with
| Ok x -> Printf.printf "Success: %s\n" (func x)
| Error [ s ] -> Printf.printf "Error: %s\n" (to_string s)
| Error errors -> Printf.printf "Errors:\t%s\n" (String.concat "\n\t" (List.map to_string errors))
end; Lwt.return ()
let trace error value =
value >>= function
| Ok x -> return x
| Error errors -> Lwt.return (Error (error :: errors))
end
The actual Tezos error monad
----------------------------
The actual Tezos error monad adds a few things. Firstly, there are three
categories of errors:
- :literal:`\`Temporary` - An error resulting from an operation that
might be valid in the future, for example, a contracts balance being
too low to execute the intended operation. This can be fixed by
adding more to the contracts balance.
- :literal:`\`Branch` - An error that occurs in one branch of the
chain, but may not occur in a different one. For example, receiving
an operation for an old or future protocol version.
- :literal:`\`Permanent` - An error that is not recoverable because the
operation is never going to be valid. For example, an invalid ꜩ
notation.
The registration scheme also uses data encodings. Heres an example from
the `validator <../api/odoc/tezos-node-shell/Tezos_node_shell/Validator/index.html>`__:
.. code:: ocaml
register_error_kind
`Permanent
~id:"validator.wrong_level"
~title:"Wrong level"
~description:"The block level is not the expected one"
~pp:(fun ppf (e, g) ->
Format.fprintf ppf
"The declared level %ld is not %ld" g e)
Data_encoding.(obj2
(req "expected" int32)
(req "provided" int32))
(function Wrong_level (e, g) -> Some (e, g) | _ -> None)
(fun (e, g) -> Wrong_level (e, g))
An error takes a category, id, title, description, and encoding. You
must specify a function to take an error to an optional value of the
encoding type and a function to take a value of the encoded type and
create an error value. A pretty printer can optionally be specified, but
may also be omitted.
The actual error monad and its tracing features can be seen in this
function which parses contracts:
.. code:: ocaml
let parse_script
: ?type_logger: (int * (Script.expr list * Script.expr list) -> unit) ->
context -> Script.storage -> Script.code -> ex_script tzresult Lwt.t
= fun ?type_logger ctxt
{ storage; storage_type = init_storage_type }
{ code; arg_type; ret_type; storage_type } ->
trace
(Ill_formed_type (Some "parameter", arg_type))
(Lwt.return (parse_ty arg_type)) >>=? fun (Ex_ty arg_type) ->
trace
(Ill_formed_type (Some "return", ret_type))
(Lwt.return (parse_ty ret_type)) >>=? fun (Ex_ty ret_type) ->
trace
(Ill_formed_type (Some "initial storage", init_storage_type))
(Lwt.return (parse_ty init_storage_type)) >>=? fun (Ex_ty init_storage_type) ->
trace
(Ill_formed_type (Some "storage", storage_type))
(Lwt.return (parse_ty storage_type)) >>=? fun (Ex_ty storage_type) ->
let arg_type_full = Pair_t (arg_type, storage_type) in
let ret_type_full = Pair_t (ret_type, storage_type) in
Lwt.return (ty_eq init_storage_type storage_type) >>=? fun (Eq _) ->
trace
(Ill_typed_data (None, storage, storage_type))
(parse_data ?type_logger ctxt storage_type storage) >>=? fun storage ->
trace
(Ill_typed_contract (code, arg_type, ret_type, storage_type, []))
(parse_returning (Toplevel { storage_type }) ctxt ?type_logger arg_type_full ret_type_full code)
>>=? fun code ->
return (Ex_script { code; arg_type; ret_type; storage; storage_type })
Each specific type error from the typechecking process is wrapped in a
more general error that explains which part of the program was
malformed. This improves the error reporting. You can also see the bind
operator used between functions to continue only if an error does not
occur. This function also operates in the ``Lwt`` monad, which is
largely hidden via the error monad.

View File

@ -0,0 +1,203 @@
Michelson Anti-Patterns
=======================
Even though Michelson is designed to make it easy to write secure
contracts and difficult to write vulnerable ones, it is still possible
to write buggy contracts that leak data and funds. This is a list of
mistakes that you can make when writing or interacting with contracts on
the Tezos blockchain and alternative ways to write code that avoid these
problems.
Note: We are currently reworking the concurrency model of Michelson (how
and when sub-transactions are made), so that some of these patterns will
be prevented by the language itself.
Refunding to a list of contracts
--------------------------------
One common pattern in contracts is to refund a group of peoples funds
at once. This is problematic if you accepted arbitrary contracts as a
malicious user can do cause various issues for you.
Possible issues:
~~~~~~~~~~~~~~~~
- One contract swallows all the gas through a series of callbacks
- One contract writes transactions until the block is full
- Reentrancy bugs. Michelson intentionally makes these difficult to
write, but it is still possible if you try.
- A contract calls the \`FAIL\` instruction, stopping all computation.
Alternatives/Solutions:
~~~~~~~~~~~~~~~~~~~~~~~
- Create a default account from peoples keys. Default accounts cannot
execute code, avoiding the bugs above. Have people submit keys rather
than contracts.
- Have people pull their funds individually. Each user can break their
own withdrawal only. **This does not protect against reentrancy
bugs.**
Avoid batch operations when users can increase the size of the batch
--------------------------------------------------------------------
Contracts that rely on linear or super-linear operations are vulnerable
to malicious users supplying values until the contract cannot finish
without running into fuel limits. This can deadlock your contract.
.. _possible-issues-1:
Possible issues:
~~~~~~~~~~~~~~~~
- Malicious users can force your contract into a pathological worst
case, stopping it from finishing with available gas. Note that in the
absence of hard gas limits, this can still be disabling as node
operators may not want to run contracts that take more than a certain
amount of gas.
- You may hit the slow case of an amortized algorithm or data structure
at an inopportune time, using up all of your contracts available
gas.
.. _alternativessolutions-1:
Alternatives/Solutions:
~~~~~~~~~~~~~~~~~~~~~~~
- Avoid data structures and algorithms that rely on amortized
operations, especially when users may add data.
- Restrict the amount of data your contract can store to a level that
will not overwhelm the available gas.
- Write your contract so that it may pause and resume batch operations.
This would complicate these sequences and require constant checking
of available gas, but it prevents various attacks.
\*Do not assume an attack will be prohibitively expensive\*
Cryptocurrencies have extreme price fluctuations frequently and an
extremely motivated attacker may decide that an enormous expense is
justified. Remember, an attack that disables a contract is not just
targeted at the authors, but also the users of that contract.
Signatures alone do not prevent replay attacks
----------------------------------------------
If your contract uses signatures to authenticate messages, beware of
replay attacks. If a user ever signs a piece of data, you *must* make
sure that that piece of data is never again a valid message to the
contract. If you do not do this, anyone else can call your contract with
the same input and piggyback on the earlier approval.
.. _possible-issues-2:
Possible issues:
~~~~~~~~~~~~~~~~
- A previously approved action can be replayed.
.. _alternativessolutions-2:
Alternatives/Solutions
~~~~~~~~~~~~~~~~~~~~~~
- Use an internal counter to make the data you ask users to sign
unique. This counter should be per key so that users can find out
what they need to approve. This should be paired with a signed hash
of your contract to prevent cross-contract replays.
- Use the ``SENDER`` instruction to verify that the expected sender is
the source of the message.
Do not assume users will use a unique key for every smart contract
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Users should always use a different key for every contract with which
they interact. If this is not the case, a message the user signed for
another contract can be sent to your contract. An internal counter alone
does not protect against this attack. It *must* be paired with a hash of
your contract. You must verify the source of the message.
Storing/transferring private data
---------------------------------
Once data is published to anyone, including broadcasting a transaction,
that data is public. Never transmit secret information via any part of
the blockchain ecosystem. As soon as you have broadcast a transaction
including that piece of information, anyone can see it. Furthermore,
malicious nodes in the system can manipulate unsigned transactions by
delaying, modifying, or reordering them.
.. _possible-issues-3:
Possible Issues
~~~~~~~~~~~~~~~
- If data is not signed, it can be modified
- Transactions can be delayed
- Secret information will become public
.. _alternativessolutions-3:
Alternatives/Solutions
~~~~~~~~~~~~~~~~~~~~~~
- Do not store private information on the blockchain or broadcast it in
transactions.
- Sign all transactions that contain information that, if manipulated,
could be abused.
- Use counters to enforce transaction orders.
This will at least create a logical clock on messages sent to your
contract.
Not setting all state before a transfer
---------------------------------------
Reentrancy is a potential issue on the blockchain. When a contract makes
a transfer to another contract, that contract can execute its own code,
and can make arbitrary further transfers, including back to the original
contract. If state has not been updated before the transfer is made, a
contract can call back in and execute actions based on old state.
.. _possible-issues-4:
Possible Issues
~~~~~~~~~~~~~~~
- Multiple withdrawals/actions
- Generating illegal state if state is updated twice later
.. _alternativessolutions-4:
Alternatives/Solutions
~~~~~~~~~~~~~~~~~~~~~~
- Forbid reentrancy by means of a flag in your storage, unless you have
a good reason to allow users to reenter your contract, this is likely
the best option.
- Only make transfers to trusted contracts or default accounts. Default
accounts cannot execute code, so it is always safe to transfer to
them. Before trusting a contract, make sure that its behavior cannot
be modified and that you have an extremely high degree of confidence
in it.
Do not store funds for others in spendable contracts
----------------------------------------------------
Tezos allows contracts to be marked as spendable. Managers of spendable
contracts can make transfers using the funds stored inside the contract.
This can subvert guarantees about the contracts behavior that are
visible in the code.
.. _possible-issues-5:
Possible Issues
~~~~~~~~~~~~~~~
- The funds of a contract can be removed.
- A contract may not be able to meet its obligations
.. _alternativessolutions-5:
Alternatives/Solutions
~~~~~~~~~~~~~~~~~~~~~~
- Do not store funds in spendable contracts that you do not control.

View File

@ -0,0 +1,79 @@
Profiling the Tezos node
========================
Memory profiling the OCaml heap
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- Install an OCaml switch with the `statmemprof` patch:
``4.04.2+statistical-memprof`` or ``4.06.0+statistical-memprof``
- Install ``statmemprof-emacs``.
- Enable loading `statmemprof` into the node.
Add the ``statmemprof-emacs`` package as a dependency to the main package, and add
``let () = Statmemprof_emacs.start 1E-4 30 5`` to the ``node_main.ml`` file.
Arguments:
- ``sampling_rate`` is the sampling rate of the profiler. Good value: ``1e-4``.
- ``callstack_size`` is the size of the fragment of the call stack which is captured for each sampled allocation.
- ``min_sample_print`` is the minimum number of samples under which the location of an allocation is not displayed.
- Load sturgeon into emacs, by adding this to your ``.emacs``:
::
(let ((opam-share (ignore-errors (car (process-lines "opam" "config" "var" "share")))))
(when (and opam-share (file-directory-p opam-share))
(add-to-list 'load-path (expand-file-name "emacs/site-lisp" opam-share))))
(require 'sturgeon)
- Launch the node then connect to it with sturgeon.
If the process is launched with pid ``1234`` then
::
M-x sturgeon-connect
tezos-nodememprof.1234.sturgeon
(tab-completion works for finding the socket name)
Memory profiling the C heap
~~~~~~~~~~~~~~~~~~~~~~~~~~~
- Install ``valgrind`` and ``massif-visualizer``
::
valgrind --tool=massif tezos-node run ...
- Stop with `Ctrl-C` then display with
::
massif-visualizer massif.out.pid
Performance profiling
~~~~~~~~~~~~~~~~~~~~~
- Install `perf` (the ``linux-perf`` package for debian).
If the package does not exist for your current kernel, a previous
version can be used. Substitute the ``perf`` command to ``perf_4.9``
if your kernel is 4.9).
- Run the node, find the pid.
- Attach `perf` with ``perf record -p pid --call-stack dwarf``.
Then stop capturing with ``Ctrl-C``. This can represent a lot of
data. Don't do that for too long. If this is too much you can remove
the ``--call-stack dwarf`` to get something more manageable, but
interpreting the information can be harder.
- display the result with ``perf report``

View File

@ -0,0 +1,48 @@
.. _protocol_environment:
Economic protocol sandboxing
============================
In Alpha, as in any sound future protocols, updates are approved by
voting. That way, the responsibility of switching to a new protocol code
is the responsibility of voters, and one could argue that it is up to
them to check that the code does not call, for instance, unsafe array
access functions.
Yet, we decided to introduce a minimum level of machine checks, by
compiling with a specific compiler that checks that no known-unsafe
function is used. This static form of sandboxing is performed by the
OCaml typechecker: we simply compile protocols in a restricted set of
modules with restricted interfaces that hide any unsafe, non wanted
feature.
Another goal of that specific environment is maintaining a stable OCaml
API for protocol development. Imagine that at some point, the OCaml
standard library changes (a function is added or removed, a type is
changed), then we will be able to upgrade to the new OCaml while still
remaining compatible with past protocols, by providing an adapter layer.
Here is a quick description of each file in this environment:
- Files ``array.mli``, ``buffer.mli``, ``bytes.mli``, ``format.mli``,
``int32.mli``, ``int64.mli``, ``list.mli``, ``map.mli``,
``pervasives.mli``, ``set.mli`` and ``string.mli`` are stripped down
interfaces to the OCaml standard library modules. The removed
elements are: effects on toplevel references or channels, unsafe
functions, functions that are known sources of bugs, and anything
deprecated.
- As we removed polymorphic comparison operators, ``compare.mli``
implements monomorphic operators for standard OCaml and Tezos types.
An example use is ``Compare.Int.(3 = 4)`` instead of plain OCaml
``(3 = 4)``.
- Files ``lwt*`` is the stripped down interface to Lwt, of which we
removed any non deterministic functions, since we only use Lwt for
asynchronous access to the storage.
- Files ``data_encoding.mli``, ``error_monad.mli``, ``mBytes.mli``,
``hash.mli``, ``base58.mli``, ``blake2B.mli``, ``ed25519.mli``,
``hex_encode.mli``, ``json.mli``, ``time.mli``, ``z.mli``,
``micheline.mli`` and files ``RPC_*`` are stripped down versions of
the Tezos standard library.
- Files ``tezos_data.mli``, ``context.mli``, ``fitness.mli`` and
``updater.mli`` are interfaces to the shells data definitions and
storage accessors that are accessible to the protocol.

View File

@ -0,0 +1,73 @@
.. _rpc:
JSON/RPC interface
==================
The Tezos node provides a JSON/RPC interface. Note that it is an RPC,
and it is JSON based, but it does not follow the “JSON-RPC” protocol. It
is not active by default and it must be explicitly activated with the
``--rpc-addr`` option. Typically, if you are not trying to run a local
network and just want to explore the RPC, you would run:
::
./tezos-node run --rpc-addr localhost
The RPC interface is self-documented and the ``tezos-client`` executable
is able to pretty-print the RPC API. For instance, to see the API
provided by the Tezos Shell:
::
./tezos-client rpc list
To get API attached to the “genesis” block, including the remote
procedures provided by the associated economic protocol version:
::
./tezos-client rpc list /chains/main/blocks/genesis
You might also want the JSON schema describing the expected input and
output of a RPC. For instance:
::
./tezos-client rpc schema get /chains/main/blocks/genesis/hash
Note: you can get the same information, but as a raw JSON object, with a
simple HTTP request:
::
curl -s localhost:8732/chains/main/blocks/head~10
wget -O - http://localhost:8732/describe?recurse=true
wget -O - http://localhost:8732/describe/chains/main/blocks/genesis?recurse=true
wget -O - http://localhost:8732/describe/chains/main/blocks/genesis/hash
An online :ref:`index <rpc_index>` of RPC calls is also available.
The general call of an RPC from the client is ``tezos-admin-client rpc
(get|post) <url>``.
For instance, if you wish to request the current balance of a given
block and contract, you can call the associated RPC via the command :
``$ tezos-admin-client rpc get
/blocks/<block_id>/proto/context/contracts/<contract_id>/balance``.
An RPC may take an *input* and generate an *output* both in JSON
format. For example, the previous RPC call, that does not require an
input, would display on the standard output : ``{ "balance":
"4000000000000" }``. When calling a RPC that requires an input
through command-line, you will be prompted to provide the JSON input
in your default configured text editor. Alternatively, you can provide
the JSON input using command
``$ tezos-admin-client rpc post <url> with <JSON>``. Don't forget to quote
the JSON according to your shell rules.
If you want to learn more about the exchange of RPCs between node and
client you can pass the option `-l` and the client will print all the
calls with their input/output.
A useful util to manipulate JSON is `jq <https://stedolan.github.io/jq/>`_.

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 437 KiB

View File

@ -0,0 +1,127 @@
.. _p2p:
The peer-to-peer layer
======================
This document explains the inner workings of the peer-to-peer layer of
the Tezos shell. This part is in charge of establishing and
maintaining network connections with other nodes (gossip).
The P2P layer is instantiated by the node. It is parametrized by the
type of messages that are exchanged over the network (to allow
different P2P protocol versions/extensions), and the type of metadata
associated to each peer. The latter is useful to compute a score for
each peer that reflects the level of trust we have in it. Different
policies can be used when communicating with peers with different
score values.
The P2P layer is comprised of a pool of connections, a set of
operations on those connections, and a set of workers following the
worker pattern pervasively used in the code base.
The P2P layer is packaged in :package:`tezos-p2p`, which has
documentation for all modules.
General operation
-----------------
I/O Scheduling
~~~~~~~~~~~~~~
The P2P layer uses a scheduling mechanism in order to control its
bandwidth usage as well as implementing different policies
(e.g. read/write quotas) to different peers. For now, each peer is
granted a fair share of the global allocated bandwidth, but it is
planned for the individual allocated bandwidth to each peer to be a
function of the peer's score.
Encryption
~~~~~~~~~~
The connection between each peer is encrypted using `NaCl`
authenticated-encryption `API <http://nacl.cr.yp.to/box.html>`__. This
is done to provide an additional level of security and tamper-proof
guarantees in the communication between peers.
Message queues
~~~~~~~~~~~~~~
On top of basic I/O scheduling, two finite-size typed message queues
are used to store incoming (resp. outgoing) messages for each
peer. This further restricts the speed at which communication is
possible with a peer; when a queue is full, it is not possible to read
(resp. write) an additional message. The high-level
`P2p_socket.connection
<../api/odoc/tezos-p2p/Tezos_p2p/P2p_socket/index.html#type-connection>`__
type by the P2P layer is basically a UNIX socket upgraded with I/O
scheduling, peer metadata, cryptographic keys and two messages queues
operated by dedicated workers which operate on those queues.
Pool of connections
~~~~~~~~~~~~~~~~~~~
All the above modules are used in `P2p_pool
<../api/odoc/tezos-p2p/Tezos_p2p/P2p_pool/index.html>`__, which
constitutes the core of the P2P layer, together with the worker
processes described below. It comprises various tables of connections
as well as methods to query them, also connections are extended with
another message queue where lower level messages (like responses to
ping) are filtered out and only application-level messages are kept.
The main entry point of the P2P layer is in module `P2p
<../api/odoc/tezos-p2p/Tezos_p2p/P2p/index.html>`__. See below
for a description of workers acting onto the P2P layer.
Welcome worker
--------------
The welcome worker is responsible for accepting incoming connections
and register them into the pool of connections managed by the P2P
layer. It basically runs the ``accept(2)`` syscall and call
`P2p_pool.accept
<../api/odoc/tezos-p2p/Tezos_p2p/P2p_pool/index.html#val-accept>`__ so
that it is made aware of an incoming connection. From there, the pool
will decide how this new connection must be handled.
{Black, While, Grey}lists
~~~~~~~~~~~~~~~~~~~~~~~~~
The welcome worker takes care of filtering all incoming connections using two
static lists of addresses handled either by ``tezos-admin-client`` and a system
table that is handled automatically by the p2p layer. The node admin can block
or whitelist individual ip addresses, while the p2p layer is in charge of
temporarily banning ip addresses and peers who misbehave. The delay to remove
an ip address from the greylist table is defined by the configuration variable
``greylist_timeout``, while peers that are greylisted are periodically removed.
The node admin can also flush greylist tables with the ``tezos-admin-client``.
Maintenance worker
------------------
The maintenance worker is in charge of establishing an appropriate
number of connections with other nodes in order to guarantee a
realistic view of the state of the blockchain. It is created with a
set of targets to reach regarding the desired amount of peers it needs
to keep an active connection to.
At the pool level, the minimum (resp. maximum) acceptable number of
connections is defined.
At the maintenance worker level, two other sets of thresholds are
defined: ``target`` (min and max) and ``threshold`` (min and max).
Given these bounds, the maintenance worker:
* Will be triggered every two minutes, when asked by the shell, or
when the minimum or maximum number of acceptable connections is
reached, whichever happens first.
* Will perform the following actions when triggered: if the number of
connections is above ``max_threshold``, it will kill connections
randomly until it reaches ``max_target`` connections. If the number of
connections is below ``min_threshold``, it will attempt to connect to
peers until it reaches at least ``min_target`` connections (and never
more than ``max_target`` connections).
The maintenance worker is also in charge of periodically run the
greylists GC functions to unban ip addresses from the greylist.

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 661 KiB

View File

@ -0,0 +1,324 @@
.. _proof-of-stake:
Proof-of-stake in Tezos
=======================
This document provides an in-depth description of the Tezos
proof-of-stake algorithm as implemented in
PsYLVpVvgbLhAhoqAkMFUo6gudkJ9weNXhUYCiLDzcUpFpkk8Wt
Blocks
------
The Tezos blockchain is a linked list of blocks. Blocks contain a
header, and a list of operations. The header itself decomposes into a
shell header (common to all protocols) and a protocol specific header.
Shell header
~~~~~~~~~~~~
The shell header contains
- ``level``: the height of the block, from the genesis block
- ``proto``: number of protocol changes since genesis (mod 256)
- ``predecessor``: the hash of the preceding block.
- ``timestamp``: the timestamp at which the block is claimed to have
been created.
- ``validation_pass``: number of validation passes (also number of
lists of lists of operations)
- ``fitness``: a sequence of sequences of unsigned bytes, ordered by
length and then lexicographically. It represents the claimed fitness
of the chain ending in this block.
- ``operations_hash`` The hash of a list of root hashes of merkle
trees of operations. There is one list of operations per
validation pass
- ``context`` Hash of the state of the context after application of
this block.
Protocol header (for tezos.alpha):
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- ``signature``: a digital signature of the shell and protocol headers
(excluding the signature itself).
- ``priority``: the position in the priority list of delegates at which
the block was baked.
- ``seed_nonce_hash``: a commitment to a random number, used to
generate entropy on the chain. Present in only one out of
(``BLOCKS_PER_COMMITMENT`` = 32) blocks.
- ``proof_of_work_nonce``: a nonce used to pass a low-difficulty
proof-of-work for the block, as a spam prevention measure.
Block size
~~~~~~~~~~
Tezos does not download blocks all at once, but rather considers headers
and various lists of operations separately. In Tezos.alpha, a maximum
size in bytes is applied to the list of transactions
``MAX_TRANSACTION_LIST_SIZE`` = 500kB (that's 5MB every 10 minutes at
most).
Other lists of operations (endorsements, denunciations, reveals) are
limited in terms of number of operations (though the defensive
programming style also puts limits on the size of operations it
expects).
This ensure that consensus critical operations do not compete with
transactions for block space.
Delegation
----------
Tezos.alpha uses a delegated proof-of-stake model. The acronym DPOS has come to
designate a specific type of algorithm used, for instance in Bitshares.
This is *not* the model used in Tezos.alpha, though there is a concept
of delegation.
Delegates
~~~~~~~~~
In tezos.alpha, tokens are controlled through a private key called the
*manager key*. Tezos.alpha accounts let the manager specify a public
delegate key. This key may be controlled by the manager themselves, or
by another party. The responsibility of the delegate is to take part in
the proof-of-stake consensus algorithm and in the governance of Tezos.
The manager can generally change the delegate at any time, though
contract can be marked to specify an immutable delegate. Though
delegation can be changed dynamically, the change only becomes effective
after a few cycles.
There are also default accounts in Tezos, which are just the hash of the
public key. These accounts do not have an attached delegate key and do
not participate in the proof-of-stake algorithm.
Finally, delegate accounts (used for placing safety deposits) are
automatically delegated to the delegate itself.
Active and passive delegates
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
A delegate can be marked as either active or passive. A passive delegate
cannot be selected for baking or endorsement.
A delegate becomes passive for cycle ``n`` when they fail to create any
of the blocks or endorsements in the past ``CYCLES_BEFORE_DEACTIVATION``
= 5 cycles, or to change their security deposit. So, in this case, in
cycles ``n-1``, ``n-3``, ..., ``n - CYCLES_BEFORE_DEACTIVATION``.
A small delegate who is afraid they might be deactivated because they
were not given the opportunity to create any block or endorsement can
ensure they do not become deactivated by making small, meaningless
transactions with their security deposits once every two cycles.
Discussion: giving ``CYCLES_BEFORE_DEACTIVATION`` a small value means
the chain adapts more quickly to participants disappearing. It's not
unlike the "difficulty adjustment" of Bitcoin. However, a long value
would ensure that a minority fork progresses more slowly for a longer
period of time than the majority fork. ``CYCLES_BEFORE_DEACTIVATION``
gives the majority chain a "headstart".
This does not affect voting rights for protocol changes.
Rolls
~~~~~
In theory, it would be possible to give each token a serial number, and
track the specific tokens assigned to specific delegates. However, it
would be too demanding of nodes to track assignment at such a granular
level. Instead we introduce the concept of rolls. A roll represents a
set of coins delegated to a given key. When tokens are moved, or a
delegate for a contract is changed, the rolls change delegate according
to the following algorithm.
Each delegate has a stack of roll ids plus some "change" which is always
an amount smaller than ``TOKENS_PER_ROLLS``. When tokens are moved from
one delegate to the other, first, the change is used. If it is not
enough, rolls need to be "broken" which means that they move from the
delegate stack to a global, unallocated, roll stack. This is done until
the amount is covered, and some change possibly remains.
Then, the other delegate is credited. First the amount is added to the
"change". If it becomes greater than ``TOKENS_PER_ROLLS``, then rolls
are unstacked from the global unallocated roll stack onto the delegate
stack. If the global stack is empty, a fresh roll is created.
This preserves the property that if the delegate is changed through
several transactions, the roll assignment is preserved, even if each
operation moves less than a full roll.
The advantage of tracking tokens in this way is that a delegate creating
a malicious fork cannot easily change the specific rolls assigned to
them, even if they control the underlying tokens and shuffle them
around.
Rolls hold ``TOKENS_PER_ROLLS`` = 10,000 tokens and thus there should be
about 80,000 rolls in the Tezos foundation's planned genesis block,
though the number of rolls will increase with inflation and / or
participation in the delegation.
Roll snapshots
~~~~~~~~~~~~~~
Roll snapshots represent the state of rolls for a given block. Roll
snapshots are taken every ``BLOCKS_PER_ROLL_SNAPSHOT`` = 256 blocks,
that is 16 times per cycle. There is a tradeoff between memory
consumption and economic efficiency. If roll snapshots are too frequent,
they will consume a lot of memory. If they are too rare, strategic
participants could purchase many tokens in anticipation of a snapshot
and resell them right after.
Cycles
------
Blocks in the Tezos.Alpha Blockchain are grouped into *cycles* of
``BLOCKS_PER_CYCLE`` = 4,096 blocks. Since blocks are at least
``TIME_BETWEEN_BLOCKS`` = one minute apart, this means a cycle lasts *at
least* 2 days, 20 hours, and 16 minutes. In the following description,
the current cycle is referred to as ``n``, it is the nth cycle from the
beginning of the chain. Cycle ``(n-1)`` is the cycle that took place
before the current one, cycle ``(n-2)`` the one before, cycle ``(n+1)``
the one after, etc.
At any point, the tezos shell will not implicitly accept a branch whose
fork point is in a cycle more than ``PRESERVED_CYCLES`` = 5 cycles in the
past (that is *at least* 14 days, 5 hours, and 20 minutes).
Security deposits
~~~~~~~~~~~~~~~~~
The cost of a security deposit is ``BLOCK_SECURITY_DEPOSIT`` = 512 XTZ
per block created and ``ENDORSEMENT_SECURITY_DEPOSIT`` = 64 XTZ per
endorsement.
Each delegate key has an associated security deposit account.
When a delegate bakes or endorses a block the security deposit is
automatically moved to the deposit account where it is frozen for
``PRESERVED_CYCLES`` cycles, after which it is automatically moved
back to the baker's main account.
Since deposits are locked for a period of ``PRESERVED_CYCLES`` one can
compute that at any given time, about ((``BLOCK_SECURITY_DEPOSIT`` +
``ENDORSEMENT_SECURITY_DEPOSIT`` \* ``ENDORSERS_PER_BLOCK``) \*
(``PRESERVED_CYCLES`` + 1) \* ``BLOCKS_PER_CYCLE``) / ``763e6`` = 8.25% of
all tokens should be held as security deposits. It also means that a
delegate should own over 8.25% of the amount of token delegated to them
in order to not miss out on creating any block.
Baking rights
~~~~~~~~~~~~~
Baking in tezos.alpha is the action of signing and publishing a block.
In Bitcoin, the right to publish a block is associated with solving a
proof-of-work puzzle. In tezos.alpha, the right to publish a block in
cycle ``n`` is assigned to a randomly selected roll in a randomly
selected roll snapshot from cycle ``n-PRESERVED_CYCLES-2``.
We admit, for the time being, that the protocol generates a random seed
for each cycle. From this random seed, we can seed a CSPRNG which is
used to draw baking rights for a cycle.
To each position, in the cycle, is associated a priority list of
delegates.
This is drawn randomly, with replacement, from the set of active rolls
so it is possible that the same public key appears multiple times in
this list.
The first baker in the list is the first one who can bake a block at
that level.
If a delegate is for some reason unable to bake, the next delegate in
the list can step up and bake the block.
The delegate with the highest priority can bake a block with a timestamp
greater than ``timestamp_of_previous_block`` plus
``TIME_BETWEEN_BLOCKS`` = one minute. The one with the kth highest
priority, ``k * TIME_BETWEEN_BLOCKS`` = k minutes.
Baking a block gives a block reward of ``BLOCK_REWARD`` = 16 XTZ plus
all fees paid by transactions inside the block.
Endorsements
~~~~~~~~~~~~
To each baking slot, we associate a list of ``ENDORSERS_PER_BLOCK`` = 32
*endorsers*. Endorsers are drawn from the set of delegates, by randomly
selecting 32 rolls with replacement.
Each endorser verifies the last block that was baked, say at level
``n``, and emits an endorsement operation. The endorsement operations
are then baked in block ``n+1`` and will contribute to the `fitness`
of block ``n``. Once block ``n+1`` is baked, no other endorsement for
block ``n`` will be considered valid.
Endorsers receive a reward (at the same time as block creators do). The
reward is ``ENDORSEMENT_REWARD`` = 2 / ``BLOCK_PRIORITY`` where block
priority starts at 1. So the endorsement reward is only half if the
block of priority 2 for a given slot is being endorsed.
It is possible that the same endorser be selected ``k`` times for the
same block, in this case ``k`` deposits are required and ``k`` rewards
gained. However a single operation needs to be sent on the network to
endorse ``k`` times the same block.
Fitness
~~~~~~~
To each block we associate a measure of `fitness` which determines the
quality of the chain leading to that block.
This measure in Bitcoin is simply the length of the chain, in Tezos we
add also the number of endorsements to each block.
Given a block at level ``n`` with fitness ``f``, when we receive a new
head that contains ``e`` endorsements for block ``n``, the fitness of
the new head is ``f+1+e``.
Inflation
~~~~~~~~~
Inflation from block rewards and endorsement reward is at most
``ENDORSERS_PER_BLOCK`` \* ``ENDORSEMENT_REWARD`` + ``BLOCK_REWARD`` =
80 XTZ. This means at most 5.51% annual inflation.
Random seed
~~~~~~~~~~~
Cycle ``n`` is associated with a random seed, a 256 bit number generated
at the end of cycle ``(n-PRESERVED_CYCLES-1)`` using commitments made during
cycle ``(n-PRESERVED_CYCLES-2)``, in one out of every
``BLOCKS_PER_COMMITMENT`` = 32 blocks.
The commitment must be revealed by the original baker during cycle
``(n-PRESERVED_CYCLES-1)`` under penalty of forfeiting the rewards and
fees of the block that included the seed commitment (the associated
security deposit is not forfeited).
A *revelation* is an operation, and multiple revelations can thus be
included in a block. A baker receives a ``seed_nonce_revelation_tip`` =
1/8 XTZ reward for including a revelation.
Revelations are free operations which do not compete with transactions
for block space. Up to ``MAX_REVELATIONS_PER_BLOCK`` = 32 revelations
can be contained in any given block. Thus, 1 /
(``MAX_REVELATIONS_PER_BLOCK`` \* ``BLOCKS_PER_COMMITMENT``) = 1/1024 of
the blocks in the cycle are sufficient to include all revelations.
The revelations are hashed together to generate a random seed at the
very end of cycle ``(n-PRESERVED_CYCLES-1)``.
The seed of cycle ``(n-PRESERVED_CYCLES-2)`` is hashed with a constant
and then with each revelation of cycle ``(n-PRESERVED_CYCLES-1)``.
Once computed, this new seed is stored and used during cycle ``n``.
Accusations
-----------
If two endorsements are made for the same slot or two blocks at the same
height by a delegate, the evidence can be collected by an accurser and included
in a block for a period of PRESERVED_CYCLES, including the current cycle.
This accusation forfeits the entirety of the safety deposit and future reward up
to that point in the cycle. Half is burned, half goes to the accuser in the form
of a block reward.
In the current protocol, accusations for the *same* incident can be made several
times after the fact. This means that the deposits and rewards for the entire
cycle are forfeited, including any deposit made, or reward earned, after
the incident.
Pragmatically, any baker who either double bakes or endorses in a given cycle
should immediately stop both baking and endorsing for the rest of that cycle.

View File

@ -0,0 +1,327 @@
.. _software_architecture:
Tezos Software Architecture
===========================
This document contains two section. The first section, which should be
readable by anyone, describes the main elements of Tezos from a
distance. It abstracts from all plumbing and both internal and system
dependencies to give a simple view of the main components, their
responsibilities and interactions. The second part is written for
developers, and is at the level of OPAM packages.
The Big Picture
---------------
.. _the_big_picture:
The diagram below shows a very coarse grained architecture of Tezos.
|Tezos architecture diagram|
The characteristic that makes Tezos unique is its self-amending
property. The part that amends itself is called the *economic protocol*
(the green eye of the octopus), sometimes abbreviated by protocol or
even proto in the source code. The rest of a Tezos node is what we call
the *shell* (the blue octopus).
The protocol is responsible for interpreting the transactions and other
administrative operations. It also has the responsibility to detect
erroneous blocks.
An important thing to notice is that the protocol always sees only one
block chain. In other words, a linear sequence of blocks since the
genesis. It does not know that it lives in an open network where nodes
can propose alternative heads.
Only the shell knows about the multiple heads. It is responsible for
choosing between the various chain proposals that come from the bakers
(the programs that cook new blocks) of the network. The shell has the
responsibility of selecting and downloading alternative chains, feed
them to the protocol, which in turn has the responsibility to check them
for errors, and give them an absolute score. The shell then simply
selects the valid head of highest absolute score. This part of the shell
is called :ref:`the validator<validation>`.
The rest of the shell includes the peer-to-peer layer, the disk storage
of blocks, the operations to allow the node to transmit the chain data
to new nodes and the versioned state of the ledger. In-between the
validator, the peer-to-peer layer and the storage sits a component
called the distributed database, that abstracts the fetching and
replication of new chain data to the validator.
Protocols are compiled using a tweaked OCaml compiler (green part on the
left of the picture) that does two things. First, it checks that the
protocols main module has the right type. A good analogy is to see
protocol as plug-ins, and in this case, it means that it respects the
common plugin interface. Then, it restricts the typing environment of
the protocols code so that it only calls authorized modules and
functions. Seeing protocols as plug-ins, it means that the code only
called primitives from the plug-in API. It is a form of statically
enforced sandboxing.
Finally, the RPC layer (in yellow on the right in the picture) is an
important part of the node. It is how the client, third party
applications and daemons can interact with the node and introspect its
state. This component uses the mainstream JSON format and HTTP protocol.
It uses in-house libraries ``ocplib-resto`` and ``ocplib-json-typed``
(via the module :ref:`Data_encoding <data_encoding>`). It
is fully inter-operable, and auto descriptive, using JSON schema.
.. |Tezos architecture diagram| image:: octopus.svg
Software Architecture and Package Relashionships
------------------------------------------------
.. _packages:
The diagram below shows the main OPAM packages present in the source
code of Tezos, and their dependencies. The ``tezos-`` prefix has been
dropped for clarity.
|Tezos source packages diagram|
In green at the bottom are binaries. Highlighted in yellow are the OPAM
packages (sometimes with shortened names). Black arrows show direct
dependencies. Orange arrows show other indirect relationships (code
generation, interface sharing), explained below. The part circled in
blue, contains modules that bear no dependency to Unix, and can thus
be compiled to JavaScript. External dependencies are not shown in this
illustration.
Base and below
~~~~~~~~~~~~~~
At the center, the :package:`tezos-base` package is where
the blockchain specific code starts. Before it are the set of libraries
that are used everywhere for basic operations.
- :package:`tezos-stdlib` contains a few extensions over the
OCaml standard library (a few string primitives, an ``Option``
module, etc.), a few ``Lwt`` utilities, and a ``Compare`` module
that implements monomorphic comparison operators.
- :package:`tezos-data-encoding` is the in-house
combinator-based serialization library. From a single type
description ``t encoding``, the code can read to and write from
values of type ``t`` both binary and JSON representations. For
both, the library provides machine and human-readable documentations
by the use of documentation combinators. The JSON part depends on
:opam:`ocplib-json-typed`.
A :ref:`tutorial<data_encoding>` is available for this library.
- :package:`tezos-error-monad` is an in-house monadic
interface to the OCaml ``('a, 'b) result`` type, that fixes the
``'b`` to an extensible type ``error`` (actually a list, to hold an
error trace). When extending the type, programmers must also call
the ``register_error`` function that registers a pretty printer and
an encoding for serialization.
A :ref:`tutorial<error_monad>` is available for this library.
- :package:`tezos-rpc` provides the basics of Tezos' RPC service
mechanism. It provides combinators for building service hierarchies
à la Ocsigen/Eliom, registering and calling services. This module
is based on :opam:`ocplib-resto`, that allows for automatic
generation of a machine and human-readable of the hierarchy of
services: the structure of URLs and the expected formats for input
and output bodies, via the use of ``data_encoding``.
- :package:`tezos-crypto` wraps the external cryptography
libraries that we use. We try to use minimal reference
implementations, with as thin as possible bindings, and
rely on libraries from the
`HACL* project <https://github.com/project-everest/hacl-star>`_,
written and verified in the F* programming language, and extracted
to C.
- :package:`tezos-micheline` is the concrete syntax used by
Michelson, the language of smart contracts. It mostly contains the
generic, untyped AST, a printer and a parser.
- :package:`tezos-base` wraps all these module in a common foundation
for all the other components of Tezos, and introduces the data
structures of the blockchain (e.g. ``Block_hash``,
``Block_header``, ``Block_locator``, ``Fitness``, ``P2p_identity``)
that are shared between the shell, economic protocol, client,
daemons and third party software. It also rewraps some modules from
``crypto`` as functors that build all-in-one modules for a given
type (for instance, the module for block hashes contains all
possible converters, command line and RPC argument builders, pretty
printers, an autocompleter, etc.). This package also contains the
``cli_entries`` module that we use to handle command line parsing
in some executables.
The Shell
~~~~~~~~~
The shell is the part of the node responsible for all communications,
peer-to-peer and RPC, acting as a cocoon around the economic
protocols.
- :package:`tezos-shell-services` contains the definition of the
node's service hierarchy, and calling functions to use in the
client (or any third party software). As this library is linked
into the client to call the services in a type-safe way, only the
description of services is done here. The registration of handlers
is done in the rest of the node's implementation.
- :package:`tezos-rpc-http` uses :opam:`cohttp` to implement the RPC
over HTTP server and client, allowing to make actual use of
services declared using :package:`tezos-rpc`.
- :package:`tezos-p2p` is the in-house peer-to-peer layer.
- :package:`tezos-storage` contains the raw simple key-value store
used for the chain data, and the raw versioned key-value store
used for storing the ledger's context (one version per
block). This is implemented using :opam:`irmin` and currently
:package:`lmdb`.
- :package:`tezos-protocol-updater` maintains the table of available
protocol versions, embedded or dynamically linked.
- :package:`tezos-shell` implements the scheduling of block
validations, the mempool management, and the distributed database.
A description is available in :ref:`this document<validation>`.
The Economic Protocol Environment and Compiler
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Economic protocols are compiled by a specific version of the OCaml
compiler. This compiler restricts the set of modules available to the
economic protocol, as a form of static sandboxing. It also generates a
functorized version of the protocol, to make the execution of the
protocol in alternative environment possible.
- :package:`tezos-protocol-environment-sigs` contains the modules
that are available to the economic protocol. A review of this
sandbox is available :ref:`here<protocol_environment>`. This
modules include a stripped down standard library, and interfaces
to the crypto APIs, RPC definitions, and key-value store.
- :package:`tezos-protocol-compiler` is the compiler for economic
protocols: an alternative driver to the OCaml
:opam:`ocaml-compiler-libs` that typechecks within the protocol
environment, and performs some more checks on the protocol code.
- ``tezos-protocol-xxx`` is produced by the protocol compiler
and contains a functorized version of protocol ``xxx`` that takes its
standard library as parameter. This parameter can be filled with
any of the implementations described in the two points below.
- :package:`tezos-protocol-environment-shell` is the instance of the
environment whose RPC service registration and storage access are
the ones of the node. This is the environment that is fed by the
node when loading new protocols.
- :package:`tezos-protocol-environment` contains three alternative
instances of the protocol environment: one whose context access
function are dummy ones which can be used when only the types and
non contextual functions of the protocol are needed, another that
simulates the key-value store in memory for testing, and a functor
that let you build an environment from a few context accessors.
- ``tezos-embedded-protocol-xxx`` contains a version of protocol
``xxx`` whose standard library is pre-instantiated to the shell's
implementation, these are the ones that are linked into the
node. It also contains a module that registers the protocol in the
node's protocol table.
The Embedded Economic Protocols
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Three economic protocols are included in the main Tezos repository.
- :package:`tezos-protocol-genesis`
(:package:`tezos-embedded-protocol-genesis`) is the protocol of
the genesis block. It accepts a single block, signed by a activator
whose public key is hardcoded, that single action is to switch to
a new protocol chosen by the activator.
- :package:`tezos-protocol-alpha`
(:package:`tezos-embedded-protocol-alpha`) is the first real
protocol of Tezos. A :ref:`tutorial<entering_alpha>` is available
to start reading the protocol's code.
- :package:`tezos-protocol-demo`
(:package:`tezos-embedded-protocol-demo`) is just a demo protocol
that does nothing interesting but has the right shape.
The Client Library
~~~~~~~~~~~~~~~~~~
The client is split into many packages, to enforce three separation
lines: shell vs economic protocol, Unix dependent vs Javascript
compatible, and library vs command line interface.
- :package:`tezos-client-base` define the client context, which is
an object whose methods allow for: accessing a wallet of keys,
interacting via the user, making RPC calls, and signing data using
signer plug-ins. Most of the, including RPC calling functions from
:package:`tezos-shell-services` and
:package:`tezos-protocol-alpha`, are abstracted over this object
type. That way, it is possible to use the same code for different
platforms or toolkits.
- :package:`tezos-client-alpha` provides some functions to perform
the operations of protocol alpha using the wallet and signers from
the client context.
- :package:`tezos-client-commands` plugs the basic context access
functions from :package:`tezos-client-base` as handlers for the
commands of the ``tezos-client`` command line wallet.
- :package:`tezos-client-alpha-commands` plugs the functions from
:package:`tezos-client-alpha` as handlers for the alpha specific
commands of the ``tezos-client`` command line wallet.
- :package:`tezos-client-genesis` contains the basic activator
commands available on the genesis protocol.
- :package:`tezos-client-base-unix` implements configuration file
and wallet storage in Unix files, user interaction via the Unix
console, and terminal based signer plug-ins.
Tests Packages
~~~~~~~~~~~~~~
The tests are split into various packages, testing more and more
elements while following the dependency chain. Use ``make test`` to
run them.
- :package-name:`tezos-client`
(in directory :src:`src/bin_client/test/`):
end-to-end tests as shell scripts that launch a local sandboxed node
and performs various tasks using the client
- :package-name:`tezos-p2p`
(in directory :src:`src/lib_p2p/test/`):
tests of the peer-to-peer layer, independently of the Tezos gossip
protocol (establishing connections, propagating peers, etc.)
- :package-name:`tezos-protocol-environment`
(in directory :src:`src/lib_protocol_environment/test/`):
tests for the in-memory context implementation.
- :package-name:`tezos-shell`
(in directory :src:`src/lib_shell/test/`):
tests for the chain data storage.
- :package-name:`tezos-stdlib`
(in directory :src:`src/lib_stdlib/test/`):
tests for the basic data structures.
- :package-name:`tezos-storage`
(in directory :src:`src/lib_storage/test/`):
tests for the versioned key-value context.
- :package-name:`tezos-protocol-alpha`
(in directory :src:`src/proto_alpha/lib_protocol/test/`):
tests of the alpha protocol (without launching a node).
- :package-name:`tezos-crypto`
(in directory :src:`src/lib_crypto/test/`):
tests for the in-house merkle trees.
- :package-name:`tezos-data-encoding`
(in directory :src:`src/lib_data_encoding/test/`):
tests for the JSON and binary serialization and deserialization.
The Final Executables
~~~~~~~~~~~~~~~~~~~~~
- :package:`tezos-node` provides the node launcher binary
``tezos-node``. All the algorithmic being implemented in the
shell, this package only implements the node's CLI. It also
provides the sandboxed node shell script launcher (see the main
readme).
- :package:`tezos-client` provides the ``tezos-client`` and
``tezos-admin-client`` binaries. The former contains a small
comand line wallet, the latter an administration tool for the
node. It also provides a shell script that configures a shell
environment to interact with a sandboxed node.
- :package:`tezos-baker-alpha` provides the ``tezos-baker-alpha``
binary.
- :package:`tezos-endorser-alpha` provides the ``tezos-endorser-alpha``
binary.
- :package:`tezos-accuser-alpha` provides the ``tezos-accuser-alpha``
binary.
- :package:`tezos-protocol-compiler` provides the
``tezos-protocol-compiler`` binary that is used by the node to
compile new protocols on the fly, and that can be used for
developing new protocols.
.. |Tezos source packages diagram| image:: packages.svg

View File

@ -0,0 +1,120 @@
.. _validation:
The validation subsystem
========================
This document explains the inner workings of the validation subsystem
of the Tezos shell, that sits between the peer-to-peer layer and the
economic protocol. This part is in charge of validating chains, blocks
and operations that come from the network, and deciding whether they
are worthy to propagate. It is composed of three main parts: the
:ref:`validator<validator_component>`, the
:ref:`prevalidator<prevalidator_component>`, and
the :ref:`distributed DB<DDB_component>`.
|Tezos validation diagram|
Validator
---------
.. _validator_component:
The validator is the component responsible for checking that blocks
coming from the network or a baker are valid, w.r.t. the rules defined
by the economic protocol, and for selecting the block that it
considers to be the current head of the blockchain.
The validator is written as a collection of workers: local event loops
communicating with each other via message passing. Workers are spawned
and killed dynamically, according to connected peers, incoming blocks
to validate, and active (test)chains.
A *chain validator* worker is launched by the validator for each
*chain* that it considers alive. Each chain validator is responsible for
handling blocks that belong to this chain, and select the best head for
this chain. A main chain validator is spawned for the main chain that
starts at the genesis, a second one when there is an active test
chain. Forking a chain is decided from within the economic protocol. In
version Alpha, this is only used to try new protocols before self
amending the main chain.
The chain validator spawns one *peer validator* worker per connected
peer. This set is updated, grown or shrunk on the fly, according to the
connections and disconnections signals from the peer-to-peer component.
Each peer validator will treat new head proposals from the associated
peer, one at a time, in a loop. In the simple case, when a peer
receives a new head proposal that is a direct successor of the current
local head, it launches a simple *head increment* task: it retrieves
all the operations and triggers a validation of the block. When the
difference between the current head and the examined proposal is
more than one block, mostly during the initial bootstrap phase, the
peer worker launches a *bootstrap pipeline* task.
A third scheme is planned (but not yet implemented) for validating
alternative chains: the *multipass validator*. This method is quite more
complex, its goal is to detect erroneous blocks as soon as possible,
without having to download all the chain data. This will work by first
validating the block headers, then the operations that act on the
fitness, and finally the remaining operations. The mechanism is
actually a bit more flexible, and allows for an arbitrary number of
lists of operations. The shell will only consider forks of a given
length, that is exported by the protocol, so that block headers and
operations are validated in the context of an ancestor block that is
in a close enough time window. In version Alpha, the check performed
on block headers is that the baking slots, baker signatures and
timestamp deltas are right. It can also detect too large fitness gaps,
as the fitness difference between two consecutive blocks is bounded in
Alpha. The operations that act on fitness are endorsements, whose
checks consist in verifying the endorsement slots and endorsers'
signatures. For that to be sound, the fork limit is set to not allow
rewinding before the baking and endorsing slots are set.
Each of these three peer validator tasks (head increment, bootstrap
pipeline or multipass) will interact with the distributed DB to get
the data they need (block headers and operations). When they have
everything needed for a block, they will call the *block validator*.
The *block validator* validates blocks (currently in sequence),
assuming that all the necessary data have already been retrieved from
the peer-to-peer network. When a block is valid, it will notify the
corresponding chain validator, that may update its head. In this case,
the chain validator will propagate this information to its associated
*prevalidator*, and may decide to kill or spawn the test network
according to the protocol's decision.
Prevalidator
------------
.. _prevalidator_component:
To each chain validator is associated a *prevalidator* (this may become
an option in the future, to allow running nodes on machines with less
RAM), that is responsible for the transmission of operations for this
chain over the peer-to-peer network.
To prevent spam, this prevalidator must select the set of operations
that it considers valid, and the ones that it chooses to broadcast.
This is done by constantly baking a dummy block, floating over the
current head, and growing as new operations are received.
Operations that get included can be broadcast unconditionally.
Operations that are included are classified into categories. Some
(such as bad signatures or garbage byte sequences) are dismissed. They
are put in a temporary bounded set for quick rejection, and the peer
that sent it is kicked. Some other operations are temporarily refused:
they come too soon or too late. For instance, in Alpha, contracts have
counters, and operations with counters in the future are classified as
temporarily refused. A malicious peer could easily flood the mempool
with such operations, so they are put in a bounded set. Another
bounded set is also kept for a third kind of non inclusion: operations
that could be valid in another branch.
Distributed DB
--------------
.. _DDB_component:
The gathering of resources needed for validation is centralized in the
*distributed db*. This component allocates a slot per requested
resource, whose priority depends on the number of peer validators
requesting it.
.. |Tezos validation diagram| image:: validation.svg

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 384 KiB

View File

@ -0,0 +1,181 @@
.. _voting:
The Voting Process
==================
The design of the Tezos Node allows the consensus protocol to be
amended, that is replaced by another set of OCaml files which
implement the API of a valid protocol.
In the current protocol the amendment procedure is guided by a voting
procedure where delegates can propose, select and test a candidate
protocol before activating it.
Delegates take part in the amendment procedure with an influence
proportional to their stake, one roll one vote.
The procedure consists of four periods, each of 32768 blocks (or
~three weeks), for a total of approximately three months.
Other than this page, there is an excellent overview from `Jacob
Arluck on medium.
<https://medium.com/tezos/amending-tezos-b77949d97e1e>`_
Periods
-------
The voting procedure works as follows:
- `Proposal period`: delegates can submit protocol amendment proposals using
the `proposals` operation. At the end of a proposal period, the proposal with
most supporters is selected and we move to a testing_vote period.
If there are no proposals, or a tie between proposals, a new proposal
period starts. Each delegate can submit a maximum of 20 proposals,
including duplicates.
- `Testing_vote period`: delegates can cast one vote to test or not the winning
proposal using the `ballot` operation.
At the end of a testing_vote period if participation reaches the quorum
and the proposal has a super-majority in favor, we proceed to a testing
period. Otherwise we go back to a proposal period.
- `Testing period`: a test chain is forked for 48 hours to test a
correct migration of the context.
At the end of a testing period we move to a promotion_vote period.
- `Promotion_vote period`: delegates can cast one vote to promote or not the
tested proposal using the `ballot` operation.
At the end of a promotion_vote period if participation reaches the quorum
and the tested proposal has a super-majority in favor, it is activated as
the new protocol. Otherwise we go back to a proposal period.
It is important to note that the stake of each delegated is computed
at the beginning of each period.
Super-majority and Quorum
-------------------------
Both voting periods work in the same way, only the subject of the
vote differs.
During a vote a delegate can cast a single Yea, Nay or Pass vote.
A vote is successful if it has super-majority and the participation
reaches the current quorum.
`Super-majority` means the Yeas are more than 8/10 of Yeas+Nays votes.
The `participation` is the ratio of all received votes, including
passes, with respect to the number of possible votes. The `quorum`
starts at 80% and at each vote it is updated using the old quorum and
the current participation with the following coefficients::
newQ = oldQ * 8/10 + participation * 2/10
More details can be found in the file
``src/proto_alpha/lib_protocol/src/amendment.ml``.
Operations
----------
There are two operations used by the delegates: ``proposals`` and ``ballot``.
A proposal operation can only be submitted during a proposal period.
::
Proposals : {
source: Signature.Public_key_hash.t ;
period: Voting_period_repr.t ;
proposals: Protocol_hash.t list ; }
Source is the public key hash of the delegate, period is the unique
identifier of each voting period and proposals is a non-empty list of
maximum 20 protocol hashes.
The operation can be submitted more than once but only as long as the
cumulative length of the proposals lists is less than 20.
A ballot operation can only be submitted during one of the voting
periods, and only once per period.
::
Ballot : {
source: Signature.Public_key_hash.t ;
period: Voting_period_repr.t ;
proposal: Protocol_hash.t ;
ballot: Vote_repr.ballot ; }
Source and period are the same as above, while proposal is the
currently selected proposal and ballot is one of ``Yea``, ``Nay`` or
``Pass``.
The pass vote allows a delegate to not influence a vote but still
allowing it to reach quorum.
More details can be found, as for all operations, in
``src/proto_alpha/lib_protocol/src/operation_repr.ml``.
The binary format is described by ``tezos-client describe unsigned
operation``.
Client Commands
---------------
Tezos' client provides a command to show the status of a voting period.
It displays different informations for different kind of periods, as
in the following samples::
$ tezos-client show voting period
Current period: "proposal"
Blocks remaining until end of period: 59
Current proposals:
PsNa6jTtsRfbGaNSoYXNTNM5A7c3Lji22Yf2ZhpFUjQFC17iZVp 400
$ tezos-client show voting period
Current period: "testing_vote"
Blocks remaining until end of period: 63
Current proposal: PsNa6jTtsRfbGaNSoYXNTNM5A7c3Lji22Yf2ZhpFUjQFC17iZVp
Ballots: { "yay": 400, "nay": 0, "pass": 0 }
Current participation 20.00%, necessary quorum 80.00%
Current in favor 400, needed supermajority 320
$ tezos-client show voting period
Current period: "testing"
Blocks remaining until end of period: 64
Current proposal: PsNa6jTtsRfbGaNSoYXNTNM5A7c3Lji22Yf2ZhpFUjQFC17iZVp
It should be noted that the number 400 above is a number of rolls.
The proposal has a total of 400 rolls, which may come from several
delegates. The same applies for the ballots, there are 400 rolls in
favor of testing protocol PsNa6jTt.
Submit proposals
~~~~~~~~~~~~~~~~
During a proposal period, the list of proposals can be submitted with::
tezos-client submit proposals for <delegate> <proposal1> <proposal2> ...
Remember that each delegate can submit a maximum of 20 protocol
hashes including duplicates.
Moreover each proposal is accepted only if it meets one of the
following two conditions:
- the protocol hash was already proposed on the network. In this case
we can submit an additional proposal that "upvotes" an existing one
and our rolls are added to the ones already supporting the proposal.
- the protocol is known by the node. In particular the first proposer
of a protocol should be able to successfully inject the protocol in
its node which performs some checks, compiles and loads the
protocol.
Submit ballots
~~~~~~~~~~~~~~
During a voting period, being it a testing vote or a promotion vote,
ballots can be submitted once with::
tezos-client submit ballot for <delegate> <proposal> <yay|nay|pass>
Other resources
~~~~~~~~~~~~~~~
For more details on the client commands refer to the manual at
:ref:`client_manual`.
For vote related RPCs check the :ref:`rpc_index` under the prefix
``vote/``.
For Ledger support refer to Obsidian Systems' `documentation
<https://github.com/obsidiansystems/ledger-app-tezos#proposals-and-voting>`_.

13
vendors/tezos-modded/dune vendored Normal file
View File

@ -0,0 +1,13 @@
(env
(dev
(flags (:standard)))
(release
(flags (:standard -O3))))
(alias
(name runtest)
(deps (alias_rec runtest_indent)))
(alias
(name runtest)
(deps (alias_rec runtest_sandbox)))

1
vendors/tezos-modded/dune-workspace vendored Normal file
View File

@ -0,0 +1 @@
(lang dune 1.0)

65
vendors/tezos-modded/emacs/README.md vendored Normal file
View File

@ -0,0 +1,65 @@
# Michelson Emacs mode
This mode is a work in progress.
Please contact us with bugs and feature requests.
All of the options mentioned below are also accessible via the customize menu.
## Dependencies:
To operate the mode, please install the following dependencies.
All are available from either melpa, elpa, or marmalade
and are available under a free software license.
| Package | Package Repository | Sources |
| -------- | ------------------ | --------------- |
| deferred | Melpa | https://github.com/kiwanami/emacs-deferred |
## Required Configuration
To use the mode, you must load the `michelson-mode.el` file into Emacs.
Add the following to your `.emacs` file.
```elisp
(load "~/tezos/tezos/emacs/michelson-mode.el" nil t)
```
Before using the Emacs mode, you must configure the `michelson-client-command`.
If you have compiled the Tezos Git repository,
set this to be the path to the `tezos-client` binary on your system.
Make sure you have an up to date version of the client compiled.
You must also start a tezos node to enable typechecking features.
This option is recommended because it is faster than operating through
the docker container.
If you wish to run the Emacs mode with the alphanet script,
use the path of the `alphanet.sh` script, plus the word `client`.
You must also set the `michelson-alphanet` variable to be `t`.
If you do not set this option, the mode will not work with the alphanet.
Here are examples of the client configuration:
### Without the alphanet
```elisp
(setq michelson-client-command "~/tezos/tezos/tezos-client")
(setq michelson-alphanet nil)
```
### With the alphanet
```elisp
(setq michelson-client-command "~/tezos/alphanet/alphanet.sh client")
(setq michelson-alphanet t)
```
## Additional Options
There are various feature of the Emacs mode you may wish to configure.
### Error display
When writing a contract, you may wish to disable error display in order to
avoid the "wrong stack type at end of body" error that is often present.
This can be done by changing the
`michelson-print-errors` and `michelson-highlight-errors` options.
Both of these options also have interactive toggles for easy access.
### Live printing
You can disable live printing using the `michelson-live-editing` option.
If this option is disabled, both type and error printing are supressed.
No background command will be run, limiting the mode to syntax highlighting.
This command can also be toggled interactively using the
`michelson-toggle-live-editing` command.
### Faces
The highlighting colors used can be configured. See the customize menu for details.

View File

@ -0,0 +1,913 @@
;; Major mode for editing Michelson smart contracts.
(require 'cl-lib)
(require 'deferred)
(require 'font-lock)
(defvar michelson-mode-hook nil)
(defgroup michelson nil
"Major mode for editing Michelson smart contracts."
:prefix "michelson-"
:group 'languages)
(defgroup michelson-options nil
"General options for Michelson mode."
:prefix "michelson-"
:group 'michelson)
(defcustom michelson-client-command "tezos-client"
"Path to the `tezos-client' binary."
:type 'string
:group 'michelson-options)
(defcustom michelson-alphanet nil
"Is the client command currently using the alphanet.sh script?"
:type 'boolean
:group 'michelson-options)
(defgroup michelson-faces nil
"Font lock faces for Michelson mode."
:prefix "michelson-"
:group 'michelson
:group 'faces)
(defcustom michelson-live-editing t
"Toggles live types and error printing.
Overrides `michelson-print-errors' and `michelson-highlight-errors'"
:group 'michelson-options)
(defcustom michelson-print-errors t
"Print the errors in the output buffer."
:type 'boolean
:group 'michelson-options)
(defcustom michelson-highlight-errors t
"Highlight errors in the source buffer."
:type 'boolean
:group 'michelson-options)
(defvar michelson-face-instruction
'michelson-face-instruction
"Face name for Michelson instructions.")
(defface michelson-face-instruction
'((t (:inherit font-lock-keyword-face)))
"Face for Michelson instructions."
:group 'michelson-faces)
(defvar michelson-face-type
'michelson-face-type
"Face name for Michelson types.")
(defface michelson-face-type
'((t (:inherit font-lock-type-face)))
"Face for Michelson types."
:group 'michelson-faces)
(defvar michelson-face-constant
'michelson-face-constant
"Face name for Michelson constants.")
(defface michelson-face-constant
'((t (:inherit font-lock-constant-face)))
"Face for Michelson constants."
:group 'michelson-faces)
(defvar michelson-face-var-annotation
'michelson-face-var-annotation
"Face name for Michelson variable or binding annotations.")
(defface michelson-face-var-annotation
'((t (:inherit font-lock-variable-name-face)))
"Face for Michelson variable or binding annotations."
:group 'michelson-faces)
(defvar michelson-face-type-annotation
'michelson-face-type-annotation
"Face name for Michelson type or field annotations.")
(defface michelson-face-type-annotation
'((t (:inherit font-lock-string-face)))
"Face for Michelson type or field annotations."
:group 'michelson-faces)
(defvar michelson-face-comment
'michelson-face-comment
"Face name for Michelson comments.")
(defface michelson-face-comment
'((t (:inherit font-lock-comment-face)))
"Face for Michelson comments."
:group 'michelson-faces)
(defvar michelson-face-declaration
'michelson-face-declaration
"Face name for Michelson declarations.")
(defface michelson-face-declaration
'((t (:inherit font-lock-keyword-face)))
"Face for Michelson constants."
:group 'michelson-faces)
(defvar michelson-face-error
'michelson-face-error
"Face name for Michelson comments.")
(defface michelson-face-error
'(( ((class color) (background light)) (:background "MistyRose") )
( ((class color) (background dark)) (:background "DarkRed") ))
"Face for Michelson annotations."
:group 'michelson-faces)
(defface michelson-stack-highlight-face
'(( ((class color) (background light)) (:background "gray86") )
( ((class color) (background dark)) (:background "grey21") ))
"Face for alternating lines of the stack."
:group 'michelson-faces)
(defun michelson-customize-options ()
"Open the general customization group for Michelson mode."
(interactive)
(customize-group-other-window `michelson-options))
(defun michelson-customize-faces ()
"Open the face customization group for Michelson mode."
(interactive)
(customize-group-other-window `michelson-faces))
(defun michelson-toggle-print-errors ()
(interactive)
(setq michelson-print-errors (not michelson-print-errors)))
(defun michelson-highlight-errors ()
(interactive)
(setq michelson-highlight-errors (not michelson-highlight-errors)))
(defconst michelson-mode-map
(let ((michelson-mode-map (make-sparse-keymap)))
;; menu
(define-key michelson-mode-map
[menu-bar michelson-menu]
(cons "Michelson" (make-sparse-keymap "michelson-menu")))
(define-key michelson-mode-map
[menu-bar michelson-menu faces]
(cons "Display options group" 'michelson-customize-faces))
(define-key michelson-mode-map
[menu-bar michelson-menu options]
(cons "General options group" 'michelson-customize-options))
(define-key michelson-mode-map
[menu-bar michelson-menu separator]
'(menu-item "--"))
(define-key michelson-mode-map
[menu-bar michelson-menu what]
(cons "What's under the cursor?" 'michelson-type-at-point))
;; keys
(define-key michelson-mode-map
(kbd "C-j") 'newline-and-indent)
(define-key michelson-mode-map
(kbd "TAB") 'indent-for-tab-command)
(define-key michelson-mode-map
(kbd "<f1>") 'michelson-type-at-point)
michelson-mode-map))
(defun michelson-font-lock-syntactic-face-function (s)
(cond ((nth 3 s) 'font-lock-constant-face)
(t 'michelson-face-comment)))
(defconst michelson-font-lock-defaults
(list
(list
'("\\<[@]\\(\\|%\\|%%\\|[A-Za-z-_][A-Za-z-_0-9\.]*\\)\\>" . michelson-face-var-annotation)
'("\\<[%:]\\(\\|@\\|[A-Za-z-_][A-Za-z-_0-9\.]*\\)\\>" . michelson-face-type-annotation)
'("\\<[0-9]+\\>" . michelson-face-constant)
'("\\<[A-Z][a-z_0-9]+\\>" . michelson-face-constant)
'("\\<[A-Z][A-Z_0-9]*\\>" . michelson-face-instruction)
;; This will have problems if users have whitespace in front of the declarations
'("^parameter\\|^return\\|^storage\\|^code" . michelson-face-declaration)
'("\\<[a-z][a-z_0-9]*\\>" . michelson-face-type))
nil nil nil nil
'(font-lock-syntactic-face-function . michelson-font-lock-syntactic-face-function)))
(defconst michelson-mode-syntax-table
(let ((michelson-mode-syntax-table (make-syntax-table)))
(modify-syntax-entry ?_ "w" michelson-mode-syntax-table)
(modify-syntax-entry ?@ "w" michelson-mode-syntax-table)
(modify-syntax-entry ?: "w" michelson-mode-syntax-table)
(modify-syntax-entry ?% "w" michelson-mode-syntax-table)
(modify-syntax-entry ?/ ". 1n4" michelson-mode-syntax-table)
(modify-syntax-entry ?* ". 23" michelson-mode-syntax-table)
(modify-syntax-entry ?# "<b" michelson-mode-syntax-table)
(modify-syntax-entry ?\n ">b" michelson-mode-syntax-table)
michelson-mode-syntax-table))
(defun in-space ()
(or (looking-at "[[:space:]\n]")
(equal (get-text-property (point) 'face)
'michelson-face-comment)))
(defun michelson-goto-previous-token ()
(interactive)
(if (bobp)
(cons 0 nil)
(progn
(backward-char 1)
(while (and (not (bobp)) (in-space)) (backward-char 1))
(let ((token-face (get-text-property (point) 'face)))
(forward-char 1)
(let ((end-of-token (point)))
(backward-char 1)
(unless (looking-at "[{()};]")
(while (and (not (bobp))
(equal (get-text-property (point) 'face) token-face))
(backward-char 1))
(when (not (equal (get-text-property (point) 'face) token-face))
(forward-char 1)))
(cons (point) (buffer-substring-no-properties (point) end-of-token)))))))
(defun michelson-goto-next-token ()
(interactive)
(if (eobp)
(cons (point) nil)
(progn
(while (and (not (eobp)) (in-space)) (forward-char 1))
(let ((token-face (get-text-property (point) 'face)))
(let ((start-of-token (point)))
(if (looking-at "[{()};]")
(forward-char 1)
(progn
(while (and (not (eobp))
(equal (get-text-property (point) 'face) token-face))
(forward-char 1))))
(cons start-of-token (buffer-substring-no-properties start-of-token (point))))))))
(defun michelson-goto-opener ()
(interactive)
(let ((paren-level 0))
(while (and (not (bobp))
(or (> paren-level 0)
(not (looking-at "[{(]"))))
(cond ((looking-at "[{(]")
(setq paren-level (- paren-level 1)))
((looking-at "[})]")
(setq paren-level (+ paren-level 1))))
(michelson-goto-previous-token))
(cons (point)
(when (looking-at "[{(]")
(buffer-substring-no-properties (point) (+ (point) 1))))))
(defun michelson-goto-closer ()
(interactive)
(let ((paren-level 0) (last-token ""))
(while (and (not (eobp))
(or (> paren-level 0)
(not (string-match "[)}]" last-token))))
(cond ((looking-at "[{(]")
(setq paren-level (+ paren-level 1)))
((looking-at "[})]")
(setq paren-level (- paren-level 1))))
(setq last-token (cdr (michelson-goto-next-token))))
(cons (point)
(when (looking-at "[)}]")
(buffer-substring-no-properties (point) (+ (point) 1))))))
(defun michelson-goto-previous-application-start ()
(interactive)
(let ((paren-level 0) (application-start 0))
(while (and (not (bobp))
(or (> paren-level 0)
(not (looking-at "[{(;]"))))
(cond ((looking-at "[{(]")
(setq paren-level (- paren-level 1)))
((looking-at "[})]")
(setq paren-level (+ paren-level 1))))
(setq application-start (point))
(michelson-goto-previous-token))
(cons application-start (goto-char application-start))))
(defun michelson-indent ()
"Indent current line of Michelson code."
(interactive)
(let ((new-indentation 0)
(previous-indentation (current-indentation))
(previous-column (current-column))
(current-token
(save-excursion
(beginning-of-line 1)
(michelson-goto-next-token))))
(save-excursion
(end-of-line 0)
(let ((previous-token
(save-excursion (michelson-goto-previous-token)))
(previous-opener
(save-excursion (michelson-goto-opener))))
(cond ((and (not (cdr previous-opener))
(not (cdr previous-token)))
(setq new-indentation 0))
((and (not (cdr previous-opener))
(equal (cdr previous-token) ";"))
(setq new-indentation 0))
((not (cdr previous-opener))
(setq new-indentation 2))
((and (equal (cdr current-token) "}")
(equal (cdr previous-opener) "{"))
(goto-char (car previous-opener))
(setq new-indentation (current-column)))
((and (or (equal (cdr previous-token) ";")
(equal (cdr previous-token) "{"))
(equal (cdr previous-opener) "{"))
(goto-char (car previous-opener))
(setq new-indentation (+ (current-column) 2)))
((equal (cdr previous-opener) "{")
(progn
(michelson-goto-previous-application-start)
(let ((default-param-indentation
(+ (current-column) 2))
(first-param-point
(save-excursion
(michelson-goto-next-token)
(car (michelson-goto-next-token)))))
(if (= first-param-point (car current-token))
(setq new-indentation default-param-indentation)
(progn
(goto-char first-param-point)
(setq new-indentation (current-column)))))))
((and (equal (cdr current-token) ")")
(equal (cdr previous-opener) "("))
(goto-char (car previous-opener))
(setq new-indentation (current-column)))
((equal (cdr previous-token) "(")
(goto-char (car previous-token))
(setq new-indentation (+ (current-column) 1)))
((equal (cdr previous-opener) "(")
(goto-char (car previous-opener))
(setq new-indentation (+ (current-column) 3))))))
(indent-line-to new-indentation)
(beginning-of-line)
(forward-char
(+ (- previous-column previous-indentation) new-indentation))
(when (< (current-column) new-indentation)
(beginning-of-line)
(forward-char new-indentation))))
(defun michelson-token-at-point ()
"Display the token closest to the cursor."
(interactive)
(let ((message
(cdr (save-excursion
(michelson-goto-next-token)
(michelson-goto-previous-token)))))
(display-message-or-buffer message "*Michelson*")))
(cl-defstruct cache
"Cache for types. Invalid entries are removed"
types
errors)
(defvar michelson-cached-buffer-info (make-cache :types '() :errors '()))
(defvar michelson-process-output-buffer "*Michelson-process*")
(defun michelson-erase-process-buffer ()
"Remove all text from process buffer."
(get-buffer-create michelson-process-output-buffer)
(with-current-buffer michelson-process-output-buffer
(erase-buffer)))
(defun michelson-async-command-to-string (command callback)
"Asynchronously execute `COMMAND' and call the `CALLBACK' on the resulting string."
(lexical-let ((command command)
(callback-fun callback))
(deferred:$
(deferred:$
(apply 'deferred:process command)
(deferred:nextc it callback-fun))
;; TODO: make this show only the client error
(deferred:error it (lambda (err) (michelson-write-output-buffer (cadr err)))))))
(defun michelson-clean-cache ()
"Clean the buffer's program info cache."
(let ((types (cache-types michelson-cached-buffer-info))
(errors (cache-errors michelson-cached-buffer-info))
(clean-cache-entry
(lambda (alist)
(remove-if (lambda (entry)
(let ((tok-end (cadr entry)))
(> tok-end (point))))
alist))))
(setq michelson-cached-buffer-info
(make-cache :types (funcall clean-cache-entry types)
:errors (funcall clean-cache-entry errors)))))
(defun michelson-get-info (buffer-name)
"Refresh the info about the program in `BUFFER-NAME' from the command."
(lexical-let ((tmp-file (make-temp-file buffer-name)))
(write-region (point-min) (point-max) tmp-file nil 'no-message)
(let ((command
(append (split-string michelson-client-command " ")
(list
"typecheck"
"script"
(if michelson-alphanet
(concat "container:" tmp-file)
tmp-file)
"-details"
"--emacs"))))
(michelson-async-command-to-string
command
(lambda (output)
(condition-case err
(let*
((record (car (read-from-string output)))
(errors (cdr (assoc 'errors record)))
(types (cdr (assoc 'types record))))
(setq michelson-cached-buffer-info (make-cache :types types :errors errors))
(delete-file tmp-file))
((error err)
(let ((inhibit-message t))
(message output)))))))))
(defvar michelson-output-buffer-name
"*Michelson*")
(defun michelson-output-width ()
(lexical-let* ((buffer (get-buffer-create michelson-output-buffer-name))
(message-window
(if (get-buffer-window buffer)
(get-buffer-window buffer)
(display-buffer-below-selected buffer nil))))
(window-body-width message-window)))
(defvar michelson-output-buffer-map
(let ((map (make-sparse-keymap)))
(set-keymap-parent map special-mode-map)
(define-key map "g" nil)
map)
"Keymap for types buffer.")
(define-derived-mode michelson-stack-mode fundamental-mode "Michelson-stack"
"Major mode for visualizing the Michelson stack."
(interactive)
(use-local-map michelson-output-buffer-map)
(set-syntax-table michelson-mode-syntax-table)
(set
(make-local-variable 'font-lock-defaults)
michelson-font-lock-defaults)
(setq major-mode 'michelson-stack-mode)
(setq mode-name "Michelson-stack")
(setq indent-tabs-mode nil))
(defun michelson-write-output-buffer (data &optional do-not-overwrite)
"Write the given `DATA' to the output buffer.
If `DATA' is a string, it is written directly,
overwriting the data in the buffer.
If `DATA' is a list of strings, the strings are written into the buffer,
with alternating lines highlighted.
If `DO-NOT-OVERWRITE' is non-nil, the existing contents of the buffer are maintained."
(lexical-let*
((buffer (get-buffer-create michelson-output-buffer-name))
(message-window
(if (get-buffer-window buffer)
(get-buffer-window buffer)
(display-buffer-below-selected buffer nil)))
(lines 0))
(when (get-buffer-window buffer)
(set-window-dedicated-p (get-buffer-window buffer) t))
(save-excursion
(set-buffer michelson-output-buffer-name)
(read-only-mode -1)
(unless do-not-overwrite
(erase-buffer))
(goto-char (point-min))
(remove-overlays)
(if (listp data)
(lexical-let ((michelson-highlighting t))
(dolist (ele (reverse data))
(lexical-let ((prev-point (point)))
(insert ele)
(when michelson-highlighting
(overlay-put (make-overlay prev-point (point))
'face 'michelson-stack-highlight-face))
(setq michelson-highlighting (not michelson-highlighting)))))
(insert data))
(with-current-buffer buffer (michelson-stack-mode))
(read-only-mode 1)
(goto-char (point-min))
(while (not (eobp))
(vertical-motion 1)
(setq lines (+ 1 lines)))
(window-resize
message-window
(min (- (window-total-height) 5)
(+ (- (max 4 lines)
(window-size message-window))
2))))))
(defun michelson-format-stack-top (bef-ele aft-ele width)
(lexical-let*
((pp-no-trailing-newline
(lambda (sexp)
(let* ((str (replace-regexp-in-string "\\\\\." "." (pp-to-string sexp)))
(len (length str)))
(if (equal "\n" (substring str (- len 1) len))
(substring str 0 (- len 1))
str))))
(bef-strs (if bef-ele (split-string (funcall pp-no-trailing-newline bef-ele) "\n") '("")))
(aft-strs (if aft-ele (split-string (funcall pp-no-trailing-newline aft-ele) "\n") '("")))
(width width))
(letrec ((format-strings
(lambda (befs afts)
(if (or befs afts)
(let ((aft-stack (if afts (car afts) "")))
(concat (format (format "%%-%ds|%s%%s\n"
(/ width 2)
(if (equal aft-stack "") "" " "))
(if befs (car befs) "")
aft-stack)
(funcall format-strings (cdr befs) (cdr afts))))
""))))
(funcall format-strings bef-strs aft-strs))))
(defun michelson-format-stacks (bef-stack aft-stack)
(letrec ((michelson-format-stacks-help
(lambda (bef aft)
(if (or bef aft)
(cons (michelson-format-stack-top (car bef) (car aft) (michelson-output-width))
(funcall michelson-format-stacks-help (cdr bef) (cdr aft)))
'()))))
(funcall michelson-format-stacks-help (reverse bef-stack) (reverse aft-stack))))
(cl-defstruct michelson-stacks
"A pair of stacks, from `BEF' (before) and `AFT' (after) the instruction"
bef
aft)
(defun michelson-get-previous-stack ()
(save-excursion
(michelson-goto-previous-token)
(lexical-let ((stacks nil)
(brace-count 0)
(break nil))
(while (and (not break)
(not stacks)
(> (point) 0)
(>= brace-count 0))
(backward-char)
(cond ((and (equal (get-text-property (point) 'face)
'michelson-face-instruction)
(= brace-count 0))
(setq break t)
(setq stacks (michelson-stacks-at-loc (point))))
((equal (string (char-after (point))) "{")
(setq brace-count (- brace-count 1)))
((equal (string (char-after (point))) "}")
(setq brace-count (+ brace-count 1)))
(t nil)))
stacks)))
(defun michelson-completion-at-point ()
(let ((prev-stack (michelson-get-previous-stack)))
(if prev-stack
(let* ((bds (bounds-of-thing-at-point 'word))
(start (car bds))
(end (cdr bds))
(completion-stack (michelson-stacks-aft prev-stack))
(instrs (michelson-get-suggestion-list completion-stack)))
(list start end instrs . nil))
nil)))
(defun michelson-stacks-at-loc (loc)
(let ((types-info nil))
(dolist (elt (cache-types michelson-cached-buffer-info))
(when (and (<= (car elt) loc) (<= loc (cadr elt))
(equal (get-text-property loc 'face)
'michelson-face-instruction))
(setq types-info (make-michelson-stacks :bef (caddr elt)
:aft (cadddr elt)))))
types-info))
(defun michelson-show-program-info ()
"Show the program's `TYPES' and `ERRORS'."
(interactive)
(remove-overlays)
(lexical-let* ((stacks (michelson-stacks-at-loc (point)))
(types-info (and stacks (michelson-format-stacks (michelson-stacks-bef stacks)
(michelson-stacks-aft stacks))))
(errors-info nil))
(when michelson-highlight-errors
(dolist (elt (cache-errors michelson-cached-buffer-info))
(overlay-put (make-overlay (car elt) (cadr elt)) 'face 'michelson-face-error)
(when (and (<= (car elt) (point)) (<= (point) (cadr elt)))
(progn
(when michelson-print-errors
(unless errors-info
(setq errors-info (concat errors-info "\n")))
(setq errors-info (concat errors-info (cadr (cdr elt)))))))))
(cond ((and types-info errors-info)
(michelson-write-output-buffer errors-info nil)
(michelson-write-output-buffer types-info t))
(types-info
(michelson-write-output-buffer types-info nil))
(errors-info
(michelson-write-output-buffer errors-info nil))
(t (michelson-write-output-buffer "\nNo information available at point")))))
(defun michelson-type-at-point ()
"Display the type of the expression under the cursor."
(interactive)
(michelson-get-info (buffer-name))
(michelson-show-program-info))
(defun michelson-make-suggest (instr pred)
"Suggest `INSTR' if `PRED' is not nil."
(lexical-let ((instr instr)
(pred pred))
(lambda (stack)
(if (funcall pred stack)
(if (listp instr)
instr
`(,instr))
nil))))
(defun michelson-constrained-p (var hash)
(not (equal var (gethash var hash var))))
(defun michelson-polymorphic-match (tbl match-types stack)
(cond ((not match-types) t)
((not stack) nil)
((and (consp match-types) (consp stack))
(and (michelson-polymorphic-match tbl (car match-types) (car stack))
(michelson-polymorphic-match tbl (cdr match-types) (cdr stack))))
((and (symbolp match-types) (symbolp stack))
(if (and (michelson-constrained-p match-types tbl)
(gethash match-types tbl))
(equal (gethash match-types tbl nil) stack)
(progn
(puthash match-types stack tbl)
t)))
(t nil)))
(defmacro forall (vars matching-stack)
(unless (listp ',vars)
(error "forall must take a list of vars"))
`(lambda (stack)
(let ((tbl (make-hash-table :test 'equal)))
,@(mapcar (lambda (var) `(puthash ',var ',var tbl)) vars)
(michelson-polymorphic-match tbl ',matching-stack stack))))
(defun michelson-literals-match-p (types)
"Generate a predicate that matches `TYPES' against the top of the stack."
(lexical-let ((types types))
(lambda (stack)
(michelson-polymorphic-match
(make-hash-table :test 'equal)
types
stack))))
(defun michelson-suggest-literals (instr &rest types)
"Suggest `INSTR' when `TYPES' are on the top of the stack."
(michelson-make-suggest
instr
(michelson-literals-match-p types)))
(defun michelson-suggest-or (instr pred1 pred2)
(lexical-let ((pred1 pred1)
(pred2 pred2))
(michelson-make-suggest
instr
(lambda (stack) (or (funcall pred1 stack) (funcall pred2 stack))))))
(defun michelson-suggest-reorderable (instr type1 type2)
(michelson-suggest-or instr
(michelson-literals-match-p `(,type1 ,type2))
(michelson-literals-match-p `(,type2 ,type1))))
(defvar michelson-suggest-always-available
'("FAIL" "PUSH" "UNIT" "LAMBDA" "NONE"
"EMPTY_SET" "EMPTY_MAP" "NIL" "BALANCE"
"AMOUNT" "STEPS_TO_QUOTA" "NOW"))
(defun michelson-comparable-p (type)
"Is the `TYPE' comparable?"
(memq type '(int nat string tez bool key timestamp)))
(defun michelson-suggest-pairs-help (pair-type accessor-prefix)
"Suggest all possible pair accessors on the given `PAIR-TYPE' and `ACCESSOR-PREFIX'."
(cons (concat accessor-prefix "R")
(if (and (consp pair-type) (equal (car pair-type) 'pair))
(let ((car-ele (cadr pair-type))
(cdr-ele (caddr pair-type)))
(append
(michelson-suggest-pairs-help car-ele
(concat accessor-prefix "A"))
(michelson-suggest-pairs-help car-ele
(concat accessor-prefix "D"))
'())))))
(defun michelson-suggest-pairs (stack)
"Suggest all possible pair accessors on the given `STACK'."
(if (and (consp (car stack)) (equal (caar stack) 'pair))
(append (michelson-suggest-pairs-help (cadar stack) "CA")
(michelson-suggest-pairs-help (caddar stack) "CD")
nil)))
(defconst michelson-comparison-operations
'("EQ" "NEQ" "LT" "LE" "GT" "GE"))
(defun michelson-suggest-comparable (stack)
(let ((first (car stack))
(second (cadr stack)))
(if (and first
second
(michelson-comparable-p first)
(equal first second))
(cons
"COMPARE"
(append
(mapcar (lambda (x) (concat "CMP" x))
michelson-comparison-operations)
(mapcar (lambda (x) (concat "IFCMP" x))
michelson-comparison-operations)))
'())))
(defun michelson-suggest-depth (instrs depth)
"Suggest `INSTRS' if the stack depth is greater than or equal to `DEPTH'."
(michelson-make-suggest
instrs
(lexical-let ((depth depth))
(lambda (stack) (>= (length stack) depth)))))
(defun michelson-suggest-prefix-depth (prefix additional suffix)
(lexical-let ((prefix prefix)
(additional additional)
(suffix suffix))
(lambda (stack)
(reverse (car (reduce
(lambda (acc ele)
(lexical-let ((existing (car acc))
(prefix (concat (cdr acc) additional)))
(cons (cons (concat prefix suffix) existing)
prefix)))
stack
:initial-value (cons nil "D")))))))
(defvar michelson-type-completion-list
(list
(michelson-make-suggest "EXEC" (forall (arg ret) (arg (lambda arg ret))))
(michelson-make-suggest "MEM" (forall (val-type) (val-type (set val-type))))
(michelson-make-suggest "MEM" (forall (key-type val-type) (key-type (map key-type val-type))))
(michelson-make-suggest "UPDATE" (forall (val-type) (val-type bool (set val-type))))
(michelson-make-suggest "UPDATE" (forall (key-type val-type)
(key-type (option val-type) (map key-type val-type))))
(michelson-make-suggest "MAP" (forall (lt rt) ((lambda lt rt) (list lt))))
(michelson-make-suggest "MAP" (forall (k v b) ((lambda (pair k v) b) (map k v))))
(michelson-suggest-literals "IF" 'bool)
(michelson-suggest-literals "LOOP" 'bool)
(michelson-suggest-literals michelson-comparison-operations 'int)
'michelson-suggest-comparable
'michelson-suggest-pairs
(michelson-suggest-prefix-depth "D" "I" "P")
(michelson-suggest-prefix-depth "D" "U" "P")
(lambda (stack) (and (cdr stack)
(funcall (michelson-suggest-prefix-depth "PA" "A" "IP") (cdr stack))))
(michelson-suggest-literals "NOT" 'bool)
(michelson-suggest-literals '("OR" "AND" "XOR") 'bool 'bool)
(michelson-suggest-literals "ABS" 'int)
(michelson-make-suggest
'("ADD" "SUB" "MUL" "EDIV")
(lambda (stack)
(let ((first (car stack))
(second (cadr stack))
(intnat '(int nat)))
(and first
second
(memq first intnat)
(memq second intnat)))))
(michelson-suggest-reorderable "ADD" 'nat 'timestamp)
(michelson-suggest-literals "NOT" 'int)
(michelson-suggest-literals '("OR" "AND" "XOR" "LSL" "LSR") 'nat 'nat)
(michelson-suggest-literals '("CONCAT") 'string 'string)
(michelson-suggest-depth '("SOME" "LEFT" "RIGHT") 1)
(michelson-suggest-literals '("ADD" "SUB") 'tez 'tez)
(michelson-suggest-reorderable '("ADD" "SUB" "MUL") 'tez 'nat)
(michelson-suggest-literals "EDIV" 'tez 'nat)
(michelson-suggest-literals "EDIV" 'tez 'tez)
(michelson-suggest-literals "IMPLICIT_ACCOUNT" 'key)
(michelson-suggest-depth "SWAP" 2)
(michelson-suggest-depth '("DROP" "H") 1)
(michelson-suggest-literals "CHECK_SIGNATURE" 'key '(pair signature string))
(michelson-suggest-literals "CREATE_ACCOUNT" 'key '(option key) 'bool 'tez)
(michelson-make-suggest "IF_NONE" (forall (x) (option x)))
(michelson-make-suggest "IF_LEFT" (forall (x y) (or x y)))
;; This is not exactly the type of TRANSFER_TOKENS.
;; It will be changed once the concurrency model is worked out
(michelson-make-suggest "TRANSFER_TOKENS" (forall (p r g) (p tez (contract p r) g)))
(michelson-make-suggest
"CREATE_CONTRACT"
(forall (p r g) (key (option key) bool bool tez (lambda (pair p g) (pair r g)) g)))
(michelson-make-suggest "MANAGER" (forall (p r) ((contract p r))))
(michelson-make-suggest "CONS" (forall (a) (a (list a))))
(michelson-make-suggest "IF_CONS" (forall (a) (list a)))
(michelson-make-suggest "GET" (forall (k v) (k (map k v))))
(michelson-make-suggest "UPDATE" (forall (v) (v bool (set v))))
(michelson-make-suggest "UPDATE" (forall (k v) (k (option v) (map k v))))
(michelson-make-suggest "REDUCE" (forall (elt b) ((lambda (pair elt b) b) (set elt) b)))
(michelson-make-suggest "REDUCE" (forall (key val b) ((lambda (pair (pair key val) b) b) (map key val) b)))
(michelson-make-suggest "REDUCE" (forall (a b) ((lambda (pair a b) b) (list a) b)))
))
;; Special handling
;; PA+IR
(defun michelson-get-suggestion-list (stack)
(lexical-let ((stack stack))
(reduce (lambda (func acc) (append (funcall func stack) acc))
michelson-type-completion-list
:from-end t
:initial-value michelson-suggest-always-available)))
(defun michelson-toggle-live-editing ()
"Toggle `michelson-live-editing'.
Enables or disables stack and error display."
(interactive)
(when (and michelson-live-editing
(get-buffer michelson-output-buffer-name))
(save-excursion
(set-buffer michelson-output-buffer-name)
(kill-buffer-and-window)))
(setq michelson-live-editing (not michelson-live-editing)))
(defun michelson-update-minibuffer-info ()
(when (nth 2 michelson-state)
(cancel-timer (nth 2 michelson-state)))
(setf
(nth 2 michelson-state)
(run-at-time
"0.3 sec" nil
(lambda (buffer)
(with-current-buffer buffer
(setf (nth 2 michelson-state) nil)
(when (and (not (= (nth 0 michelson-state) (point)))
michelson-live-editing)
(setf (nth 0 michelson-state) (point))
(michelson-type-at-point))))
(current-buffer))))
(defun michelson-close-output-buffer ()
"Close the interactive editing buffer."
(interactive)
(let ((buffer (get-buffer michelson-output-buffer-name)))
(when buffer
(let ((window (get-buffer-window buffer)))
(if window (quit-window t window) (kill-buffer buffer))))))
(define-derived-mode michelson-mode prog-mode "Michelson"
"Major mode for editing Michelson smart contracts."
(interactive)
(kill-all-local-variables)
(use-local-map michelson-mode-map)
(set-syntax-table michelson-mode-syntax-table)
(set
(make-local-variable 'font-lock-defaults)
michelson-font-lock-defaults)
(set
(make-local-variable 'indent-line-function)
'michelson-indent)
(set
(make-local-variable 'indent-for-tab-command)
'michelson-indent)
(set
(make-local-variable 'michelson-state)
(list 0 0 nil))
(set (make-local-variable 'michelson-cached-buffer-info)
(make-cache :types nil
:errors nil))
(add-to-list
(make-local-variable 'pre-command-hook)
'michelson-update-minibuffer-info)
(add-to-list
(make-local-variable 'focus-in-hook)
'michelson-update-minibuffer-info)
(add-hook 'post-self-insert-hook 'michelson-clean-cache)
(add-hook 'kill-buffer-hook 'michelson-close-output-buffer t t)
(setq major-mode 'michelson-mode)
(setq mode-name "Michelson")
(setq indent-tabs-mode nil)
(setq show-trailing-whitespace t)
(setq buffer-file-coding-system 'utf-8-unix)
(add-hook 'completion-at-point-functions 'michelson-completion-at-point nil 'local)
(setq-local company-backends '(company-capf))
(setq-local process-environment
(cons "TEZOS_CLIENT_UNSAFE_DISABLE_DISCLAIMER=Y"
(cons "ALPHANET_EMACS=true"
(cons "TEZOS_ALPHANET_DO_NOT_PULL=yes"
process-environment))))
(run-hooks 'michelson-mode-hook))
(add-to-list 'auto-mode-alist '("\\.tz\\'" . michelson-mode))
(add-to-list 'auto-mode-alist '("\\.tez\\'" . michelson-mode))
(provide 'michelson-mode)

View File

@ -0,0 +1,89 @@
#! /bin/bash
set -e
usage="Usage:
$ ./scripts/activate_protocol.sh src/proto_004_PtDPBVyN
Inserts the protocol in the right files of the build system to compile it
If in master activates in addition to alpha.
If in mainnet activates in addition to its predecessor, here proto_003_PsddFKi3."
script_dir="$(cd "$(dirname "$0")" && echo "$(pwd -P)/")"
cd "$script_dir"/..
if [ ! -d "$1" ]; then
echo "$usage"
exit 1
fi
is_mainnet () {
# need to check a real file because of phantom git directories
if [ -f "src/proto_000_Ps9mPmXa/lib_protocol/src/TEZOS_PROTOCOL" ]
then return 0; else return 1; fi
}
new_version=$(basename $1 | awk -F'_' '{print $2}')
new_hash=$(basename $1 | awk -F'_' '{print $3}')
full_hash=$(jq .hash < $1/lib_protocol/src/TEZOS_PROTOCOL)
replacement=${new_version}-${new_hash}
if [[ -z "${new_version}" || -z "${new_hash}" || -z "${full_hash}" ]] ; then
echo "$usage"
exit 1
fi
# The pattern to look for, "alpha" for master or "00X-<hash>" for mainnet.
# Once found it's either replaced or the line is duplicated and then replaced
if is_mainnet
then
old_version=$( printf '%03d' $(($new_version -1)) )
old_dir=$(ls -d src/proto_${old_version}_*)
old_hash=$(basename $old_dir | awk -F'_' '{print $3}')
pattern=${old_version}-${old_hash}
else
pattern="alpha"
fi
# if a line matches PATTERN, a new line is printed where the pattern is replaced
duplicate_and_replace() {
PATTERN=$1
REPLACEMENT=$2
shift 2
awk -i inplace '{
print
if ($0 ~ PATTERN) {
sub(PATTERN,REPLACEMENT)
print
}}' PATTERN=$PATTERN REPLACEMENT=$REPLACEMENT $*
}
# the minimum needed, although you can't bake
duplicate_and_replace ${pattern} ${replacement} active_protocol_versions
# activate in client to bake and use RPCs
duplicate_and_replace -${pattern} -${replacement} \
src/bin_client/{dune,tezos-client.opam}
read -p "Link in the Node? (no if you want to test injection) (Y/n) " ans
if [[ "$ans" == "Y" || "$ans" == "y" || -z "$ans" ]]; then
duplicate_and_replace -${pattern} -${replacement} \
src/bin_node/{dune,tezos-node.opam}
fi
read -p "User-activated update in 3 blocks? (Y/n) " ans
if [[ "$ans" == "Y" || "$ans" == "y" || -z "$ans" ]]; then
# clean existing lines, if any
awk -i inplace '
BEGIN{found=0}{
if (!found && $0 ~ "let forced_protocol_upgrades")
{found=1; print}
else {
if (found && $0 ~ "^]")
{found=0; print }
else
{ if (!found){print}}
}}' src/lib_base/block_header.ml
sed -i '/let forced_protocol_upgrades/ a \ \ 3l, Protocol_hash.of_b58check_exn '${full_hash}' ;' \
src/lib_base/block_header.ml
fi

829
vendors/tezos-modded/scripts/alphanet.sh vendored Executable file
View File

@ -0,0 +1,829 @@
#! /usr/bin/env bash
set -e
if ! which docker > /dev/null 2>&1 ; then
echo "Docker does not seem to be installed."
exit 1
fi
if ! which docker-compose > /dev/null 2>&1 ; then
echo "Docker-compose does not seem to be installed."
exit 1
fi
docker_version="$(docker version -f "{{ .Server.Version }}")"
docker_major="$(echo "$docker_version" | cut -d . -f 1)"
docker_minor="$(echo "$docker_version" | cut -d . -f 2)"
if ([ "$docker_major" -gt 1 ] ||
( [ "$docker_major" -eq 1 ] && [ "$docker_minor" -ge 13 ] )) ; then
docker_1_13=true
else
docker_1_13=false
fi
current_dir="$(pwd -P)"
src_dir="$(cd "$(dirname "$0")" && echo "$current_dir/")"
cd "$src_dir"
update_compose_file() {
update_active_protocol_version
if [ "$#" -ge 2 ] && [ "$1" = "--rpc-port" ] ; then
export_rpc="
- \"$2:8732\""
shift 2
fi
cat > "$docker_compose_yml" <<EOF
version: "2"
volumes:
node_data:
client_data:
services:
node:
image: $docker_image
hostname: node
command: tezos-node --net-addr :$port $@
ports:
- "$port:$port"$export_rpc
expose:
- "8732"
volumes:
- node_data:/var/run/tezos/node
- client_data:/var/run/tezos/client
restart: on-failure
EOF
for proto in $(cat "$active_protocol_versions") ; do
cat >> "$docker_compose_yml" <<EOF
baker-$proto:
image: $docker_image
hostname: baker-$proto
environment:
- PROTOCOL=$proto
command: tezos-baker --max-priority 128
links:
- node
volumes:
- node_data:/var/run/tezos/node:ro
- client_data:/var/run/tezos/client
restart: on-failure
endorser-$proto:
image: $docker_image
hostname: endorser-$proto
environment:
- PROTOCOL=$proto
command: tezos-endorser
links:
- node
volumes:
- client_data:/var/run/tezos/client
restart: on-failure
accuser-$proto:
image: $docker_image
hostname: accuser-$proto
environment:
- PROTOCOL=$proto
command: tezos-accuser
links:
- node
volumes:
- client_data:/var/run/tezos/client
restart: on-failure
EOF
done
}
call_docker_compose() {
docker-compose -f "$docker_compose_yml" -p "$docker_compose_name" "$@"
}
exec_docker() {
if [ -t 0 ] && [ -t 1 ] && [ -t 2 ] && [ -z "$ALPHANET_EMACS" ]; then
local interactive_flags="-it"
else
local interactive_flags="-t"
fi
local node_container="$(container_name "$docker_node_container")"
declare -a container_args=();
tmpdir="/tmp"
for arg in "$@"; do
if [[ "$arg" == 'container:'* ]]; then
local_path="${arg#container:}"
if [[ "$local_path" != '/'* ]]; then
local_path="$current_dir/$local_path"
fi
file_name=$(basename "${local_path}")
docker_path="$tmpdir/$file_name"
docker cp "${local_path}" "$node_container:${docker_path}"
docker exec "$interactive_flags" "$node_container" sudo chown tezos "${docker_path}"
container_args+=("file:$docker_path");
else
container_args+=("${arg}");
fi
done
docker exec "$interactive_flags" -e 'TEZOS_CLIENT_UNSAFE_DISABLE_DISCLAIMER' "$node_container" "${container_args[@]}"
}
## Container ###############################################################
update_active_protocol_version() {
docker run --entrypoint /bin/cat "$docker_image" \
/usr/local/share/tezos/active_protocol_versions > "$active_protocol_versions"
}
may_update_active_protocol_version() {
if [ ! -f "$active_protocol_versions" ] ; then
update_active_protocol_version
fi
}
pull_image() {
if [ "$TEZOS_ALPHANET_DO_NOT_PULL" = "yes" ] \
|| [ "$ALPHANET_EMACS" ] \
|| [ "$docker_image" = "$(echo $docker_image | tr -d '/')" ] ; then
return ;
fi
docker pull "$docker_image"
update_active_protocol_version
date "+%s" > "$docker_pull_timestamp"
}
may_pull_image() {
if [ ! -f "$docker_pull_timestamp" ] \
|| [ 3600 -le $(($(date "+%s") - $(cat $docker_pull_timestamp))) ]; then
pull_image
fi
}
uptodate_container() {
running_image=$(docker inspect \
--format="{{ .Image }}" \
--type=container "$(container_name "$1")")
latest_image=$(docker inspect \
--format="{{ .Id }}" \
--type=image "$docker_image")
[ "$latest_image" = "$running_image" ]
}
uptodate_containers() {
container=$1
if [ ! -z "$container" ]; then
shift 1
uptodate_container $container && uptodate_containers $@
fi
}
assert_container() {
call_docker_compose up --no-start
}
container_name() {
local name="$(docker ps --filter "name=$1" --format "{{.Names}}")"
if [ -n "$name" ]; then echo "$name"; else echo "$1"; fi
}
## Node ####################################################################
check_node_volume() {
docker volume inspect "$docker_node_volume" > /dev/null 2>&1
}
clear_node_volume() {
if check_node; then
echo -e "\033[31mCannot clear data while the node is running.\033[0m"
exit 1
fi
if check_node_volume ; then
docker volume rm "$docker_node_volume" > /dev/null
echo -e "\033[32mThe chain data has been removed from the disk.\033[0m"
else
echo -e "\033[32mNo remaining data to be removed from the disk.\033[0m"
fi
}
check_node() {
res=$(docker inspect \
--format="{{ .State.Running }}" \
--type=container "$(container_name "$docker_node_container")" 2>/dev/null || echo false)
[ "$res" = "true" ]
}
assert_node() {
if ! check_node; then
echo -e "\033[31mNode is not running!\033[0m"
exit 0
fi
}
warn_node_uptodate() {
if ! uptodate_container "$docker_node_container"; then
echo -e "\033[33mThe current node is not the latest available.\033[0m"
fi
}
assert_node_uptodate() {
may_pull_image
assert_node
if ! uptodate_container "$docker_node_container"; then
echo -e "\033[33mThe current node is not the latest available.\033[0m"
exit 1
fi
}
status_node() {
may_pull_image
if check_node; then
echo -e "\033[32mNode is running\033[0m"
warn_node_uptodate
else
echo -e "\033[33mNode is not running\033[0m"
fi
}
start_node() {
pull_image
if check_node; then
echo -e "\033[31mNode is already running\033[0m"
exit 1
fi
update_compose_file "$@"
call_docker_compose up --no-start
call_docker_compose start node
echo -e "\033[32mThe node is now running.\033[0m"
}
log_node() {
may_pull_image
assert_node_uptodate
call_docker_compose logs -f node
}
stop_node() {
if ! check_node; then
echo -e "\033[31mNo node to kill!\033[0m"
exit 1
fi
echo -e "\033[32mStopping the node...\033[0m"
call_docker_compose stop node
}
## Baker ###################################################################
check_baker() {
update_active_protocol_version
bakers="$(sed s/^/baker-/g "$active_protocol_versions")"
docker_baker_containers="$(sed "s/^\(.*\)$/${docker_compose_name}_baker-\1_1/g" "$active_protocol_versions")"
res=$(docker inspect \
--format="{{ .State.Running }}" \
--type=container "$(container_name "$docker_baker_containers")" 2>/dev/null || echo false)
[ "$res" = "true" ]
}
assert_baker() {
if ! check_baker; then
echo -e "\033[31mBaker is not running!\033[0m"
exit 0
fi
}
assert_baker_uptodate() {
assert_baker
if ! uptodate_containers $docker_baker_containers; then
echo -e "\033[33mThe current baker is not the latest available.\033[0m"
exit 1
fi
}
status_baker() {
if check_baker; then
echo -e "\033[32mBaker is running\033[0m"
may_pull_image
if ! uptodate_containers $docker_baker_containers; then
echo -e "\033[33mThe current baker is not the latest available.\033[0m"
fi
else
echo -e "\033[33mBaker is not running\033[0m"
fi
}
start_baker() {
if check_baker; then
echo -e "\033[31mBaker is already running\033[0m"
exit 1
fi
pull_image
assert_node_uptodate
call_docker_compose start $bakers
echo -e "\033[32mThe baker is now running.\033[0m"
}
log_baker() {
may_pull_image
assert_baker_uptodate
call_docker_compose logs -f $bakers
}
stop_baker() {
if ! check_baker; then
echo -e "\033[31mNo baker to kill!\033[0m"
exit 1
fi
echo -e "\033[32mStopping the baker...\033[0m"
call_docker_compose stop $bakers
}
## Endorser ###################################################################
check_endorser() {
update_active_protocol_version
endorsers="$(sed s/^/endorser-/g "$active_protocol_versions")"
docker_endorser_containers="$(sed "s/^\(.*\)$/${docker_compose_name}_endorser-\1_1/g" "$active_protocol_versions")"
res=$(docker inspect \
--format="{{ .State.Running }}" \
--type=container "$(container_name "$docker_endorser_containers")" 2>/dev/null || echo false)
[ "$res" = "true" ]
}
assert_endorser() {
if ! check_endorser; then
echo -e "\033[31mEndorser is not running!\033[0m"
exit 0
fi
}
assert_endorser_uptodate() {
assert_endorser
if ! uptodate_containers $docker_endorser_containers; then
echo -e "\033[33mThe current endorser is not the latest available.\033[0m"
exit 1
fi
}
status_endorser() {
if check_endorser; then
echo -e "\033[32mEndorser is running\033[0m"
may_pull_image
if ! uptodate_containers $docker_endorser_containers; then
echo -e "\033[33mThe current endorser is not the latest available.\033[0m"
fi
else
echo -e "\033[33mEndorser is not running\033[0m"
fi
}
start_endorser() {
if check_endorser; then
echo -e "\033[31mEndorser is already running\033[0m"
exit 1
fi
pull_image
assert_node_uptodate
call_docker_compose start $endorsers
echo -e "\033[32mThe endorser is now running.\033[0m"
}
log_endorser() {
may_pull_image
assert_endorser_uptodate
call_docker_compose logs -f $endorsers
}
stop_endorser() {
if ! check_endorser; then
echo -e "\033[31mNo endorser to kill!\033[0m"
exit 1
fi
echo -e "\033[32mStopping the endorser...\033[0m"
call_docker_compose stop $endorsers
}
## Accuser ###################################################################
check_accuser() {
update_active_protocol_version
accusers="$(sed s/^/accuser-/g "$active_protocol_versions")"
docker_accuser_containers="$(sed "s/^\(.*\)$/${docker_compose_name}_accuser-\1_1/g" "$active_protocol_versions")"
res=$(docker inspect \
--format="{{ .State.Running }}" \
--type=container "$(container_name "$docker_accuser_containers")" 2>/dev/null || echo false)
[ "$res" = "true" ]
}
assert_accuser() {
if ! check_accuser; then
echo -e "\033[31mAccuser is not running!\033[0m"
exit 0
fi
}
assert_accuser_uptodate() {
assert_accuser
if ! uptodate_containers $docker_accuser_containers; then
echo -e "\033[33mThe current accuser is not the latest available.\033[0m"
exit 1
fi
}
status_accuser() {
if check_accuser; then
echo -e "\033[32mAccuser is running\033[0m"
may_pull_image
if ! uptodate_containers $docker_accuser_containers; then
echo -e "\033[33mThe current accuser is not the latest available.\033[0m"
fi
else
echo -e "\033[33mAccuser is not running\033[0m"
fi
}
start_accuser() {
if check_accuser; then
echo -e "\033[31mAccuser is already running\033[0m"
exit 1
fi
pull_image
assert_node_uptodate
call_docker_compose start $accusers
echo -e "\033[32mThe accuser is now running.\033[0m"
}
log_accuser() {
may_pull_image
assert_accuser_uptodate
call_docker_compose logs -f $accusers
}
stop_accuser() {
if ! check_accuser; then
echo -e "\033[31mNo accuser to kill!\033[0m"
exit 1
fi
echo -e "\033[32mStopping the accuser...\033[0m"
call_docker_compose stop $accusers
}
## Misc ####################################################################
run_client() {
assert_node_uptodate
exec_docker "tezos-client" "$@"
}
run_admin_client() {
assert_node_uptodate
exec_docker "tezos-admin-client" "$@"
}
run_shell() {
assert_node_uptodate
if [ $# -eq 0 ]; then
exec_docker /bin/sh
else
exec_docker /bin/sh -c "$@"
fi
}
display_head() {
assert_node_uptodate
exec_docker tezos-client rpc get /chains/main/blocks/head/header
}
## Main ####################################################################
start() {
pull_image
update_compose_file "$@"
call_docker_compose up -d --remove-orphans
warn_script_uptodate
}
stop() {
call_docker_compose down
}
kill_() {
call_docker_compose kill
stop
}
status() {
status_node
status_baker
status_endorser
warn_script_uptodate verbose
}
warn_script_uptodate() {
if [[ $ALPHANET_EMACS ]]; then
return
fi
docker run --entrypoint /bin/cat "$docker_image" \
"/usr/local/share/tezos/alphanet.sh" > ".alphanet.sh.new"
if ! diff .alphanet.sh.new "$0" >/dev/null 2>&1 ; then
echo -e "\033[33mWarning: the container contains a new version of 'alphanet.sh'.\033[0m"
echo -e "\033[33mYou might run '$0 update_script' to synchronize.\033[0m"
elif [ "$1" = "verbose" ] ; then
echo -e "\033[32mThe script is up to date.\033[0m"
fi
rm .alphanet.sh.new
}
update_script() {
docker run --entrypoint /bin/cat "$docker_image" \
"/usr/local/share/tezos/alphanet.sh" > ".alphanet.sh.new"
if ! diff .alphanet.sh.new "$0" >/dev/null 2>&1 ; then
mv .alphanet.sh.new "$0"
echo -e "\033[32mThe script has been updated.\033[0m"
else
rm .alphanet.sh.new
echo -e "\033[32mThe script is up to date.\033[0m"
fi
}
usage() {
echo "Usage: $0 [GLOBAL_OPTIONS] <command> [OPTIONS]"
echo " Main commands:"
echo " $0 start [--rpc-port <int>] [OPTIONS]"
echo " Launch a full Tezos alphanet node in a docker container"
echo " automatically generating a new network identity."
echo " OPTIONS (others than --rpc-port) are directly passed to the"
echo " Tezos node, see '$0 shell tezos-node config --help'"
echo " for more details."
echo " By default, the RPC port is not exported outside the docker"
echo " container. WARNING: when exported some RPCs could be harmful"
echo " (e.g. 'inject_block', 'force_validation', ...), it is"
echo " advised not to export them publicly."
echo " $0 <stop|kill>"
echo " Friendly or brutally stop the node."
echo " $0 restart"
echo " Friendly stop the node, fetch the latest docker image and "
echo " update this script, then start the node again."
echo " The blockchain data are preserved."
echo " $0 clear"
echo " Remove all the blockchain data from the disk (except"
echo " for secret keys and other configuration backup)."
echo " $0 status"
echo " Check that the running node is running and up to date."
echo " Upgrade is automatically done by the start command."
echo " $0 head"
echo " Display info about the current head of the blockchain."
echo " $0 client <COMMAND>"
echo " Pass a command to the tezos client."
echo " $0 update_script"
echo " Replace 'alphanet.sh' with the one found in the docker image."
echo " Advanced commands:"
echo " $0 node <start|stop|status|log>"
echo " $0 baker <start|stop|status|log>"
echo " $0 endorser <start|stop|status|log>"
echo " $0 shell"
echo "Node configuration backup directory: $data_dir"
echo "Global options are currently limited to:"
echo " --port <int>"
echo " change public the port Tezos node"
echo "Container prefix:"
echo " container:<FILE>"
echo " can be used anywhere 'file:<FILE>' is permitted in client commands."
echo " It will cause the referenced file to be copied into the docker conainer."
echo " Files will be renamed, which may make errors difficult to read"
}
## Dispatch ################################################################
if [ "$#" -ge 2 ] && [ "$1" = "--port" ] ; then
port="$2"
suffix="$port"
shift 2
fi
command="$1"
if [ "$#" -eq 0 ] ; then usage ; exit 1; else shift ; fi
case $(basename "$0") in
localnet.sh)
docker_base_dir="$HOME/.tezos-localnet"
docker_image=tezos:latest
docker_compose_base_name=localnet
default_port=14732
;;
zeronet.sh)
docker_base_dir="$HOME/.tezos-zeronet"
docker_image=tezos/tezos:zeronet
docker_compose_base_name=zeronet
default_port=19732
;;
betanet.sh)
if [ -d "$HOME/.tezos-mainnet" ] ; then
echo 'You already upgraded, please only use `mainnet.sh` now.'
exit 1
else
echo 'A new script `mainnet.sh` is now available.'
echo 'The current `betanet.sh` still works, but we recommend that you upgrade.'
fi
docker_base_dir="$HOME/.tezos-betanet"
docker_image=tezos/tezos:mainnet
docker_compose_base_name=betanet
default_port=9732
;;
mainnet.sh)
if [ -d "$HOME/.tezos-betanet" ] ; then
echo 'Folder "'$HOME'/.tezos-betanet" detected.'
echo 'To upgrade to the mainnet script, execute the following commands.'
echo ' `betanet.sh stop`'
echo 'Make sure that your node is stopped using `docker ps`.'
echo ' `mv "'$HOME'/.tezos-betanet" "'$HOME'/.tezos-mainnet"`'
echo ' `mainnet.sh start`'
exit 1
fi
docker_base_dir="$HOME/.tezos-mainnet"
docker_image=tezos/tezos:mainnet
docker_compose_base_name=mainnet
default_port=9732
;;
*)
docker_base_dir="$HOME/.tezos-alphanet"
docker_image=tezos/tezos:alphanet
docker_compose_base_name="alphanet"
default_port=9732
;;
esac
if [ -n "$suffix" ] ; then
mkdir -p "$docker_base_dir"
echo "$port" > "$docker_base_dir/default_port"
elif [ -f "$docker_base_dir/default_port" ]; then
port=$(cat "$docker_base_dir/default_port")
suffix="$port"
else
port=$default_port
fi
docker_dir="$docker_base_dir$suffix"
docker_compose_yml="$docker_dir/docker-compose.yml"
docker_pull_timestamp="$docker_dir/docker_pull.timestamp"
active_protocol_versions="$docker_dir/active_protocol_versions"
docker_compose_name="$docker_compose_base_name$suffix"
docker_node_container=${docker_compose_name}_node_1
docker_node_volume=${docker_compose_name}_node_data
docker_client_volume=${docker_compose_name}_client_data
mkdir -p "$docker_dir"
case "$command" in
## Main
start)
start "$@"
;;
restart)
stop
update_script
export TEZOS_ALPHANET_DO_NOT_PULL=yes
exec "$0" start "$@"
;;
clear)
clear_node_volume
;;
status)
status
;;
stop)
stop
;;
kill)
kill_
;;
## Node
node)
subcommand="$1"
if [ "$#" -eq 0 ] ; then usage ; exit 1; else shift ; fi
case "$subcommand" in
start)
start_node "$@"
;;
status)
status_node
;;
log)
log_node
;;
stop)
stop_node
;;
*)
usage
exit 1
esac ;;
## Baker
baker)
subcommand="$1"
if [ "$#" -eq 0 ] ; then usage ; exit 1; else shift ; fi
case "$subcommand" in
status)
status_baker
;;
start)
start_baker
;;
log)
log_baker
;;
stop)
stop_baker
;;
*)
usage
exit 1
esac ;;
## Endorser
endorser)
subcommand="$1"
if [ "$#" -eq 0 ] ; then usage ; exit 1; else shift ; fi
case "$subcommand" in
status)
status_endorser
;;
start)
start_endorser
;;
log)
log_endorser
;;
stop)
stop_endorser
;;
*)
usage
exit 1
esac ;;
## Accuser
accuser)
subcommand="$1"
if [ "$#" -eq 0 ] ; then usage ; exit 1; else shift ; fi
case "$subcommand" in
status)
status_accuser
;;
start)
start_accuser
;;
log)
log_accuser
;;
stop)
stop_accuser
;;
*)
usage
exit 1
esac ;;
## Misc.
head)
display_head
;;
shell)
run_shell "$@"
;;
client)
run_client "$@"
;;
admin-client)
run_admin_client "$@"
;;
check_script)
warn_script_uptodate verbose
;;
update_script)
update_script
;;
*)
usage
exit 1
;;
esac

View File

@ -0,0 +1,20 @@
diff --git a/src/proto_alpha/lib_protocol/src/constants_repr.ml b/src/proto_alpha/lib_protocol/src/constants_repr.ml
index 8ccaaee8..d17c4ada 100644
--- a/src/proto_alpha/lib_protocol/src/constants_repr.ml
+++ b/src/proto_alpha/lib_protocol/src/constants_repr.ml
@@ -68,12 +68,12 @@ let read_public_key s = Ed25519.Public_key.of_hex_exn (`Hex s)
let default = {
preserved_cycles = 5 ;
- blocks_per_cycle = 4096l ;
+ blocks_per_cycle = 128l ;
blocks_per_commitment = 32l ;
- blocks_per_roll_snapshot = 256l ;
+ blocks_per_roll_snapshot = 8l ;
blocks_per_voting_period = 32768l ;
time_between_blocks =
- List.map Period_repr.of_seconds_exn [ 60L ] ;
+ List.map Period_repr.of_seconds_exn [ 60L ; 30L ; 20L ; 10L ] ;
first_free_baking_slot = 16 ;
endorsers_per_block = 32 ;
max_gas = 40_000 ;

View File

@ -0,0 +1 @@
2018-06-30T16:07:32Z

35
vendors/tezos-modded/scripts/apply_patch.sh vendored Executable file
View File

@ -0,0 +1,35 @@
#! /bin/sh
script_dir="$(cd "$(dirname "$0")" && echo "$(pwd -P)/")"
cd "$script_dir"/..
branch=$1
has_git() {
which git && [ -d .git ]
}
if has_git && ! [ -z "$(git status -s)" ] ; then
echo "This script cannot be applied within a dirty git directory,"
echo "you need 'stash' or 'commit' your changes before."
exit 1
fi
set -e
case "$branch" in
zeronet)
sed -i s/TEZOS/TEZOS_ZERONET/ ./src/lib_shell/distributed_db_message.ml
patch -p1 < scripts/alphanet_constants.patch
patch -p1 < scripts/zeronet.patch
if has_git; then git commit -a -m "Zeronet: change economic constants." --author "Tezos CI <null@tezos.com>"; fi
echo "Done"
;;
alphanet)
sed -i s/TEZOS/TEZOS_ALPHANET/ ./src/lib_shell/distributed_db_message.ml
patch -p1 < scripts/alphanet_constants.patch
if has_git; then git commit -a -m "Alphanet: change economic constants." --author "Tezos CI <null@tezos.com>"; fi
echo "Done"
;;
*)
echo "Noop"
esac

44
vendors/tezos-modded/scripts/b58_prefix.py vendored Executable file
View File

@ -0,0 +1,44 @@
#! /usr/bin/env python
import sys
import bitcoin
alphabet = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'
def b58dec(word):
x = 0
for c in word:
x *= 58
x += alphabet.find(c)
return x
def asciidec(val):
word = []
while val > 0:
word.append(val % 256)
val /= 256
return word[-1::-1]
if __name__ == '__main__':
prefix = sys.argv[1]
length = int(sys.argv[2])
target = b58dec(prefix)
shift = 8*(length+4)
for m in range(1,1000):
lo = target * 58**m
lo = (lo >> shift) + (0 if lo == ((lo >> shift) << shift) else 1)
hi = (target + 1) * 58**m - (1 << shift) +1
hi = hi >> shift
if hi >= lo:
# test
for bt in '\x00\xff':
s = bitcoin.bin_to_b58check(bt * length, magicbyte=lo)
assert s.startswith(prefix)
assert len(s) == m + len(prefix)
print m + len(prefix), lo, asciidec(lo)
exit(0)

1
vendors/tezos-modded/scripts/betanet.sh vendored Symbolic link
View File

@ -0,0 +1 @@
alphanet.sh

View File

@ -0,0 +1,36 @@
#! /bin/sh
set -e
script_dir="$(cd "$(dirname "$0")" && echo "$(pwd -P)/")"
src_dir="$(dirname "$script_dir")"
opams=$(find "$src_dir/vendors" "$src_dir/src" -name \*.opam -print)
yml="${1:-$src_dir/.gitlab-ci.yml}"
missing=
for opam in $opams; do
file=$(basename $opam)
package=${file%.opam}
if ! grep -qe "opam:..:$package:\$" "$yml"; then
missing=yes
echo "Missing test for package '$package'."
fi
done
tested=$(grep -e '^opam:..:tezos-.*:$' "$yml" | cut -d: -f3)
for package in $tested; do
found=$(find "$src_dir/src" "$src_dir/vendors" -name $package.opam | wc -l 2>&1)
if [ $found != 1 ] ; then
missing=yes
echo "Test for unknown package '$package'."
fi
done
if ! [ -z "$missing" ]; then
echo
echo "You should update .gitlab-ci.yml by running: ./scripts/update_opam_test.sh"
echo
exit 1
fi

22
vendors/tezos-modded/scripts/check_patch.sh vendored Executable file
View File

@ -0,0 +1,22 @@
#! /bin/sh
set -e
if [ $1 != "zeronet" ] && [ $1 != "alphanet" ] ; then
echo Ignored
exit 0
fi
if git log | grep "net: change economic constants" >/dev/null 2>&1 ; then
echo OK
exit 0
fi
cat <<EOF
The branch $1 should include the constant patch.
Please run './scripts/apply-patch.sh $1'.
EOF
exit 1

View File

@ -0,0 +1,47 @@
#! /bin/sh
set -e
ci_dir="$(cd "$(dirname "$0")" && echo "$(pwd -P)/")"
script_dir="$(dirname "$ci_dir")"
src_dir="$(dirname "$script_dir")"
cd "$src_dir"
. "$script_dir"/version.sh
tmp_dir=$(mktemp -dt tezos.opam.tezos.XXXXXXXX)
cleanup () {
set +e
echo Cleaning up...
rm -rf "$tmp_dir"
rm -rf Dockerfile
}
trap cleanup EXIT INT
image_name="${1:-tezos_build}"
image_version="${2:-latest}"
base_image="${3-${image_name}_deps:${image_version}}"
mkdir -p "$tmp_dir"/tezos/scripts
cp -a Makefile "$tmp_dir"/tezos
cp -a active_protocol_versions "$tmp_dir"/tezos
cp -a scripts/version.sh "$tmp_dir"/tezos/scripts/
cp -a src "$tmp_dir"/tezos
cp -a vendors "$tmp_dir"/tezos
cat <<EOF > "$tmp_dir"/Dockerfile
FROM $base_image
COPY --chown=tezos:nogroup tezos tezos
RUN opam exec -- make -C tezos all build-test
EOF
echo
echo "### Building tezos..."
echo
docker build -t "$image_name:$image_version" "$tmp_dir"
echo
echo "### Successfully build docker image: $image_name:$image_version"
echo

View File

@ -0,0 +1,65 @@
#! /bin/sh
set -e
ci_dir="$(cd "$(dirname "$0")" && echo "$(pwd -P)/")"
script_dir="$(dirname "$ci_dir")"
src_dir="$(dirname "$script_dir")"
cd "$src_dir"
. "$script_dir"/version.sh
tmp_dir=$(mktemp -dt tezos.opam.tezos.XXXXXXXX)
image_name="${1:-tezos}"
image_version="${2:-latest}"
build_image="${3:-registry.gitlab.com/tezos/opam-repository:${opam_repository_tag}}"
base_image="${4-registry.gitlab.com/tezos/opam-repository:minimal--${opam_repository_tag}}"
cleanup () {
set +e
echo Cleaning up...
rm -rf "$tmp_dir"
if ! [ -z "$container" ]; then docker rm $container; fi
}
trap cleanup EXIT INT
mkdir -p "$tmp_dir"/bin
mkdir -p "$tmp_dir"/scripts
container=$(docker create $build_image)
versioned_daemons="$(sed "s/^\(.*\)$/tezos-baker-\1 tezos-endorser-\1 tezos-accuser-\1/g" "active_protocol_versions")"
for bin in tezos-client tezos-admin-client tezos-node $versioned_daemons tezos-signer; do
docker cp -L $container:/home/tezos/tezos/$bin "$tmp_dir"/bin
done
cp -a "$script_dir"/docker/entrypoint.sh "$tmp_dir"/bin/
cp -a "$script_dir"/docker/entrypoint.inc.sh "$tmp_dir"/bin/
cp "$script_dir"/alphanet.sh "$tmp_dir"/scripts/
cp "$script_dir"/alphanet_version "$tmp_dir"/scripts/
cp "$src_dir"/src/bin_client/bash-completion.sh "$tmp_dir"/scripts/
cp "$src_dir"/active_protocol_versions "$tmp_dir"/scripts/
echo
echo "### Building minimal docker image..."
echo
cat > "$tmp_dir"/Dockerfile <<EOF
FROM $base_image
RUN sudo apk --no-cache add vim
ENV EDITOR=/usr/bin/vi
RUN sudo mkdir -p /var/run/tezos/node /var/run/tezos/client && \
sudo chown -R tezos /var/run/tezos
COPY bin/* /usr/local/bin/
COPY scripts/* /usr/local/share/tezos/
ENTRYPOINT ["/usr/local/bin/entrypoint.sh"]
EOF
docker build -t "$image_name:$image_version" "$tmp_dir"
echo
echo "### Successfully build docker image: $image_name:$image_version"
echo

View File

@ -0,0 +1,75 @@
#! /bin/sh
registry_uri="https://registry.gitlab.com/v2"
auth_uri="https://gitlab.com/jwt/auth"
scope=push,pull
getBearerToken() {
local headers
local username
local reponame
local basic_token
username="$1"
password="$2"
reponame="$3"
basic_token=$(echo -n "${username}:${password}" | base64)
headers="Authorization: Basic ${basic_token}"
curl -fs -H "${headers}" "${auth_uri}?service=container_registry&scope=repository:${reponame}:${scope}" | jq '.token' -r
}
getTagDigest() {
local token=$1
local reponame=$2
local tag=$3
local digest="$(curl -fs -H "Authorization: Bearer ${token}" \
-H "Accept: application/vnd.docker.distribution.manifest.v2+json" \
--head \
"${registry_uri}/${reponame}/manifests/${tag}" | \
grep Docker-Content-Digest | tr -d '\r')"
echo -n "${digest##Docker-Content-Digest: }"
}
deleteDigest() {
local token=$1
local reponame=$2
local digest=$3
curl -fs -H "Authorization: Bearer ${token}" \
-D - -o - -X DELETE "${registry_uri}/${reponame}/manifests/${digest}"
}
deleteTag() {
local token=$1
local reponame=$2
local tag=$3
local digest="$(getTagDigest "${token}" "${reponame}" "${tag}")"
if [ -z "$digest" ]; then
echo "Failed to locate the ${reponame}:${tag}"
exit 1
fi
deleteDigest "${token}" "${reponame}" "${digest}"
}
readTag() {
local token=$1
local reponame=$2
local tag=$3
curl -fs -H "Authorization: Bearer ${token}" \
-H "Accept: application/vnd.docker.distribution.manifest.v2+json" \
--head "$registry_uri/$reponame/manifests/$tag" | \
grep Docker-Content-Digest
}
renameTag() {
local token=$1
local reponame=$2
local old_tag=$3
local new_tag=$4
curl -fs -H "Authorization: Bearer ${token}" \
-H "Accept: application/vnd.docker.distribution.manifest.v2+json" \
-o MANIFEST "$registry_uri/$reponame/manifests/$old_tag"
curl -fs -H "Authorization: Bearer ${token}" \
-H "Content-type: application/vnd.docker.distribution.manifest.v2+json" \
-X PUT -d @MANIFEST "$registry_uri/$reponame/manifests/$new_tag"
rm MANIFEST
}

View File

@ -0,0 +1,41 @@
#! /bin/sh
set -e
set -x
ci_dir="$(cd "$(dirname "$0")" && echo "$(pwd -P)/")"
script_dir="$(dirname "$ci_dir")"
src_dir="$(dirname "$script_dir")"
cd "$src_dir"
. "$ci_dir"/docker_registry.inc.sh
username="$1"
password="$2"
reponame="${3##registry.gitlab.com/}"
shift 3
tags="${@:-latest}"
for tag in $tags; do
scope='push,pull'
token="$(getBearerToken "${username}" "${password}" "${reponame}")"
if [ -z "$token" ]; then
echo "Failed to fetch the Bearer token"
exit 1
fi
digest="$(getTagDigest "${token}" "${reponame}" "${tag}")"
if [ -z "$digest" ]; then
echo "Failed to locate the ${reponame}:${tag}"
exit 1
fi
scope='*'
token="$(getBearerToken "${username}" "${password}" "${reponame}")"
if [ -z "$token" ]; then
echo "Failed to fetch the Bearer token"
exit 1
fi
deleteDigest "${token}" "${reponame}" "${digest}"
done

View File

@ -0,0 +1,25 @@
#! /bin/sh
set -e
ci_dir="$(cd "$(dirname "$0")" && echo "$(pwd -P)/")"
script_dir="$(dirname "$ci_dir")"
src_dir="$(dirname "$script_dir")"
cd "$src_dir"
. "$ci_dir"/docker_registry.inc.sh
username="$1"
password="$2"
image="${3##registry.gitlab.com/}"
reponame=${image%%:*}
tag=${image##*:}
token="$(getBearerToken "${username}" "${password}" "${reponame}")"
if [ -z "$token" ]; then
echo "Failed to fetch the Bearer token"
exit 1
fi
readTag "$token" "$reponame" "$tag"

View File

@ -0,0 +1,24 @@
#! /bin/sh
set -e
ci_dir="$(cd "$(dirname "$0")" && echo "$(pwd -P)/")"
script_dir="$(dirname "$ci_dir")"
src_dir="$(dirname "$script_dir")"
cd "$src_dir"
. "$ci_dir"/docker_registry.inc.sh
username="$1"
password="$2"
reponame="${3##registry.gitlab.com/}"
old_tag="$4"
new_tag="$5"
token="$(getBearerToken "${username}" "${password}" "${reponame}")"
if [ -z "$token" ]; then
echo "Failed to fetch the Bearer token"
exit 1
fi
renameTag "$token" "$reponame" "$old_tag" "$new_tag"

View File

@ -0,0 +1,25 @@
#! /bin/sh
set -e
script_dir="$(cd "$(dirname "$0")" && echo "$(pwd -P)/")"
src_dir="$(dirname "$script_dir")"
cd "$src_dir"
. "$script_dir"/version.sh
image_name="${1:-tezos}"
image_version="${2:-latest}"
build_deps_image_name=${3:-registry.gitlab.com/tezos/opam-repository}
build_deps_image_version=${4:-$opam_repository_tag}
build_image_name="${image_name}_build"
"$script_dir"/ci/create_docker_image.build.sh \
"$build_image_name" "$image_version" \
"$build_deps_image_name:$build_deps_image_version"
"$script_dir"/ci/create_docker_image.minimal.sh \
"$image_name" "$image_version" \
"$build_image_name:$image_version" \
"$build_deps_image_name:minimal--$build_deps_image_version"

View File

@ -0,0 +1,134 @@
#! /usr/bin/env python
import sys
import os
import json
import bitcoin
import binascii
import numpy as np
import pysodium
from pyblake2 import blake2b
import unicodedata
import pysodium
from hashlib import sha256
import random
import string
def get_keys(mnemonic, email, password):
salt = unicodedata.normalize(
"NFKD", (email + password).decode("utf8")).encode("utf8")
seed = bitcoin.mnemonic_to_seed(mnemonic, salt)
pk, sk = pysodium.crypto_sign_seed_keypair(seed[0:32])
pkh = blake2b(pk,20).digest()
pkhb58 = bitcoin.bin_to_b58check(pkh, magicbyte=434591)
return (sk, pk, pkh, pkhb58)
def random_email():
rnd = lambda n: ''.join(random.choice(string.ascii_lowercase) for _ in range(n))
return '%s.%s@tezos.example.org' % (rnd(8),rnd(8))
def tez_to_int(amount):
return int(round(amount * 1e6, 0))
def allocate_with_subthreshold( w ):
from_ether = sum(x[u'tezzies'] for x in w[u'ethDeposits'])
def discount_level( level ):
if level >= 2000:
return 0
return 6000 - (level/400)*250
from_bitcoin = sum(x[u'satoshis'] * discount_level(x[u'crowdfund_level']) for x in w[u'utxos'])
return from_ether + from_bitcoin * 1e-8
def get_wallets(path):
wallets = {}
for fn in os.listdir(path):
# ignore misc files
if not fn.startswith("tz1"):
continue
w = json.load(open(os.path.join(path, fn), "r"))
# if not u'allocated_tezzies' in w.keys():
# continue
wallets[fn.split(".")[0]] = allocate_with_subthreshold(w)
return wallets
def secret_code(pkh, blind):
return blake2b(pkh, 20, key=blind).digest()
def genesis_commitments(wallets, blind):
commitments = []
for pkh_b58, amount in wallets.iteritems():
# Public key hash corresponding to this Tezos address.
pkh = bitcoin.b58check_to_bin(pkh_b58)[2:]
# The redemption code is unique to the public key hash and deterministically
# constructed using a secret blinding value.
secret = secret_code(pkh, blind)
# The redemption code is used to blind the pkh
blinded_pkh = blake2b(pkh, 20, key=secret).digest()
commitment = {
'blinded_pkh': bitcoin.bin_to_b58check(blinded_pkh, magicbyte=16921055),
'amount': amount
}
commitments.append(commitment)
return commitments
# Generate dummy genesis information for a centralized alphanet faucet
def make_dummy_wallets(n, blind):
# Not a realistic shape, but for an alphanet faucet it's better to
# have less variance.
amounts = np.random.pareto(10.0, n)
amounts = amounts / sum(amounts) * 700e6
wallets = {}
secrets = {}
for i in range(0, n):
entropy = blake2b(str(i), 20, key=blind).digest()
mnemonic = bitcoin.mnemonic.entropy_to_words(entropy)
password = ''.join(random.choice(string.letters + string.digits) for _ in range(10))
email = random_email()
sk, pk, pkh, pkh_b58 = get_keys(' '.join(mnemonic), email, password)
amount = tez_to_int(amounts[i])
wallets[pkh_b58] = amount
secret = secret_code(pkh, blind)
secrets[pkh_b58] = (mnemonic, email, password, amount, binascii.hexlify(secret))
return wallets, secrets
if __name__ == '__main__':
if len(sys.argv) < 3:
print "Usage: python create_genesis_info.py /path/to/json blind [dummy]"
exit(1)
blind = sys.argv[2]
if len(sys.argv) == 4 and sys.argv[3] == "dummy":
wallets, secrets = make_dummy_wallets(30000, blind)
with open('secret_seeds.json', 'w') as f:
json.dump([ { "pkh" : pkh,
"mnemonic" : mnemonic,
"email" : email,
"password" : password,
"amount" : str(amount),
"activation_code" : secret }
for pkh, (mnemonic, email, password, amount, secret) in secrets.iteritems()], f, indent=1)
else:
wallets = get_wallets( sys.argv[1] )
commitments = genesis_commitments(wallets, blind)
with open('commitments.json', 'w') as f:
json.dump({
"bootstrap_accounts": [
[ "edsk4X12XaKRPHgDkgvMe4UWEiygx8AVrt9rpktmhu1uT2GCPU4dp7",
"12000000000000" ],
[ "edsk46ypB8PztxMDPMdVnEgjQmJhca7zMJvTMDrdwJaJ4mgm4qNmwE",
"12000000000000" ],
[ "edsk4JsBpWJH5cDtanNADY2D5Ygma1dUtxko8qaM2Af8FHGU52yLcW",
"12000000000000" ],
[ "edsk3b5GrQdRF1Pt3ccRjvyoNHTFrSXUKZufg2zQYhBumqS8kMfeGC",
"12000000000000" ],
[ "edsk3T8CRr8YK2vnjsZK2vDzCjpcWpMEUXMAzjeR1GWjmyhGaDHTNV",
"12000000000000" ]
],
"commitments": [
(commitment['blinded_pkh'], str(commitment['amount']))
for commitment in commitments if commitment['amount'] > 0
],
"no_rewards_cycles": 7,
"security_deposit_ramp_up_cycles": 64
}, f, indent=1)

View File

@ -0,0 +1,3 @@
-e git+https://github.com/vbuterin/pybitcointools.git@aeb0a2bbb8bbfe421432d776c649650eaeb882a5#egg=master
pyblake2==0.9.3
pysodium==0.6.11

View File

@ -0,0 +1,57 @@
version: "2"
services:
node:
image: tezos/tezos:latest
hostname: node
command: tezos-node
ports:
- 9732:9732
expose:
- '8732'
volumes:
- node_data:/var/run/tezos/node
- client_data:/var/run/tezos/client
restart: on-failure
## Duplicate the `baker/endorser/accuser` containers for each PROTOCOL
## in file `active_protocol_versions`
baker-alpha:
image: tezos/tezos:latest
hostname: baker-alpha
environment:
- PROTOCOL=alpha
command: tezos-baker
links:
- node
volumes:
- client_data:/var/run/tezos/client
restart: on-failure
endorser-alpha:
image: tezos/tezos:latest
hostname: endorser-alpha
environment:
- PROTOCOL=alpha
command: tezos-endorser
links:
- node
volumes:
- client_data:/var/run/tezos/client
restart: on-failure
accuser-alpha:
image: tezos/tezos:latest
hostname: accuser-alpha
environment:
- PROTOCOL=alpha
command: tezos-accuser
links:
- node
volumes:
- client_data:/var/run/tezos/client
restart: on-failure
volumes:
node_data:
client_data:

View File

@ -0,0 +1,134 @@
#!/bin/sh
configure_client() {
local client_config="$HOME/.tezos-client/config"
mkdir -p "$client_dir" "$HOME/.tezos-client"
if [ ! -f "$client_config" ]; then
"$client" --base-dir "$client_dir" \
--addr "$NODE_HOST" --port "$NODE_RPC_PORT" \
config init --output "$client_config" >/dev/null 2>&1
else
"$client" --base-dir "$client_dir" \
--addr "$NODE_HOST" --port "$NODE_RPC_PORT" \
config update >/dev/null 2>&1
fi
}
wait_for_the_node_to_be_ready() {
local count=0
if "$client" rpc get /chains/main/blocks/head/hash >/dev/null 2>&1; then return; fi
printf "Waiting for the node to initialize..."
sleep 1
while ! "$client" rpc get /chains/main/blocks/head/hash >/dev/null 2>&1
do
count=$((count+1))
if [ "$count" -ge 30 ]; then
echo " timeout."
exit 2
fi
printf "."
sleep 1
done
echo " done."
}
wait_for_the_node_to_be_bootstraped() {
wait_for_the_node_to_be_ready
echo "Waiting for the node to synchronize with the network..."
"$client" bootstrapped
}
launch_node() {
mkdir -p "$node_dir"
# Check if we have to reset the chain because the image we want to
# run has a incompatible version with the blockchain we have stored
# locally on disk
local image_version="$(cat "/usr/local/share/tezos/alphanet_version")"
echo "Current public chain: $image_version."
local local_data_version=""
if [ -f "$node_dir/alphanet_version" ]; then
local_data_version="$(cat "$node_dir/alphanet_version")"
echo "Local chain data: $local_data_version."
fi
if [ "$local_data_version" != "$image_version" ]; then
echo "Removing outdated chain data..."
if [ -f "$node_data_dir/identity.json" ]; then \
mv "$node_data_dir/identity.json" /tmp
fi
rm -rf "$node_data_dir"
rm -rf "$client_dir/blocks"
rm -rf "$client_dir/nonces"
rm -rf "$client_dir/endorsements"
if [ -f "/tmp/identity.json" ]; then \
mkdir -p "$node_data_dir"
mv /tmp/identity.json "$node_data_dir/"
fi
cp "/usr/local/share/tezos/alphanet_version" \
"$node_dir/alphanet_version"
fi
mkdir -p "$node_data_dir"
if [ ! -f "$node_data_dir/config.json" ]; then
echo "Configuring the node..."
"$node" config init \
--data-dir "$node_data_dir" \
--rpc-addr ":$NODE_RPC_PORT" \
"$@"
else
echo "Updating the node configuration..."
"$node" config update \
--data-dir "$node_data_dir" \
--rpc-addr ":$NODE_RPC_PORT" \
"$@"
fi
for i in "$@"; do
if [ "$i" = "--help" ] ; then exit 0; fi
done
# Generate a new identity if not present
if [ ! -f "$node_data_dir/identity.json" ]; then
echo "Generating a new node identity..."
"$node" identity generate "${IDENTITY_POW:-26}". \
--data-dir "$node_data_dir"
fi
configure_client
# Launching the node
exec "$node" run --data-dir "$node_data_dir"
}
launch_baker() {
configure_client
wait_for_the_node_to_be_bootstraped
exec "$baker" --base-dir "$client_dir" \
--addr "$NODE_HOST" --port "$NODE_RPC_PORT" \
run with local node "$node_data_dir" "$@"
}
launch_endorser() {
configure_client
wait_for_the_node_to_be_bootstraped
exec "$endorser" --base-dir "$client_dir" \
--addr "$NODE_HOST" --port "$NODE_RPC_PORT" \
run "$@"
}
launch_accuser() {
configure_client
wait_for_the_node_to_be_bootstraped
exec "$accuser" --base-dir "$client_dir" \
--addr "$NODE_HOST" --port "$NODE_RPC_PORT" \
run "$@"
}

View File

@ -0,0 +1,66 @@
#!/bin/sh
set -e
bin_dir="$(cd "$(dirname "$0")" && echo "$(pwd -P)/")"
: ${BIN_DIR:="/usr/local/bin"}
: ${DATA_DIR:="/var/run/tezos"}
: ${NODE_HOST:="node"}
: ${NODE_RPC_PORT:="8732"}
: ${PROTOCOL:="unspecified-PROTOCOL-variable"}
node="$BIN_DIR/tezos-node"
client="$BIN_DIR/tezos-client"
admin_client="$BIN_DIR/tezos-admin-client"
baker="$BIN_DIR/tezos-baker-$PROTOCOL"
endorser="$BIN_DIR/tezos-endorser-$PROTOCOL"
accuser="$BIN_DIR/tezos-accuser-$PROTOCOL"
signer="$BIN_DIR/tezos-signer"
client_dir="$DATA_DIR/client"
node_dir="$DATA_DIR/node"
node_data_dir="$node_dir/data"
. "$bin_dir/entrypoint.inc.sh"
command=${1:-tezos-node}
shift 1
case $command in
tezos-node)
launch_node "$@"
;;
tezos-baker)
launch_baker "$@"
;;
tezos-endorser)
launch_endorser "$@"
;;
tezos-accuser)
launch_accuser "$@"
;;
tezos-client)
configure_client
exec "$client" "$@"
;;
tezos-admin-client)
configure_client
exec "$admin_client" "$@"
;;
tezos-signer)
exec "$signer" "$@"
;;
*)
cat <<EOF
Available commands:
- tezos-node [args]
- tezos-client [args]
- tezos-baker [keys]
- tezos-endorser [keys]
- tezos-signer [args]
EOF
;;
esac

View File

@ -0,0 +1,66 @@
#use "topfind";;
#thread;;
#require "threads";;
#require "stringext";;
#require "lwt";;
#require "lwt.unix";;
#require "zarith";;
#require "re";;
#require "hacl";;
#require "calendar";;
#mod_use "../src/lib_stdlib/tzString.ml";;
#mod_use "../src/lib_stdlib/option.ml";;
#mod_use "../src/lib_stdlib/tzList.ml";;
#mod_use "../src/lib_stdlib/utils.ml";;
#mod_use "../src/lib_crypto/base58.ml";;
open Lwt.Infix;;
let prefix = "BLockGenesisGenesisGenesisGenesisGenesis"
let rec genesis () =
let date =
Lwt_main.run
(Lwt_process.pread_line (Lwt_process.shell "TZ='AAA+1' date +%FT%TZ")) in
let suffix = String.sub Digest.(to_hex (string date)) 0 5 in
match Base58.raw_decode (prefix ^ suffix ^ "crcCRC") with
| None -> genesis ()
| Some p ->
let p = String.sub p 0 (String.length p - 4) in
Base58.safe_encode p, date
let genesis, date = genesis ()
let () =
Lwt_main.run @@
let stream = Lwt_io.lines_of_file "alphanet_version" in
Lwt_stream.to_list stream >>= function
| [] | _ :: _ :: _ -> failwith "bad alphanet_version file"
| [ line ] -> match String.split_on_char 'Z' line with
| [ _ ; branch ] ->
let contents = if String.trim branch = "" then date else date ^ branch in
Lwt_io.lines_to_file "alphanet_version" (Lwt_stream.of_list [ contents ])
| _ -> failwith "bad alphanet_version file"
let sed =
Format.sprintf
"sed -i.old \
-e 's/Time.of_notation_exn \"[^\\\"]*\"/Time.of_notation_exn \"%s\"/' \
-e 's/BLockGenesisGenesisGenesisGenesisGenesis.........../%s/' \
../src/bin_node/node_run_command.ml"
date
genesis
let () =
Lwt_main.run (Lwt_process.exec (Lwt_process.shell sed) >>= fun _ ->
Lwt_unix.unlink "../src/bin_node/node_run_command.ml.old")
let sed =
Format.sprintf
"sed -E -i.old \
-e 's/name = \"(TEZOS[_A-Z]+)[^\"]*\" ;/name = \"\\1%s\" ;/' \
../src/lib_shell/distributed_db_message.ml"
date
let () =
Lwt_main.run (Lwt_process.exec (Lwt_process.shell sed) >>= fun _ ->
Lwt_unix.unlink "../src/lib_shell/distributed_db_message.ml.old")

View File

@ -0,0 +1,16 @@
#! /bin/sh
script_dir="$(cd "$(dirname "$0")" && echo "$(pwd -P)/")"
src_dir="$(dirname "$script_dir")"
. "$script_dir"/version.sh
opams=$(find "$src_dir/vendors" "$src_dir/src" -name \*.opam -print)
export OPAMYES=${OPAMYES:=true}
## In an ideal world, `--with-test` should be present only when using
## `--dev`. But this would probably break the CI, so we postponed this
## change until someone have some spare time. (@pirbo, @hnrgrgr)
opam install $opams --deps-only --with-test --criteria="-notuptodate,-changed,-removed"

View File

@ -0,0 +1,45 @@
#! /bin/sh
script_dir="$(cd "$(dirname "$0")" && echo "$(pwd -P)/")"
src_dir="$(dirname "$script_dir")"
. "$script_dir"/version.sh
if [ "$1" = "--dev" ]; then
dev=yes
else
dev=
fi
opam repository set-url tezos --dont-select $opam_repository || \
opam repository add tezos --dont-select $opam_repository > /dev/null 2>&1
opam update --repositories --development
if [ ! -d "$src_dir/_opam" ] ; then
opam switch create "$src_dir" --repositories=tezos ocaml-base-compiler.$ocaml_version
fi
if [ ! -d "$src_dir/_opam" ] ; then
echo "Failed to create the opam switch"
exit 1
fi
eval $(opam env --shell=sh)
if [ -n "$dev" ]; then
opam repository remove default > /dev/null 2>&1 || true
fi
if [ "$(ocaml -vnum)" != "$ocaml_version" ]; then
opam install --unlock-base ocaml-base-compiler.$ocaml_version
fi
opam list --installed opam-depext || opam --yes install opam-depext
"$script_dir"/install_build_deps.raw.sh
if [ -n "$dev" ]; then
opam repository add default --rank=-1 > /dev/null 2>&1 || true
opam install merlin
fi

1
vendors/tezos-modded/scripts/localnet.sh vendored Symbolic link
View File

@ -0,0 +1 @@
alphanet.sh

1
vendors/tezos-modded/scripts/mainnet.sh vendored Symbolic link
View File

@ -0,0 +1 @@
alphanet.sh

31
vendors/tezos-modded/scripts/nginx.conf vendored Normal file
View File

@ -0,0 +1,31 @@
# /etc/nginx/nginx.conf
user nginx;
worker_processes 1;
error_log off;
events {
worker_connections 1024;
}
http {
server_tokens off;
client_max_body_size 0;
keepalive_timeout 65;
tcp_nodelay on;
access_log off;
server {
listen 80 default_server;
listen [::]:80 default_server;
location / {
proxy_pass http://127.0.0.1:8732/;
}
location ~ ^/(validate_block|network/connection/.*/kick|network/connect/|(forge|inject)_(block|operation|protocol)/) {
return 404;
}
location = /404.html {
internal;
}
}
}

85
vendors/tezos-modded/scripts/ocamldot.py vendored Executable file
View File

@ -0,0 +1,85 @@
#!/usr/bin/python
import re
import sys
import os
import argparse
from sets import Set
alldeps={}
allmodules={}
def sanitize(s):
s=re.sub('.*/','',s)
s=re.sub('[^0-9a-zA-Z]+', '_', s)
return s
def cleanName(s):
ml = os.path.basename(s)
(mod,_) = os.path.splitext(ml)
return mod.capitalize()
def mangle(f,modulename):
dictionary = {}
for line in open(f):
s=line.split();
for x in range(2, len(s)):
mod = cleanName(s[0])
dep = sanitize(s[x])
if mod in dictionary :
dictionary[mod].append(dep)
else :
dictionary[mod] = [dep]
allmodules.update({mod : modulename})
alldeps[modulename] = dictionary
def cleanup(alldeps):
# remove references to external libraries
for (name,dictionary) in alldeps.iteritems() :
for (mod,deps) in dictionary.iteritems() :
dictionary[mod] = [x for x in deps if x in allmodules]
alldeps[name] = dictionary
return alldeps
def print_graph(alldeps):
print("strict digraph G {")
print('graph [fontsize=10 fontname="Verdana"];')
print('node [shape=record fontsize=10 fontname="Verdana" compound=true];')
counter = 0
l = { x: i for i,x in enumerate(alldeps.keys())}
for (name,dictionary) in alldeps.iteritems() :
names = ['"%s"' % mod for mod in dictionary.keys()]
if len(names) > 0 :
print ('subgraph cluster_%i { label = "%s"; color=blue; node [style=filled];' % (l[name],name))
counter += 1
for (mod,deps) in dictionary.iteritems() :
for dep in deps :
if dep in dictionary :
print ('"%s" -> "%s";' % (mod,dep))
print "}"
# for (mod,deps) in dictionary.iteritems() :
# for dep in deps :
# if dep not in dictionary :
# print ('"%s" -> "%s" [ltail=cluster_%i lhead=cluster_%i];' % (mod,dep,l[name],l[allmodules[dep]]))
print "}"
def scan(directories):
ext = ".depends.ocamldep-output"
for directory in directories:
for root, dirs, files in os.walk(directory):
for f in files:
if f.endswith(ext):
mangle(os.path.join(root, f),f[:-len(ext)])
print_graph(cleanup(alldeps))
def main():
parser = argparse.ArgumentParser(description='OcamlDep Dependency Tree')
parser.add_argument('inputdirs', type=str, nargs='*', help="directories to scan")
args = parser.parse_args()
scan(args.inputdirs)
if __name__ == '__main__':
main()

39
vendors/tezos-modded/scripts/opam-check.sh vendored Executable file
View File

@ -0,0 +1,39 @@
#! /bin/sh
script_dir="$(cd "$(dirname "$0")" && echo "$(pwd -P)/")"
src_dir="$(dirname "$script_dir")"
. "$script_dir"/version.sh
opams=$(find "$src_dir/vendors" "$src_dir/src" -name \*.opam -print)
echo "## Checking installed dependencies..."
echo
if ! opam install $opams --deps-only --with-test --show-actions | grep "Nothing to do." > /dev/null 2>&1 ; then
echo
echo 'Failure! Missing actions:'
echo
opam install $opams --deps-only --with-test --show-actions
echo
echo 'Failed! Please read the doc in `./scripts/update_opam_repo.sh` and act accordingly.'
echo
exit 1
fi
echo '## Running `./scripts/update_opam_repo.sh`'
echo
./scripts/update_opam_repo.sh
if [ -n "$(cat opam_repo.patch)" ] ; then
echo "##################################################"
cat opam_repo.patch
echo "##################################################"
echo 'Failed! The variables `opam_repository_tag` and `full_opam_repository_tag` are not synchronized. Please read the doc in `./scripts/update_opam_repo.sh` and act accordingly.'
echo
exit 1
fi
echo "Ok."

30
vendors/tezos-modded/scripts/opam-pin.sh vendored Executable file
View File

@ -0,0 +1,30 @@
#! /bin/sh
set -e
script_dir="$(cd "$(dirname "$0")" && echo "$(pwd -P)/")"
src_dir="$(dirname "$script_dir")"
export OPAMYES=yes
echo
echo "## Pinning tezos packages..."
opams=$(find "$src_dir/vendors" "$src_dir/src" -name \*.opam -print)
packages=
for opam in $opams; do
dir=$(dirname $opam)
file=$(basename $opam)
package=${file%.opam}
packages="$packages $package"
opam pin add --no-action $package $dir > /dev/null 2>&1
done
packages=$(opam list --short --sort --pinned $packages)
echo
echo "## Pinned packages:"
echo
echo "$packages" | sed 's/^/ /'
echo

20
vendors/tezos-modded/scripts/opam-remove.sh vendored Executable file
View File

@ -0,0 +1,20 @@
#! /bin/sh
set -e
script_dir="$(cd "$(dirname "$0")" && echo "$(pwd -P)/")"
src_dir="$(dirname "$script_dir")"
opams=$(find "$src_dir" -name \*.opam)
packages=
for opam in $opams; do
dir=$(dirname $opam)
file=$(basename $opam)
package=${file%.opam}
packages="$packages $package"
done
installed=$(opam list --short --installed --pinned $packages)
opam remove $installed

74
vendors/tezos-modded/scripts/opam-test-all.sh vendored Executable file
View File

@ -0,0 +1,74 @@
#! /bin/sh
set -e
script_dir="$(cd "$(dirname "$0")" && echo "$(pwd -P)/")"
src_dir="$(dirname "$script_dir")"
cd "$src_dir"
cleanup () {
set +e
if [ -f LOG ]; then
echo "failed."
echo
cat LOG
rm LOG
echo
exit 1
fi
}
trap cleanup EXIT INT
silent () {
"$@" > LOG 2>&1
rm LOG
}
requested_packages="$@"
export OPAMYES=yes
echo -n "Cleanup state and pin packages..."
silent ./scripts/opam-unpin.sh
silent . ./scripts/opam-pin.sh
echo " OK."
if ! [ -z "$requested_packages" ]; then
packages="$requested_packages"
fi
okfile="$0.DONE"
touch $okfile
ok=$(cat "$okfile")
ignore() {
for i in $ok; do
if [ $i = $1 ]; then return 0; fi
done
return 1
}
for package in $packages; do
if ignore $package; then
echo "Ignoring: $package."
continue
fi
echo -n "Installing: $package..."
silent opam install $package
echo " OK."
echo -n "Removing: $package..."
silent opam remove -a $package
echo " OK."
echo $package >> "$okfile"
done
echo
echo "Successfully installed the following packages: "
echo
cat $okfile | sed 's/^/- /'
rm $okfile

13
vendors/tezos-modded/scripts/opam-unpin.sh vendored Executable file
View File

@ -0,0 +1,13 @@
#! /bin/sh
set -e
script_dir="$(cd "$(dirname "$0")" && echo "$(pwd -P)/")"
src_dir="$(dirname "$script_dir")"
. "$script_dir"/opam-remove.sh
echo
echo "## Unpinning tezos packages..."
opam pin remove $packages > /dev/null 2>&1

35
vendors/tezos-modded/scripts/opam-upgrade.sh vendored Executable file
View File

@ -0,0 +1,35 @@
#! /bin/sh
set -e
script_dir="$(cd "$(dirname "$0")" && echo "$(pwd -P)/")"
src_dir="$(dirname "$script_dir")"
cd "$src_dir"
cleanup () {
set +e
if [ -f LOG ]; then
echo "Failure"
echo
cat LOG
echo
exit 1
fi
}
trap cleanup EXIT INT
silent () {
"$@" > LOG 2>&1
rm LOG
}
echo "Updating package description..."
silent . ./scripts/opam-pin.sh
upgradables=$(opam list --short --installed --pinned $packages)
if [ -z "$upgradables" ]; then
echo "No previously installed package. Nothing to do."
exit 1
fi
opam upgrade $upgradables

View File

@ -0,0 +1,48 @@
{ "bootstrap_accounts": [
[ "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav", "4000000000000" ],
[ "edpktzNbDAUjUk697W7gYg2CRuBQjyPxbEg8dLccYYwKSKvkPvjtV9", "4000000000000" ],
[ "edpkuTXkJDGcFd5nh6VvMz8phXxU3Bi7h6hqgywNFi1vZTfQNnS1RV", "4000000000000" ],
[ "edpkuFrRoDSEbJYgxRtLx2ps82UdaYc1WwfS9sE11yhauZt5DgCHbU", "4000000000000" ],
[ "edpkv8EUUH68jmo3f7Um5PezmfGrRF24gnfLpH3sVNwJnV5bVCxL2n", "4000000000000" ],
[ "tz1PooUKBaoxjBiCR2dxEtbtTUjLX3iaZQoJ", "100" ],
[ "edpkuSLWfVU1Vq7Jg9FucPyKmma6otcMHac9zG4oU1KMHSTBpJuGQ2", "1" ] ],
"bootstrap_contracts": [
{ "delegate": "tz1TGu6TN5GSez2ndXXeDX6LgUDvLzPLqgYV",
"amount": "10000000",
"script":
{ "code":
[ { "prim": "parameter",
"args": [ { "prim": "key_hash" } ] },
{ "prim": "storage",
"args": [ { "prim": "timestamp" } ] },
{ "prim": "code",
"args":
[ [ [ [ { "prim": "DUP" }, { "prim": "CAR" },
{ "prim": "DIP", "args": [ [ { "prim": "CDR" } ] ] } ] ],
{ "prim": "SWAP" },
{ "prim": "PUSH", "args": [ { "prim": "int" }, { "int": "300" } ] },
{ "prim": "ADD", "annots": [ "@FIVE_MINUTES_LATER" ] },
{ "prim": "NOW" },
[ [ { "prim": "COMPARE" }, { "prim": "GE" } ],
{ "prim": "IF",
"args":
[ [],
[ [ { "prim": "UNIT" },
{ "prim": "FAILWITH" } ] ] ] } ],
{ "prim": "IMPLICIT_ACCOUNT" },
{ "prim": "PUSH", "args": [ { "prim": "mutez" }, { "int": "1000000" } ] },
{ "prim": "UNIT" },
{ "prim": "TRANSFER_TOKENS" },
{ "prim": "NIL", "args": [ { "prim": "operation" } ] },
{ "prim": "SWAP" },
{ "prim": "CONS" },
{ "prim": "DIP", "args": [ [ { "prim": "NOW" } ] ] },
{ "prim": "PAIR" } ] ] } ],
"storage": { "int": "0" } } } ],
"time_between_blocks" : [ "1", "0" ],
"blocks_per_roll_snapshot" : 4,
"blocks_per_cycle" : 8,
"blocks_per_voting_period" : 64,
"preserved_cycles" : 2,
"proof_of_work_threshold": "-1"
}

23
vendors/tezos-modded/scripts/reset_chain.sh vendored Executable file
View File

@ -0,0 +1,23 @@
#! /bin/sh
script_dir="$(cd "$(dirname "$0")" && echo "$(pwd -P)/")"
cd "$script_dir"/..
branch=$1
has_git() {
which git && [ -d .git ]
}
if has_git && ! [ -z "$(git status -s)" ] ; then
echo "This script cannot be applied within a dirty git directory,"
echo "you need 'stash' or 'commit' your changes before."
exit 1
fi
set -e
cd scripts
ocaml gen_genesis.ml
git commit -a -m "Reset the chain"

View File

@ -0,0 +1,4 @@
{
"genesis_pubkey":
"edpkuSLWfVU1Vq7Jg9FucPyKmma6otcMHac9zG4oU1KMHSTBpJuGQ2"
}

124
vendors/tezos-modded/scripts/snapshot_alpha.sh vendored Executable file
View File

@ -0,0 +1,124 @@
#! /bin/bash
set -e
usage="Usage:
$ ./scripts/snapshot_alpha.sh babylon_005 from athens_004
Packs the current proto_alpha directory in a new proto_005_<hash>
directory with all the necessary renamings.
With option --master prepares the protocol for master."
script_dir="$(cd "$(dirname "$0")" && echo "$(pwd -P)/")"
cd "$script_dir"/..
current=$1
label=$(echo $current | cut -d'_' -f1)
version=$(echo $current | cut -d'_' -f2)
if ! ( [[ "$label" =~ ^[a-z]+$ ]] && [[ "$version" =~ ^[0-9][0-9][0-9]$ ]] ); then
echo "Wrong protocol version"
echo
echo "$usage"
exit 1
fi
predecessor=$3
previous_label=$(echo $predecessor | cut -d'_' -f1)
previous_version=$(echo $predecessor | cut -d'_' -f2)
if ! ( [[ "$2" == "from" ]] && [[ "$3" ]] && [[ "$previous_label" =~ ^[a-z]+$ ]] && [[ "$previous_version" =~ ^[0-9][0-9][0-9]$ ]] ); then
if [[ "$2" == "--master" ]]; then master="true"
else
echo 'pass a predecessor such as "from athens_004" or "--master"'
echo
echo "$usage"
exit 1
fi
fi
if [ -d src/proto_${version} ] ; then
echo "Error: you should remove the directory 'src/proto_${version}'"
exit 1
fi
#create a temporary directory until the hash is known
cp -r src/proto_alpha/ src/proto_${version}
# set current version
sed -i --follow-symlink \
-e 's/let version_value = "alpha_current"/let version_value = "'${current}'"/' \
src/proto_${version}/lib_protocol/src/raw_context.ml
# set previous version
if [[ "$master" ]]; then
#in master our predecessor is alpha_current
sed -i --follow-symlink \
-e 's/s = "alpha_previous"/s = "alpha_current"/' \
src/proto_${version}/lib_protocol/src/raw_context.ml
else
# set previous version
sed -i --follow-symlink \
-e 's/Alpha_previous/'${predecessor^}'/' \
src/proto_${version}/lib_protocol/src/{raw_context.ml,raw_context.mli,init_storage.ml}
# set previous version
sed -i --follow-symlink \
-e 's/s = "alpha_previous"/s = "'${predecessor}'"/' \
src/proto_${version}/lib_protocol/src/raw_context.ml
fi
long_hash=$(./tezos-protocol-compiler -hash-only src/proto_${version}/lib_protocol/src)
short_hash=$(echo $long_hash | head -c 8)
if [ -d src/proto_${version}_${short_hash} ] ; then
echo "Error: you should remove the directory 'src/proto_${version}_${short_hash}'"
exit 1
fi
mv src/proto_${version} src/proto_${version}_${short_hash}
cd src/proto_${version}_${short_hash}
# the following files do not influence the hash
# replace fake hash with real hash
sed -i --follow-symlink \
-e 's/"hash": "[^"]*",/"hash": "'$long_hash'",/' \
lib_protocol/src/TEZOS_PROTOCOL
sed -i --follow-symlink \
-e 's/"alpha"/"'${version}-${short_hash}'"/' \
lib_client/proto_alpha.ml
sed -i --follow-symlink \
-e s/protocol_alpha/protocol_${version}_${short_hash}/ \
$(find -name \*.ml -or -name \*.mli)
# rename main_*.ml{,i} files of the binaries
rename s/_alpha/_${version}_${short_hash}/ $(find -name main_\*.ml -or -name main_\*.mli)
# change version in opam files
sed -i --follow-symlink \
-e 's/Some \\"alpha\\"/Some \\"'${version}_${short_hash}'\\"/' \
lib_protocol/tezos{,-embedded}-protocol-alpha.opam
# rename .opam files
rename s/alpha/${version}-${short_hash}/ $(find -name \*.opam)
# fix content of dune and opam files
sed -i --follow-symlink \
-e s/_alpha/_${version}_${short_hash}/g \
-e s/-alpha/-${version}-${short_hash}/g \
$(find . -name dune -or -name \*.opam)
# rename genesis except if in master
if [[ ! "$master" ]]; then
#rename genesis
sed -i --follow-symlink \
-e "s/-genesis/-000-Ps9mPmXa/" \
$(find . -name dune -or -name \*.opam)
sed -i --follow-symlink \
-e "s/_genesis/_000_Ps9mPmXa/" \
$(find lib_delegate/test -type f)
fi

49
vendors/tezos-modded/scripts/update_hashes.sh vendored Executable file
View File

@ -0,0 +1,49 @@
#! /bin/sh
script_dir="$(cd "$(dirname "$0")" && echo "$(pwd -P)/")"
cd "$script_dir"/..
branch=$1
has_git() {
which git && [ -d .git ]
}
if has_git && ! [ -z "$(git status -s)" ] ; then
echo "This script cannot be applied within a dirty git directory,"
echo "you need 'stash' or 'commit' your changes before."
exit 1
fi
set -e
current_hash_genesis=`jq '.hash' < src/proto_genesis/lib_protocol/src/TEZOS_PROTOCOL | tr -d '"'`
echo "Genesis's current hash: $current_hash_genesis"
genesis_tmpdir=`mktemp -d`
mkdir $genesis_tmpdir/src
cp src/proto_genesis/lib_protocol/src/*.ml src/proto_genesis/lib_protocol/src/*.mli $genesis_tmpdir/src/
grep -v '"hash"' < src/proto_genesis/lib_protocol/src/TEZOS_PROTOCOL > $genesis_tmpdir/src/TEZOS_PROTOCOL
new_hash_genesis=`./tezos-protocol-compiler -hash-only $genesis_tmpdir/tmp $genesis_tmpdir/src`
echo "Genesis's new hash: $new_hash_genesis"
if [ "$current_hash_genesis" != "$new_hash_genesis" ]
then
find . -type f -exec sed "s/$current_hash_genesis/$new_hash_genesis/g" -i {} \;
git commit -a -m "Update proto Genesis's hash"
else
echo "Proto Genesis's hash hasn't changed, nothing to do"
fi
current_hash_alpha=`jq '.hash' < src/proto_alpha/lib_protocol/src/TEZOS_PROTOCOL | tr -d '"'`
echo "Alpha's current hash: $current_hash_alpha"
alpha_tmpdir=`mktemp -d`
mkdir $alpha_tmpdir/src
cp src/proto_alpha/lib_protocol/src/*.ml src/proto_alpha/lib_protocol/src/*.mli $alpha_tmpdir/src/
grep -v '"hash"' < src/proto_alpha/lib_protocol/src/TEZOS_PROTOCOL > $alpha_tmpdir/src/TEZOS_PROTOCOL
new_hash_alpha=`./tezos-protocol-compiler -hash-only $alpha_tmpdir/tmp $alpha_tmpdir/src`
echo "Alpha's new hash: $new_hash_alpha"
if [ "$current_hash_alpha" != "$new_hash_alpha" ]
then
find src/proto_alpha src/bin_client docs -type f -exec sed "s/$current_hash_alpha/$new_hash_alpha/g" -i {} \;
git commit -a -m "Update proto Alpha's hash"
else
echo "Proto Alpha's hash hasn't changed, nothing to do"
fi

View File

@ -0,0 +1,117 @@
#! /bin/sh
# Update the repository of opam packages used by tezos. Tezos uses a
# private, shrunk down, opam repository to store all its
# dependencies. This is generated by the official opam repository
# (branch master) and then filtered using opam admin to include only
# the cone of tezos dependencies. This repository is then used to
# create the based opam image used by the CI to compile tezos and to
# generate the docker images. From time to time, when it is necessary
# to update a dependency, this repository should be manually
# refreshed. This script takes care of generating a patch for the
# private opam tezos repository. This patch must be applied manually
# w.r.t. the master branch. The procedure is as follows :
#
# 1. Update the variable `full_opam_repository_tag` in `version.sh` to
# a commit hash from the master branch of the official
# opam-repository. All the required packages will be extracted from
# this snapshot to the repo.
#
# 2. Run this script, it will generate a file `opam_repo.patch`
#
# 3. Review the patch.
#
# 4. In the tezos opam-repository, create a new branch from master and
# apply this patch. Push the patch and create a merge request. A
# new docker image with all the prebuilt dependencies will be
# created by the CI.
#
# 5. Update the variable `opam_repository_tag` in files
# `scripts/version.sh` and `.gitlab-ci.yml` with the hash of the
# newly created commit in `tezos/opam-repository`.
#
# 6. Enjoy your new dependencies
set -e
target="$(pwd)"/opam_repo.patch tmp_dir=$(mktemp -dt tezos_deps_opam.XXXXXXXX)
cleanup () {
set +e
echo Cleaning up...
rm -rf "$tmp_dir"
rm -rf Dockerfile
}
trap cleanup EXIT INT
script_dir="$(cd "$(dirname "$0")" && echo "$(pwd -P)/")"
src_dir="$(dirname "$script_dir")"
. "$script_dir"/version.sh
opams=$(find "$src_dir/vendors" "$src_dir/src" -name \*.opam -print)
## Full snapshot of the opam repository
git clone https://github.com/ocaml/opam-repository -b master "$tmp_dir"
## Adding the various tezos packages
packages=
for opam in $opams; do
dir=$(dirname $opam)
file=$(basename $opam)
package=${file%.opam}
packages=$packages,$package
mkdir -p "$tmp_dir"/packages/$package/$package.dev
## HACK: For some reason, `opam admin list/filter` do not follow
## `--with-test/doc` for 'toplevel' package, only for their
## 'dependencies. We want the exact opposite (like for `opam
## install`), so we manually remove the tag in the most
## ugliest-possible way...
sed -e "s/{ *with-test *}//" \
-e "s/with-test \& //" \
-e "s/\& with-test//" \
-e "s/{ *with-doc *}//" \
-e "s/with-doc \& //" \
-e "s/\& with-doc//" \
$opam > "$tmp_dir"/packages/$package/$package.dev/opam
done
## Filtering unrequired packages
cd $tmp_dir
git reset --hard "$full_opam_repository_tag"
opam admin filter --yes \
--resolve $packages,ocaml,ocaml-base-compiler,odoc,opam-depext,js_of_ocaml-ppx
## Adding useful compiler variants
for variant in afl flambda fp fp+flambda ; do
git checkout packages/ocaml-variants/ocaml-variants.$ocaml_version+$variant
done
## Removing the various tezos packages
for opam in $opams; do
file=$(basename $opam)
package=${file%.opam}
rm -r "$tmp_dir"/packages/$package
done
## Adding safer hashes
opam admin add-hashes sha256 sha512
## Generating the diff!
git remote add tezos $opam_repository_url
git fetch tezos
git reset "$opam_repository_tag"
git add packages
git diff HEAD -- packages > "$target"
echo
echo "Wrote proposed update in: $target."
echo 'Please add this patch to: `https://gitlab.com/tezos/opam-repository`'
echo 'And update accordingly the commit hash in: `.gitlab-ci.yml` and `scripts/version.sh`'
echo

View File

@ -0,0 +1,30 @@
#! /bin/sh
set -e
script_dir="$(cd "$(dirname "$0")" && echo "$(pwd -P)/")"
src_dir="$(dirname "$script_dir")"
. "$script_dir/opam-pin.sh"
tmp=$(mktemp)
sed -z 's/^\(.*##BEGIN_OPAM##\n\).*\(\n##END_OPAM##.*\)$/\1/' "$src_dir/.gitlab-ci.yml" > $tmp
cpt=0
for package in $packages; do
num=$(printf "%02d" $cpt)
cpt=$((cpt+1))
cat >> $tmp <<EOF
opam:$num:$package:
<<: *opam_definition
variables:
package: $package
EOF
done
sed -z 's/^\(.*##BEGIN_OPAM##\n\).*\(\n##END_OPAM##.*\)$/\2/' "$src_dir/.gitlab-ci.yml" >> $tmp
mv $tmp "$src_dir/.gitlab-ci.yml"

13
vendors/tezos-modded/scripts/version.sh vendored Normal file
View File

@ -0,0 +1,13 @@
#! /bin/sh
## `ocaml-version` should be in sync with `README.rst` and
## `lib.protocol-compiler/tezos-protocol-compiler.opam`
ocaml_version=4.06.1
opam_version=2.0
## Please update `.gitlab-ci.yml` accordingly
opam_repository_tag=9f0956e21f4dcd2803d83072903872eba196bef8
full_opam_repository_tag=3ed20d6cfd8a35fd8b459bec3a30e149b6dc03d4
opam_repository_url=https://gitlab.com/tezos/opam-repository.git
opam_repository=$opam_repository_url\#$opam_repository_tag

View File

@ -0,0 +1,21 @@
diff --git a/src/bin_node/node_config_file.ml b/src/bin_node/node_config_file.ml
--- a/src/bin_node/node_config_file.ml
+++ b/src/bin_node/node_config_file.ml
@@ -14,7 +14,7 @@ let home =
with Not_found -> "/root"
let default_data_dir = home // ".tezos-node"
-let default_p2p_port = 9732
+let default_p2p_port = 19732
let default_rpc_port = 8732
type t = {
@@ -85,7 +85,7 @@ let default_p2p_limits : P2p.limits = {
let default_p2p = {
expected_pow = 24. ;
- bootstrap_peers = ["bootstrap.tezos.com"] ;
+ bootstrap_peers = [ "52.47.156.43" ; "35.182.249.228" ; "13.231.173.142" ] ;
listen_addr = Some ("[::]:" ^ string_of_int default_p2p_port) ;
closed = false ;
limits = default_p2p_limits ;

1
vendors/tezos-modded/scripts/zeronet.sh vendored Symbolic link
View File

@ -0,0 +1 @@
alphanet.sh

View File

@ -0,0 +1,26 @@
(*****************************************************************************)
(* *)
(* Open Source License *)
(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. <contact@tezos.com> *)
(* *)
(* Permission is hereby granted, free of charge, to any person obtaining a *)
(* copy of this software and associated documentation files (the "Software"),*)
(* to deal in the Software without restriction, including without limitation *)
(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *)
(* and/or sell copies of the Software, and to permit persons to whom the *)
(* Software is furnished to do so, subject to the following conditions: *)
(* *)
(* The above copyright notice and this permission notice shall be included *)
(* in all copies or substantial portions of the Software. *)
(* *)
(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*)
(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *)
(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *)
(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*)
(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *)
(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *)
(* DEALINGS IN THE SOFTWARE. *)
(* *)
(*****************************************************************************)
let () = Attacker_minimal.main ()

View File

@ -0,0 +1,336 @@
(*****************************************************************************)
(* *)
(* Open Source License *)
(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. <contact@tezos.com> *)
(* *)
(* Permission is hereby granted, free of charge, to any person obtaining a *)
(* copy of this software and associated documentation files (the "Software"),*)
(* to deal in the Software without restriction, including without limitation *)
(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *)
(* and/or sell copies of the Software, and to permit persons to whom the *)
(* Software is furnished to do so, subject to the following conditions: *)
(* *)
(* The above copyright notice and this permission notice shall be included *)
(* in all copies or substantial portions of the Software. *)
(* *)
(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*)
(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *)
(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *)
(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*)
(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *)
(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *)
(* DEALINGS IN THE SOFTWARE. *)
(* *)
(*****************************************************************************)
open Format
include Logging.Make(struct let name = "attacker" end)
module Proto = Client_embedded_proto_alpha
(* the genesis block and network *)
let genesis_block_hashed = Block_hash.of_b58check
"BLockGenesisGenesisGenesisGenesisGenesisGeneskvg68z"
let network = Store.Net genesis_block_hashed
let network = Store.Chain_id.Id genesis_block_hashed
(* the bootstrap accounts and actions like signing to do with them *)
let source_account = List.nth Proto.Bootstrap_storage.accounts 4
let destination_account = List.nth Proto.Bootstrap_storage.accounts 0
let wrong_account = List.nth Proto.Bootstrap_storage.accounts 1
let another_account = List.nth Proto.Bootstrap_storage.accounts 2
let signed = Ed25519.append_signature source_account.secret_key
let signed_wrong = Ed25519.append_signature wrong_account.secret_key
(* forge a block from a list of operations *)
let block_forged ?prev ops =
let from_int64 x =
[ MBytes.of_string Proto.Constants_repr.version_number ;
Proto.Fitness_repr.int64_to_bytes x ] in
let pred = match prev with None -> genesis_block_hashed | Some x -> x in
let block ops = Store.Block_header.{ chain_id = network ;
predecessor = pred ;
timestamp = Time.now () ;
fitness = from_int64 1L;
operations = ops } in
let open Proto in
let generate_proof_of_work_nonce () =
Rand.generate
Proto.Alpha_context.Constants.proof_of_work_nonce_size in
let generate_seed_nonce () =
match Proto.Nonce_storage.of_bytes @@
Rand.generate
Proto.Alpha_context.Constants.nonce_length with
| Error _ -> assert false
| Ok nonce -> nonce in
Block_repr.forge_header (block ops)
Block_repr.{
baking_slot = {level = Raw_level_repr.of_int32_exn 1l ; priority = 0l } ;
seed_nonce_hash = Proto.Nonce_storage.hash (generate_seed_nonce ());
proof_of_work_nonce = generate_proof_of_work_nonce () ;
}
(* forge a transaction *)
let tx_forged ?dest amount fee =
let open Proto.Operation_repr in
let open Proto.Tez_repr in
let open Proto.Contract_repr in
let trgt
= match dest with
None -> destination_account
| Some dest -> dest in
let src = source_account in
let tx = Transaction
{ amount = of_cents_exn amount ;
parameters = None ;
destination = default_contract trgt.public_key_hash ; } in
let op = Sourced_operations
( Manager_operations
{ source = default_contract src.public_key_hash ;
public_key = Some src.public_key ;
fee = of_cents_exn fee ;
counter = 1l ;
operations = [tx] ; }) in
forge { chain_id = network } op
(* forge a list of proposals, california eat your heart out *)
let props_forged period props =
let open Proto.Operation_repr in
let src = source_account in
let props = Proposals {
period = period ;
proposals = props } in
let op = Sourced_operations (Delegate_operations {
source = src.public_key ;
operations = [props] }) in
forge { chain_id = network } op
(* "forge" a ballot *)
let ballot_forged period prop vote =
let open Proto.Operation_repr in
let src = source_account in
let ballot = Ballot {
period = period ;
proposal = prop ;
ballot = vote
} in
let op = Sourced_operations (Delegate_operations {
source = src.public_key ;
operations = [ballot] }) in
forge { chain_id = network } op
let identity = P2p_identity.generate Crypto_box.default_target
(* connect to the network, run an action and then disconnect *)
let try_action addr port action =
let socket = Lwt_unix.socket PF_INET6 SOCK_STREAM 0 in
let uaddr = Ipaddr_unix.V6.to_inet_addr addr in
Lwt_unix.connect socket (Lwt_unix.ADDR_INET (uaddr, port)) >>= fun () ->
let io_sched = P2p_io_scheduler.create ~read_buffer_size:(1 lsl 14) () in
let conn = P2p_io_scheduler.register io_sched socket in
P2p_connection.authenticate
~proof_of_work_target:Crypto_box.default_target
~incoming:false
conn
(addr, port)
identity Distributed_db.Raw.supported_versions >>=? fun (_, auth_fd) ->
P2p_connection.accept auth_fd Distributed_db.Raw.encoding >>= function
| Error _ -> failwith "Connection rejected by peer."
| Ok conn ->
action conn >>=? fun () ->
P2p_connection.close conn >>= fun () ->
return_unit
let replicate n x =
let rec replicate_acc acc n x =
if n <= 0 then acc else replicate_acc (x :: acc) (n-1) x in
replicate_acc [] n x
let send conn (msg : Distributed_db.Message.t) =
P2p_connection.write conn (P2p.Raw.Message msg)
let request_block_times block_hash n conn =
let open Block_hash in
lwt_log_notice
"requesting %a block %d times"
pp_short block_hash n >>= fun () ->
let block_hashes = replicate n block_hash in
send conn (Get_block_headers (network, block_hashes))
let request_op_times op_signed n conn =
let open Operation_hash in
let op_hash = hash_bytes [op_signed] in
lwt_log_notice "sending %a transaction" pp_short op_hash >>= fun () ->
send conn (Operation op_signed) >>=? fun () ->
lwt_log_notice
"requesting %a transaction %d times"
pp_short op_hash n >>= fun () ->
let op_hashes = replicate n op_hash in
send conn (Get_operations op_hashes)
let send_block_size n conn =
let bytes = MBytes.create n in
let open Block_hash in
lwt_log_notice
"propagating fake %d byte block %a" n pp_short (hash_bytes [bytes]) >>= fun () ->
send conn (Block bytes)
let send_protocol_size n conn =
let bytes = MBytes.create n in
let open Protocol_hash in
lwt_log_notice
"propagating fake %d byte protocol %a"
n pp_short (hash_bytes [bytes]) >>= fun () ->
send conn (Protocol bytes)
let send_operation_size n conn =
let op_faked = MBytes.create n in
let op_hashed = Operation_hash.hash_bytes [op_faked] in
lwt_log_notice
"propagating fake %d byte operation %a"
n Operation_hash.pp_short op_hashed >>= fun () ->
send conn (Operation op_faked) >>=? fun () ->
let block = signed (block_forged [op_hashed]) in
let block_hashed = Block_hash.hash_bytes [block] in
lwt_log_notice
"propagating block %a with operation"
Block_hash.pp_short block_hashed >>= fun () ->
send conn (Block block)
let send_operation_bad_signature () conn =
let open Operation_hash in
let signed_wrong_op = signed_wrong (tx_forged 5L 1L) in
let hashed_wrong_op = hash_bytes [signed_wrong_op] in
lwt_log_notice
"propagating operation %a with wrong signature"
pp_short hashed_wrong_op >>= fun () ->
send conn (Operation signed_wrong_op) >>=? fun () ->
let block = signed (block_forged [hashed_wrong_op]) in
let block_hashed = Block_hash.hash_bytes [block] in
lwt_log_notice
"propagating block %a with operation"
Block_hash.pp_short block_hashed >>= fun () ->
send conn (Block block)
let send_block_bad_signature () conn =
let open Block_hash in
let signed_wrong_block = signed_wrong (block_forged []) in
lwt_log_notice
"propagating block %a with wrong signature"
pp_short (hash_bytes [signed_wrong_block]) >>= fun () ->
send conn (Block signed_wrong_block)
let double_spend () conn =
let spend account =
let op_signed = signed (tx_forged ~dest:account 199999999L 1L) in
let op_hashed = Operation_hash.hash_bytes [op_signed] in
let block_signed = signed (block_forged [op_hashed]) in
let block_hashed = Block_hash.hash_bytes [block_signed] in
lwt_log_notice
"propagating operation %a"
Operation_hash.pp_short op_hashed >>= fun () ->
send conn (Operation op_signed) >>=? fun () ->
lwt_log_notice
"propagating block %a"
Block_hash.pp_short block_hashed >>= fun () ->
send conn (Block block_signed) in
spend destination_account >>=? fun () ->
spend another_account
let long_chain n conn =
lwt_log_notice "propogating %d blocks" n >>= fun () ->
let prev_ref = ref genesis_block_hashed in
let rec loop k =
if k < 1 then
return_unit
else
let block = signed (block_forged ~prev:!prev_ref []) in
prev_ref := Block_hash.hash_bytes [block] ;
send conn (Block block) >>=? fun () ->
loop (k-1) in
loop n
let lots_transactions amount fee n conn =
let signed_op = signed (tx_forged amount fee) in
let rec loop k =
if k < 1 then
return_unit
else
send conn (Operation signed_op) >>=? fun () ->
loop (k-1) in
let ops = replicate n (Operation_hash.hash_bytes [signed_op]) in
let signed_block = signed (block_forged ops) in
lwt_log_notice "propogating %d transactions" n >>= fun () ->
loop n >>=? fun () ->
lwt_log_notice
"propagating block %a with wrong signature"
Block_hash.pp_short (Block_hash.hash_bytes [signed_block]) >>= fun () ->
send conn (Block signed_block)
let main () =
let addr = Ipaddr.V6.localhost in
let port = 9732 in
let run_action action = try_action addr port action in
let run_cmd_unit lwt =
Arg.Unit begin fun () ->
Lwt_main.run begin
lwt () >>= function
| Ok () -> Lwt.return_unit
| Error err ->
lwt_log_error "Error: %a" pp_print_error err >>= fun () ->
Lwt.return_unit
end
end in
let run_cmd_int_suffix lwt =
Arg.String begin fun str ->
let last = str.[String.length str - 1] in
let init = String.sub str 0 (String.length str - 1) in
let n =
if last == 'k' || last == 'K'
then int_of_string init * 1 lsl 10
else if last == 'm' || last == 'M'
then int_of_string init * 1 lsl 20
else if last == 'g' || last == 'G'
then int_of_string init * 1 lsl 30
else int_of_string str in
Lwt_main.run begin
lwt n >>= function
| Ok () -> Lwt.return_unit
| Error err ->
lwt_log_error "Error: %a" pp_print_error err >>= fun () ->
Lwt.return_unit
end
end in
let cmds =
[( "-1",
run_cmd_int_suffix (run_action << request_block_times genesis_block_hashed),
"[N {,K,M,G}] Attempt to request to download N {,kilo,mega,giga}blocks.")
;( "-2",
run_cmd_int_suffix (run_action << request_op_times (signed (tx_forged 5L 1L))),
"[N {,K,M,G}] Attempt to request to download N {,kilo,mega,giga}ops.")
;( "-3",
run_cmd_int_suffix (run_action << send_block_size),
"[N {,K,M,G}] Attempt to propagate an N {,kilo,mega,giga}byte fake block.")
;( "-4",
run_cmd_int_suffix (run_action << send_operation_size),
"[N {,K,M,G}] Attempt to propagate an N {,kilo,mega,giga}byte fake operation.")
;( "-5",
run_cmd_int_suffix (run_action << send_protocol_size),
"[N {,K,M,G}] Attempt to propagate an N {,kilo,mega,giga}byte fake protocol.")
;( "-6",
run_cmd_unit (run_action << send_operation_bad_signature),
"Attempt to propagate a transaction with a bad signature.")
;( "-7",
run_cmd_unit (run_action << send_block_bad_signature),
"Attempt to propagate a block with a bad signature.")
;( "-8",
run_cmd_unit (run_action << double_spend),
"Attempt to send the same transaction in two blocks")
; ( "-9",
run_cmd_int_suffix (run_action << long_chain),
"[N {,K,M,G}] Attempt to send a chain of N {,kilo,mega,giga}blocks")
; ( "-10",
run_cmd_int_suffix (run_action << lots_transactions 0L 0L),
"[N {,K,M,G}] Attempt to send N {,kilo,mega,giga}ops")
] in
Arg.parse cmds print_endline "Tezos Evil Client"

Some files were not shown because too many files have changed in this diff Show More