Merge repository tezos-modded
This commit is contained in:
commit
681fe53dd6
50
vendors/tezos-modded/.dockerignore
vendored
Normal file
50
vendors/tezos-modded/.dockerignore
vendored
Normal 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
4
vendors/tezos-modded/.gitattributes
vendored
Normal 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
|
1
vendors/tezos-modded/.github/ISSUE_TEMPLATE.md
vendored
Symbolic link
1
vendors/tezos-modded/.github/ISSUE_TEMPLATE.md
vendored
Symbolic link
@ -0,0 +1 @@
|
||||
../.gitlab/issue_templates/issues.md
|
48
vendors/tezos-modded/.gitignore
vendored
Normal file
48
vendors/tezos-modded/.gitignore
vendored
Normal 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
38
vendors/tezos-modded/.gitlab-ci.yml
vendored
Normal 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
|
56
vendors/tezos-modded/.gitlab/issue_templates/issues.md
vendored
Normal file
56
vendors/tezos-modded/.gitlab/issue_templates/issues.md
vendored
Normal 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
1
vendors/tezos-modded/.ocp-indent
vendored
Normal file
@ -0,0 +1 @@
|
||||
match_clause = 4
|
20
vendors/tezos-modded/LICENSE
vendored
Normal file
20
vendors/tezos-modded/LICENSE
vendored
Normal 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
119
vendors/tezos-modded/Makefile
vendored
Normal 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
47
vendors/tezos-modded/README.md
vendored
Normal 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.
|
1
vendors/tezos-modded/active_protocol_versions
vendored
Normal file
1
vendors/tezos-modded/active_protocol_versions
vendored
Normal file
@ -0,0 +1 @@
|
||||
alpha
|
42
vendors/tezos-modded/docs/Makefile
vendored
Normal file
42
vendors/tezos-modded/docs/Makefile
vendored
Normal 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
64
vendors/tezos-modded/docs/README.rst
vendored
Normal 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.
|
77
vendors/tezos-modded/docs/_extensions/tezos_custom_roles.py
vendored
Normal file
77
vendors/tezos-modded/docs/_extensions/tezos_custom_roles.py
vendored
Normal 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], []
|
19
vendors/tezos-modded/docs/api/api-inline.rst
vendored
Normal file
19
vendors/tezos-modded/docs/api/api-inline.rst
vendored
Normal 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>
|
66
vendors/tezos-modded/docs/api/cli-commands.rst
vendored
Normal file
66
vendors/tezos-modded/docs/api/cli-commands.rst
vendored
Normal 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
|
1
vendors/tezos-modded/docs/api/p2p_usage.rst.inc
vendored
Normal file
1
vendors/tezos-modded/docs/api/p2p_usage.rst.inc
vendored
Normal file
@ -0,0 +1 @@
|
||||
|
181
vendors/tezos-modded/docs/conf.py
vendored
Normal file
181
vendors/tezos-modded/docs/conf.py
vendored
Normal 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
26
vendors/tezos-modded/docs/doc_gen/dune
vendored
Normal 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})))
|
16
vendors/tezos-modded/docs/doc_gen/errors/dune
vendored
Normal file
16
vendors/tezos-modded/docs/doc_gen/errors/dune
vendored
Normal 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})))
|
263
vendors/tezos-modded/docs/doc_gen/errors/error_doc.ml
vendored
Normal file
263
vendors/tezos-modded/docs/doc_gen/errors/error_doc.ml
vendored
Normal 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
|
62
vendors/tezos-modded/docs/doc_gen/node_helpers.ml
vendored
Normal file
62
vendors/tezos-modded/docs/doc_gen/node_helpers.ml
vendored
Normal 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
|
70
vendors/tezos-modded/docs/doc_gen/p2p_doc.ml
vendored
Normal file
70
vendors/tezos-modded/docs/doc_gen/p2p_doc.ml
vendored
Normal 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)
|
314
vendors/tezos-modded/docs/doc_gen/rpc_doc.ml
vendored
Normal file
314
vendors/tezos-modded/docs/doc_gen/rpc_doc.ml
vendored
Normal 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 "<%s>" 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
120
vendors/tezos-modded/docs/doc_gen/rst.ml
vendored
Normal 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
160
vendors/tezos-modded/docs/index.rst
vendored
Normal 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`
|
100
vendors/tezos-modded/docs/introduction/contributing.rst
vendored
Normal file
100
vendors/tezos-modded/docs/introduction/contributing.rst
vendored
Normal 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 don’t know well about the Lwt library, that’s what you want
|
||||
to learn. This library is used extensively throughout the code base, as
|
||||
that’s 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.
|
||||
- Don’t 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, don’t 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.
|
||||
- Don’t 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.
|
184
vendors/tezos-modded/docs/introduction/howtoget.rst
vendored
Normal file
184
vendors/tezos-modded/docs/introduction/howtoget.rst
vendored
Normal 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``.
|
302
vendors/tezos-modded/docs/introduction/howtorun.rst
vendored
Normal file
302
vendors/tezos-modded/docs/introduction/howtorun.rst
vendored
Normal 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'
|
481
vendors/tezos-modded/docs/introduction/howtouse.rst
vendored
Normal file
481
vendors/tezos-modded/docs/introduction/howtouse.rst
vendored
Normal 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>`
|
25
vendors/tezos-modded/docs/introduction/support.rst
vendored
Normal file
25
vendors/tezos-modded/docs/introduction/support.rst
vendored
Normal 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>`_.
|
613
vendors/tezos-modded/docs/introduction/various.rst
vendored
Normal file
613
vendors/tezos-modded/docs/introduction/various.rst
vendored
Normal 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
129
vendors/tezos-modded/docs/logo.svg
vendored
Normal 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 |
236
vendors/tezos-modded/docs/protocols/003_PsddFKi3.rst
vendored
Normal file
236
vendors/tezos-modded/docs/protocols/003_PsddFKi3.rst
vendored
Normal 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.
|
207
vendors/tezos-modded/docs/tutorials/data_encoding.rst
vendored
Normal file
207
vendors/tezos-modded/docs/tutorials/data_encoding.rst
vendored
Normal 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. Let’s 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.
|
199
vendors/tezos-modded/docs/tutorials/entering_alpha.rst
vendored
Normal file
199
vendors/tezos-modded/docs/tutorials/entering_alpha.rst
vendored
Normal 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 tower’s
|
||||
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 ledger’s state (that we call
|
||||
**context** in the code), cannot be specific to protocol Alpha’s 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 ledger’s 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 you’re 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 ledger’s 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 that’s 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.
|
366
vendors/tezos-modded/docs/tutorials/error_monad.rst
vendored
Normal file
366
vendors/tezos-modded/docs/tutorials/error_monad.rst
vendored
Normal file
@ -0,0 +1,366 @@
|
||||
.. _error_monad:
|
||||
|
||||
The Error Monad
|
||||
===============
|
||||
|
||||
This has been adapted from a blog post on *michelson-lang.com*.
|
||||
|
||||
If you’re 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 isn’t terribly scary as Monads
|
||||
go, so once you feel like you understand the gist, come on back and see
|
||||
if you can understand what’s going on.
|
||||
|
||||
I’m going to omit some convenience operations that a lot of monads
|
||||
provide in the examples below. If you want to add them, they’re not
|
||||
difficult.
|
||||
|
||||
Why you want the error monad
|
||||
----------------------------
|
||||
|
||||
In Tezos, we don’t 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, let’s write an error monad.
|
||||
|
||||
A simple version of the error monad
|
||||
-----------------------------------
|
||||
|
||||
Here’s 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 we’ll use later. The basic idea is that you return a
|
||||
value that’s correct and return an error if the operation failed.
|
||||
Outside of the error module, you can’t actually introspect an error
|
||||
value. You can only dispatch on the correctness/incorrectness of the
|
||||
value using bind.
|
||||
|
||||
What’s wrong here?
|
||||
|
||||
- We can’t report any information about an error case
|
||||
- We can’t report error traces, something that’s used to improve the
|
||||
quality of error messages throughout Tezos
|
||||
- We can’t handle some errors and continue executing
|
||||
|
||||
A slight improvement
|
||||
--------------------
|
||||
|
||||
Let’s 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 don’t have any flexibility
|
||||
about how the printing works. We still can’t create error traces and we
|
||||
can’t 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. We’re 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. We’re 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, we’ll have a way of adding a printer for each error.
|
||||
|
||||
When we add a new error handler, we’ll 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)
|
||||
|
||||
I’m also renaming the ``error`` function to ``fail``. This is the
|
||||
convention used by the actual `Error_monad` module. I’m 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.
|
||||
|
||||
I’m 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 contract’s balance being
|
||||
too low to execute the intended operation. This can be fixed by
|
||||
adding more to the contract’s 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. Here’s 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.
|
203
vendors/tezos-modded/docs/tutorials/michelson_anti_patterns.rst
vendored
Normal file
203
vendors/tezos-modded/docs/tutorials/michelson_anti_patterns.rst
vendored
Normal 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 people’s 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 people’s 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 contract’s 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 contract’s 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.
|
79
vendors/tezos-modded/docs/tutorials/profiling.rst
vendored
Normal file
79
vendors/tezos-modded/docs/tutorials/profiling.rst
vendored
Normal 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``
|
48
vendors/tezos-modded/docs/tutorials/protocol_environment.rst
vendored
Normal file
48
vendors/tezos-modded/docs/tutorials/protocol_environment.rst
vendored
Normal 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 shell’s data definitions and
|
||||
storage accessors that are accessible to the protocol.
|
73
vendors/tezos-modded/docs/tutorials/rpc.rst
vendored
Normal file
73
vendors/tezos-modded/docs/tutorials/rpc.rst
vendored
Normal 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/>`_.
|
3115
vendors/tezos-modded/docs/whitedoc/michelson.rst
vendored
Normal file
3115
vendors/tezos-modded/docs/whitedoc/michelson.rst
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1558
vendors/tezos-modded/docs/whitedoc/octopus.svg
vendored
Normal file
1558
vendors/tezos-modded/docs/whitedoc/octopus.svg
vendored
Normal file
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 437 KiB |
127
vendors/tezos-modded/docs/whitedoc/p2p.rst
vendored
Normal file
127
vendors/tezos-modded/docs/whitedoc/p2p.rst
vendored
Normal 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.
|
3030
vendors/tezos-modded/docs/whitedoc/packages.svg
vendored
Normal file
3030
vendors/tezos-modded/docs/whitedoc/packages.svg
vendored
Normal file
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 661 KiB |
324
vendors/tezos-modded/docs/whitedoc/proof_of_stake.rst
vendored
Normal file
324
vendors/tezos-modded/docs/whitedoc/proof_of_stake.rst
vendored
Normal 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.
|
327
vendors/tezos-modded/docs/whitedoc/the_big_picture.rst
vendored
Normal file
327
vendors/tezos-modded/docs/whitedoc/the_big_picture.rst
vendored
Normal 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
|
||||
protocol’s 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 protocol’s 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
|
120
vendors/tezos-modded/docs/whitedoc/validation.rst
vendored
Normal file
120
vendors/tezos-modded/docs/whitedoc/validation.rst
vendored
Normal 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
|
1578
vendors/tezos-modded/docs/whitedoc/validation.svg
vendored
Normal file
1578
vendors/tezos-modded/docs/whitedoc/validation.svg
vendored
Normal file
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 384 KiB |
181
vendors/tezos-modded/docs/whitedoc/voting.rst
vendored
Normal file
181
vendors/tezos-modded/docs/whitedoc/voting.rst
vendored
Normal 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
13
vendors/tezos-modded/dune
vendored
Normal 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
1
vendors/tezos-modded/dune-workspace
vendored
Normal file
@ -0,0 +1 @@
|
||||
(lang dune 1.0)
|
65
vendors/tezos-modded/emacs/README.md
vendored
Normal file
65
vendors/tezos-modded/emacs/README.md
vendored
Normal 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.
|
913
vendors/tezos-modded/emacs/michelson-mode.el
vendored
Normal file
913
vendors/tezos-modded/emacs/michelson-mode.el
vendored
Normal 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)
|
89
vendors/tezos-modded/scripts/activate_protocol.sh
vendored
Executable file
89
vendors/tezos-modded/scripts/activate_protocol.sh
vendored
Executable 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
829
vendors/tezos-modded/scripts/alphanet.sh
vendored
Executable 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
|
20
vendors/tezos-modded/scripts/alphanet_constants.patch
vendored
Normal file
20
vendors/tezos-modded/scripts/alphanet_constants.patch
vendored
Normal 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 ;
|
1
vendors/tezos-modded/scripts/alphanet_version
vendored
Normal file
1
vendors/tezos-modded/scripts/alphanet_version
vendored
Normal file
@ -0,0 +1 @@
|
||||
2018-06-30T16:07:32Z
|
35
vendors/tezos-modded/scripts/apply_patch.sh
vendored
Executable file
35
vendors/tezos-modded/scripts/apply_patch.sh
vendored
Executable 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
44
vendors/tezos-modded/scripts/b58_prefix.py
vendored
Executable 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
1
vendors/tezos-modded/scripts/betanet.sh
vendored
Symbolic link
@ -0,0 +1 @@
|
||||
alphanet.sh
|
36
vendors/tezos-modded/scripts/check_opam_test.sh
vendored
Executable file
36
vendors/tezos-modded/scripts/check_opam_test.sh
vendored
Executable 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
22
vendors/tezos-modded/scripts/check_patch.sh
vendored
Executable 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
|
47
vendors/tezos-modded/scripts/ci/create_docker_image.build.sh
vendored
Executable file
47
vendors/tezos-modded/scripts/ci/create_docker_image.build.sh
vendored
Executable 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
|
65
vendors/tezos-modded/scripts/ci/create_docker_image.minimal.sh
vendored
Executable file
65
vendors/tezos-modded/scripts/ci/create_docker_image.minimal.sh
vendored
Executable 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
|
75
vendors/tezos-modded/scripts/ci/docker_registry.inc.sh
vendored
Normal file
75
vendors/tezos-modded/scripts/ci/docker_registry.inc.sh
vendored
Normal 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
|
||||
}
|
41
vendors/tezos-modded/scripts/ci/docker_registry_delete.sh
vendored
Executable file
41
vendors/tezos-modded/scripts/ci/docker_registry_delete.sh
vendored
Executable 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
|
25
vendors/tezos-modded/scripts/ci/docker_registry_read.sh
vendored
Executable file
25
vendors/tezos-modded/scripts/ci/docker_registry_read.sh
vendored
Executable 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"
|
24
vendors/tezos-modded/scripts/ci/docker_registry_tag.sh
vendored
Executable file
24
vendors/tezos-modded/scripts/ci/docker_registry_tag.sh
vendored
Executable 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"
|
25
vendors/tezos-modded/scripts/create_docker_image.sh
vendored
Executable file
25
vendors/tezos-modded/scripts/create_docker_image.sh
vendored
Executable 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"
|
134
vendors/tezos-modded/scripts/create_genesis/create_genesis_info.py
vendored
Executable file
134
vendors/tezos-modded/scripts/create_genesis/create_genesis_info.py
vendored
Executable 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)
|
3
vendors/tezos-modded/scripts/create_genesis/requirements.txt
vendored
Normal file
3
vendors/tezos-modded/scripts/create_genesis/requirements.txt
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
-e git+https://github.com/vbuterin/pybitcointools.git@aeb0a2bbb8bbfe421432d776c649650eaeb882a5#egg=master
|
||||
pyblake2==0.9.3
|
||||
pysodium==0.6.11
|
57
vendors/tezos-modded/scripts/docker/docker-compose-generic.yml
vendored
Normal file
57
vendors/tezos-modded/scripts/docker/docker-compose-generic.yml
vendored
Normal 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:
|
134
vendors/tezos-modded/scripts/docker/entrypoint.inc.sh
vendored
Normal file
134
vendors/tezos-modded/scripts/docker/entrypoint.inc.sh
vendored
Normal 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 "$@"
|
||||
}
|
66
vendors/tezos-modded/scripts/docker/entrypoint.sh
vendored
Executable file
66
vendors/tezos-modded/scripts/docker/entrypoint.sh
vendored
Executable 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
|
66
vendors/tezos-modded/scripts/gen_genesis.ml
vendored
Normal file
66
vendors/tezos-modded/scripts/gen_genesis.ml
vendored
Normal 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")
|
16
vendors/tezos-modded/scripts/install_build_deps.raw.sh
vendored
Executable file
16
vendors/tezos-modded/scripts/install_build_deps.raw.sh
vendored
Executable 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"
|
45
vendors/tezos-modded/scripts/install_build_deps.sh
vendored
Executable file
45
vendors/tezos-modded/scripts/install_build_deps.sh
vendored
Executable 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
1
vendors/tezos-modded/scripts/localnet.sh
vendored
Symbolic link
@ -0,0 +1 @@
|
||||
alphanet.sh
|
1
vendors/tezos-modded/scripts/mainnet.sh
vendored
Symbolic link
1
vendors/tezos-modded/scripts/mainnet.sh
vendored
Symbolic link
@ -0,0 +1 @@
|
||||
alphanet.sh
|
31
vendors/tezos-modded/scripts/nginx.conf
vendored
Normal file
31
vendors/tezos-modded/scripts/nginx.conf
vendored
Normal 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
85
vendors/tezos-modded/scripts/ocamldot.py
vendored
Executable 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
39
vendors/tezos-modded/scripts/opam-check.sh
vendored
Executable 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
30
vendors/tezos-modded/scripts/opam-pin.sh
vendored
Executable 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
20
vendors/tezos-modded/scripts/opam-remove.sh
vendored
Executable 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
74
vendors/tezos-modded/scripts/opam-test-all.sh
vendored
Executable 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
13
vendors/tezos-modded/scripts/opam-unpin.sh
vendored
Executable 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
35
vendors/tezos-modded/scripts/opam-upgrade.sh
vendored
Executable 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
|
48
vendors/tezos-modded/scripts/protocol_parameters.json
vendored
Normal file
48
vendors/tezos-modded/scripts/protocol_parameters.json
vendored
Normal 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
23
vendors/tezos-modded/scripts/reset_chain.sh
vendored
Executable 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"
|
4
vendors/tezos-modded/scripts/sandbox.json
vendored
Normal file
4
vendors/tezos-modded/scripts/sandbox.json
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
{
|
||||
"genesis_pubkey":
|
||||
"edpkuSLWfVU1Vq7Jg9FucPyKmma6otcMHac9zG4oU1KMHSTBpJuGQ2"
|
||||
}
|
124
vendors/tezos-modded/scripts/snapshot_alpha.sh
vendored
Executable file
124
vendors/tezos-modded/scripts/snapshot_alpha.sh
vendored
Executable 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
49
vendors/tezos-modded/scripts/update_hashes.sh
vendored
Executable 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
|
117
vendors/tezos-modded/scripts/update_opam_repo.sh
vendored
Executable file
117
vendors/tezos-modded/scripts/update_opam_repo.sh
vendored
Executable 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
|
30
vendors/tezos-modded/scripts/update_opam_test.sh
vendored
Executable file
30
vendors/tezos-modded/scripts/update_opam_test.sh
vendored
Executable 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
13
vendors/tezos-modded/scripts/version.sh
vendored
Normal 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
|
21
vendors/tezos-modded/scripts/zeronet.patch
vendored
Normal file
21
vendors/tezos-modded/scripts/zeronet.patch
vendored
Normal 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
1
vendors/tezos-modded/scripts/zeronet.sh
vendored
Symbolic link
@ -0,0 +1 @@
|
||||
alphanet.sh
|
26
vendors/tezos-modded/src/bin_attacker/attacker_main.ml
vendored
Normal file
26
vendors/tezos-modded/src/bin_attacker/attacker_main.ml
vendored
Normal 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 ()
|
336
vendors/tezos-modded/src/bin_attacker/attacker_minimal.ml
vendored
Normal file
336
vendors/tezos-modded/src/bin_attacker/attacker_minimal.ml
vendored
Normal 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
Loading…
Reference in New Issue
Block a user