Add dev docs generation to Jenkins:

Fixes: RIPD-1521

Switch to pure doxygen HTML for developer docs. Remove docca/boostbook
system. Convert consensus document to markdown. Add existing markdown
files to doxygen input set. Fix some image paths and scale images for
use with MD links. Rename/cleanup some files for consistency.
Add pipeline logic for windows slaves. Add ninja and parallel test run
option. Add make doc target build in build-and-test.sh. Cleanup README
files. Add nounity windows build. Add link to jenkins summary table.
Add rippled_classic build (win). Improve formatting of summary table.
This commit is contained in:
Mike Ellery
2018-01-10 11:20:13 -08:00
parent 605ace7645
commit 755849115e
51 changed files with 676 additions and 3531 deletions

20
docs/CheatSheet.md Normal file
View File

@@ -0,0 +1,20 @@
# Code Style Cheat Sheet
## Form
- One class per header file.
- Place each data member on its own line.
- Place each ctor-initializer on its own line.
- Create typedefs for primitive types to describe them.
- Return descriptive local variables instead of constants.
- Use long descriptive names instead of abbreviations.
- Use "explicit" for single-argument ctors
- Avoid globals especially objects with static storage duration
- Order class declarations as types, public, protected, private, then data.
- Prefer 'private' over 'protected'
## Function
- Minimize external dependencies
* Pass options in the ctor instead of using theConfig
* Use as few other classes as possible

84
docs/CodingStyle.md Normal file
View File

@@ -0,0 +1,84 @@
# Coding Standards
Coding standards used here gradually evolve and propagate through
code reviews. Some aspects are enforced more strictly than others.
## Rules
These rules only apply to our own code. We can't enforce any sort of
style on the external repositories and libraries we include. The best
guideline is to maintain the standards that are used in those libraries.
* Tab inserts 4 spaces. No tab characters.
* Braces are indented in the [Allman style][1].
* Modern C++ principles. No naked ```new``` or ```delete```.
* Line lengths limited to 80 characters. Exceptions limited to data and tables.
## Guidelines
If you want to do something contrary to these guidelines, understand
why you're doing it. Think, use common sense, and consider that this
your changes will probably need to be maintained long after you've
moved on to other projects.
* Use white space and blank lines to guide the eye and keep your intent clear.
* Put private data members at the top of a class, and the 6 public special
members immediately after, in the following order:
* Destructor
* Default constructor
* Copy constructor
* Copy assignment
* Move constructor
* Move assignment
* Don't over-inline by defining large functions within the class
declaration, not even for template classes.
## Formatting
The goal of source code formatting should always be to make things as easy to
read as possible. White space is used to guide the eye so that details are not
overlooked. Blank lines are used to separate code into "paragraphs."
* Always place a space before and after all binary operators,
especially assignments (`operator=`).
* The `!` operator should always be followed by a space.
* The `~` operator should be preceded by a space, but not followed by one.
* The `++` and `--` operators should have no spaces between the operator and
the operand.
* A space never appears before a comma, and always appears after a comma.
* Always place a space before an opening parenthesis. One exception is if
the parentheses are empty.
* Don't put spaces after a parenthesis. A typical member function call might
look like this: `foobar (1, 2, 3);`
* In general, leave a blank line before an `if` statement.
* In general, leave a blank line after a closing brace `}`.
* Do not place code or comments on the same line as any opening or
closing brace.
* Do not write `if` statements all-on-one-line. The exception to this is when
you've got a sequence of similar `if` statements, and are aligning them all
vertically to highlight their similarities.
* In an `if-else` statement, if you surround one half of the statement with
braces, you also need to put braces around the other half, to match.
* When writing a pointer type, use this spacing: `SomeObject* myObject`.
Technically, a more correct spacing would be `SomeObject *myObject`, but
it makes more sense for the asterisk to be grouped with the type name,
since being a pointer is part of the type, not the variable name. The only
time that this can lead to any problems is when you're declaring multiple
pointers of the same type in the same statement - which leads on to the next
rule:
* When declaring multiple pointers, never do so in a single statement, e.g.
`SomeObject* p1, *p2;` - instead, always split them out onto separate lines
and write the type name again, to make it quite clear what's going on, and
avoid the danger of missing out any vital asterisks.
* The previous point also applies to references, so always put the `&` next to
the type rather than the variable, e.g. `void foo (Thing const& thing)`. And
don't put a space on both sides of the `*` or `&` - always put a space after
it, but never before it.
* The word `const` should be placed to the right of the thing that it modifies,
for consistency. For example `int const` refers to an int which is const.
`int const*` is a pointer to an int which is const. `int *const` is a const
pointer to an int.
* Always place a space in between the template angle brackets and the type
name. Template code is already hard enough to read!
[1]: http://en.wikipedia.org/wiki/Indent_style#Allman_style

16
docs/Docker.md Normal file
View File

@@ -0,0 +1,16 @@
# Rippled Docker Image
Rippled has a continuous deployment pipeline that turns every git commit into a
docker image for quick testing and deployment.
To run the tip of the latest release via docker:
```$ docker run -P -v /srv/rippled/ ripple/rippled:latest```
To run the tip of active development:
```$ docker run -P -v /srv/rippled/ ripple/rippled:develop```
Where ```/srv/rippled``` points to a directory containing a rippled.cfg and
database files. By default, port 5005/tcp maps to the RPC port and 51235/udp to
the peer port.

View File

@@ -1,22 +1,31 @@
FROM ubuntu:16.04
RUN apt-get update
RUN apt-get -y install build-essential g++ git libbz2-dev wget python-dev
RUN apt -y update
RUN apt -y upgrade
RUN apt -y install build-essential g++ git libbz2-dev wget python-dev
RUN apt -y install cmake flex bison graphviz graphviz-dev libicu-dev
RUN apt -y install jarwrapper java-common
# Install Boost
ENV BOOST_SHA 440a59f8bc4023dbe6285c9998b0f7fa288468b889746b1ef00e8b36c559dce1
RUN wget https://sourceforge.net/projects/boost/files/boost/1.62.0/boost_1_62_0.tar.gz
RUN echo "$BOOST_SHA boost_1_62_0.tar.gz" | sha256sum -c
RUN tar xzf boost_1_62_0.tar.gz
RUN cd boost_1_62_0 && ./bootstrap.sh --prefix=/usr/local
RUN cd boost_1_62_0 && ./b2 install
ENV BOOST_ROOT=/boost_1_62_0
RUN cd /tmp
ENV CM_INSTALLER=cmake-3.10.0-rc3-Linux-x86_64.sh
ENV CM_VER_DIR=/opt/local/cmake-3.10.0
RUN cd /tmp && wget https://cmake.org/files/v3.10/$CM_INSTALLER && chmod a+x $CM_INSTALLER
RUN mkdir -p $CM_VER_DIR
RUN ln -s $CM_VER_DIR /opt/local/cmake
RUN /tmp/$CM_INSTALLER --prefix=$CM_VER_DIR --exclude-subdir
RUN rm -f /tmp/$CM_INSTALLER
# Install dependencies
RUN apt-get -y install doxygen
RUN apt-get -y install xsltproc
RUN cd /tmp && wget https://ftp.stack.nl/pub/users/dimitri/doxygen-1.8.14.src.tar.gz
RUN cd /tmp && tar xvf doxygen-1.8.14.src.tar.gz
RUN mkdir -p /tmp/doxygen-1.8.14/build
RUN cd /tmp/doxygen-1.8.14/build && /opt/local/cmake/bin/cmake -G "Unix Makefiles" ..
RUN cd /tmp/doxygen-1.8.14/build && make -j2
RUN cd /tmp/doxygen-1.8.14/build && make install
RUN rm -f /tmp/doxygen-1.8.14.src.tar.gz
RUN rm -rf /tmp/doxygen-1.8.14
CMD cd /opt/rippled/docs && \
chmod +x makeqbk.sh && \
./makeqbk.sh && \
$BOOST_ROOT/b2
RUN mkdir -p /opt/plantuml
RUN wget -O /opt/plantuml/plantuml.jar http://sourceforge.net/projects/plantuml/files/plantuml.jar/download
ENV PLANTUML_JAR=/opt/plantuml/plantuml.jar
CMD cd /opt/rippled/docs && doxygen source.dox

63
docs/HeapProfiling.md Normal file
View File

@@ -0,0 +1,63 @@
## Heap profiling of rippled with jemalloc
The jemalloc library provides a good API for doing heap analysis,
including a mechanism to dump a description of the heap from within the
running application via a function call. Details on how to perform this
activity in general, as well as how to acquire the software, are available on
the jemalloc site:
[https://github.com/jemalloc/jemalloc/wiki/Use-Case:-Heap-Profiling](https://github.com/jemalloc/jemalloc/wiki/Use-Case:-Heap-Profiling)
jemalloc is acquired separately from rippled, and is not affiliated
with Ripple Labs. If you compile and install jemalloc from the
source release with default options, it will install the library and header
under `/usr/local/lib` and `/usr/local/include`, respectively. Heap
profiling has been tested with rippled on a Linux platform. It should
work on platforms on which both rippled and jemalloc are available.
To link rippled with jemalloc, the argument
`profile-jemalloc=<jemalloc_dir>` is provided after the optional target.
The `<jemalloc_dir>` argument should be the same as that of the
`--prefix` parameter passed to the jemalloc configure script when building.
## Examples:
Build rippled with jemalloc library under /usr/local/lib and
header under /usr/local/include:
$ scons profile-jemalloc=/usr/local
Build rippled using clang with the jemalloc library under /opt/local/lib
and header under /opt/local/include:
$ scons clang profile-jemalloc=/opt/local
----------------------
## Using the jemalloc library from within the code
The `profile-jemalloc` parameter enables a macro definition called
`PROFILE_JEMALLOC`. Include the jemalloc header file as
well as the api call(s) that you wish to make within preprocessor
conditional groups, such as:
In global scope:
#ifdef PROFILE_JEMALLOC
#include <jemalloc/jemalloc.h>
#endif
And later, within a function scope:
#ifdef PROFILE_JEMALLOC
mallctl("prof.dump", NULL, NULL, NULL, 0);
#endif
Fuller descriptions of how to acquire and use jemalloc's api to do memory
analysis are available at the [jemalloc
site.](http://www.canonware.com/jemalloc/)
Linking against the jemalloc library will override
the system's default `malloc()` and related functions with jemalloc's
implementation. This is the case even if the code is not instrumented
to use jemalloc's specific API.

View File

@@ -1,81 +0,0 @@
#
# Copyright (c) 2015-2016 Vinnie Falco (vinnie dot falco at gmail dot com)
#
# Distributed under the Boost Software License, Version 1.0. (See accompanying
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#
import os ;
local broot = [ os.environ BOOST_ROOT ] ;
project rippled/doc ;
using boostbook ;
using quickbook ;
using doxygen ;
path-constant out : . ;
install stylesheets
:
$(broot)/doc/src/boostbook.css
:
<location>$(out)/html
;
explicit stylesheets ;
install images
:
[ glob $(broot)/doc/src/images/*.png ]
:
<location>$(out)/html/images
;
explicit images ;
install callouts
:
[ glob $(broot)/doc/src/images/callouts/*.png ]
:
<location>$(out)/html/images/callouts
;
explicit callout ;
install consensus_images
:
[ glob images/consensus/*.png ]
:
<location>$(out)/html/images/consensus
;
explicit consensus_images ;
xml doc
:
main.qbk
:
<location>temp
<include>$(broot)/tools/boostbook/dtd
;
boostbook boostdoc
:
doc
:
<xsl:param>chapter.autolabel=0
<xsl:param>boost.root=$(broot)
<xsl:param>chunk.first.sections=1 # Chunk the first top-level section?
<xsl:param>chunk.section.depth=8 # Depth to which sections should be chunked
<xsl:param>generate.section.toc.level=2 # Control depth of TOC generation in sections
<xsl:param>toc.max.depth=2 # How many levels should be created for each TOC?
<xsl:param>toc.section.depth=2 # How deep should recursive sections appear in the TOC?
<xsl:param>generate.toc="chapter toc section toc"
:
<location>temp
<dependency>stylesheets
<dependency>images
<dependency>consensus_images
;

Binary file not shown.

View File

@@ -13,21 +13,6 @@ relative to the `docs/` directory.
Install these dependencies:
1. Install [Doxygen](http://www.stack.nl/~dimitri/doxygen/download.html)
2. Download the following zip files from [xsltproc](https://www.zlatkovic.com/pub/libxml/)
(Alternate download: ftp://ftp.zlatkovic.com/libxml/),
and extract the `bin\` folder contents into any folder in your path.
* iconv
* libxml2
* libxslt
* zlib
3. Download [Boost](http://www.boost.org/users/download/)
1. Extract the compressed file contents to your (new) `$BOOST_ROOT` location.
2. Open a command prompt or shell in the `$BOOST_ROOT`.
3. `./bootstrap.bat`
4. (Optional, if you also plan to build rippled) `./bjam.exe --toolset=msvc-14.0
--build-type=complete variant=debug,release link=static runtime-link=static
address-model=64 stage`
5. If it is not already there, add your `$BOOST_ROOT` to your environment `$PATH`.
### MacOS
@@ -38,47 +23,54 @@ Install these dependencies:
You'll then need to make doxygen available to your command line. You can
do this by adding a symbolic link from `/usr/local/bin` to the doxygen
executable. For example, `$ ln -s /Applications/Doxygen.app/Contents/Resources/doxygen /usr/local/bin/doxygen`
2. Install [Boost](http://www.boost.org/users/download/)
1. Extract the compressed file contents to your (new) `$BOOST_ROOT` location.
2. Open a command prompt or shell in the `$BOOST_ROOT`.
3. `$ ./bootstrap.bat`
4. (Optional, if you also plan to build rippled)
`$ ./b2 toolset=clang threading=multi runtime-link=static link=static
cxxflags="-stdlib=libc++" linkflags="-stdlib=libc++" adress-model=64`
5. If it is not already there, add your `$BOOST_ROOT` to your environment
`$PATH`. This makes the `b2` command available to the command line.
3. That should be all that's required. In OS X 10.11, at least, libxml2 and
libxslt come pre-installed.
### Linux
1. Install [Docker](https://docs.docker.com/engine/installation/)
2. Build Docker image. From the rippled root folder:
```
sudo docker build -t rippled-docs docs/
```
1. Install doxygen using your package manager OR from source using the links above.
## Setup project submodules
### [Optional] Install Plantuml (all platforms)
1. Open a shell in your rippled root folder.
2. `git submodule init`
3. `git submodule update docs/docca`
Doxygen supports the optional use of [plantuml](http://plantuml.com) to
generate diagrams from `@startuml` sections. We don't currently rely on this
functionality for docs, so it's largely optional. Requirements:
1. Download/install a functioning java runtime, if you don't already have one.
2. Download [plantuml](http://plantuml.com) from
[here](http://sourceforge.net/projects/plantuml/files/plantuml.jar/download).
Set a system environment variable named `PLANTUML_JAR` with a value of the fullpath
to the file system location of the `plantuml.jar` file you downloaded.
## Do it
### Windows & MacOS
### all platforms
From the rippled root folder:
```
cd docs
./makeqbk.sh && b2
mkdir -p html_doc
doxygen source.dox
```
The output will be in `docs/html`.
The output will be in `docs/html_doc`.
### Linux
## Docker
(applicable to all platforms)
Instead of installing the doxygen tools locally, you can use the provided `Dockerfile` to create
an ubuntu based image for running the tools:
1. Install [Docker](https://docs.docker.com/engine/installation/)
2. Build Docker image. From the rippled root folder:
```
sudo docker build -t rippled-docs docs/
```
Then to run the image, from the rippled root folder:
From the rippled root folder:
```
sudo docker run -v $PWD:/opt/rippled --rm rippled-docs
```
The output will be in `docs/html`.
The output will be in `docs/html_doc`.

View File

@@ -1,439 +0,0 @@
<!--
BoostBook DTD - development version
For further information, see: http://www.crystalclearsoftware.com/cgi-bin/boost_wiki/wiki.pl?Boost_Documentation_Format
Copyright (c) 2002 by Peter Simons <simons@cryp.to>
Copyright (c) 2003-2004 by Douglas Gregor <doug.gregor -at- gmail.com>
Copyright (c) 2007 by Frank Mori Hess <fmhess@users.sourceforge.net>
Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt)
The latest stable DTD module is identified by the PUBLIC and SYSTEM identifiers:
PUBLIC "-//Boost//DTD BoostBook XML V1.1//EN"
SYSTEM "http://www.boost.org/tools/boostbook/dtd/1.1/boostbook.dtd"
$Revision$
$Date$
-->
<!--========== Define XInclude features. ==========-->
<!-- This is not really integrated into the DTD yet. Needs more
research. -->
<!--
<!ELEMENT xi:include (xi:fallback)?>
<!ATTLIST xi:include
xmlns:xi CDATA #FIXED "http://www.w3.org/2001/XInclude"
href CDATA #REQUIRED
parse (xml|text) "xml"
encoding CDATA #IMPLIED>
<!ELEMENT xi:fallback ANY>
<!ATTLIST xi:fallback
xmlns:xi CDATA #FIXED "http://www.w3.org/2001/XInclude">
-->
<!ENTITY % local.common.attrib "last-revision CDATA #IMPLIED">
<!--========== Define the BoostBook extensions ==========-->
<!ENTITY % boost.common.attrib "%local.common.attrib;
id CDATA #IMPLIED">
<!ENTITY % boost.namespace.mix
"class|class-specialization|struct|struct-specialization|
union|union-specialization|typedef|enum|
free-function-group|function|overloaded-function|
namespace">
<!ENTITY % boost.template.mix
"template-type-parameter|template-nontype-parameter|template-varargs">
<!ENTITY % boost.class.members
"static-constant|typedef|enum|
copy-assignment|constructor|destructor|method-group|
method|overloaded-method|data-member|class|class-specialization|struct|
struct-specialization|union|union-specialization">
<!ENTITY % boost.class.mix
"%boost.class.members;|free-function-group|function|overloaded-function">
<!ENTITY % boost.class.content
"template?, inherit*, purpose?, description?,
(%boost.class.mix;|access)*">
<!ENTITY % boost.class-specialization.content
"template?, specialization?, inherit?, purpose?, description?,
(%boost.class.mix;|access)*">
<!ENTITY % boost.function.semantics
"purpose?, description?, requires?, effects?, postconditions?,
returns?, throws?, complexity?, notes?, rationale?">
<!ENTITY % library.content
"libraryinfo, (title, ((section|library-reference|testsuite))+)?">
<!ELEMENT library (%library.content;)>
<!ATTLIST library
name CDATA #REQUIRED
dirname CDATA #REQUIRED
html-only CDATA #IMPLIED
url CDATA #IMPLIED
%boost.common.attrib;>
<!ELEMENT boostbook (title, (chapter|library)*)>
<!ATTLIST boostbook %boost.common.attrib;>
<!ELEMENT libraryinfo (author+, copyright*, legalnotice*, librarypurpose, librarycategory*)>
<!ATTLIST libraryinfo %boost.common.attrib;>
<!ELEMENT librarypurpose (#PCDATA|code|ulink|functionname|methodname|classname|macroname|headername|enumname|globalname)*>
<!ATTLIST librarypurpose %boost.common.attrib;>
<!ELEMENT librarycategory (#PCDATA)>
<!ATTLIST librarycategory
name CDATA #REQUIRED
%boost.common.attrib;>
<!ELEMENT libraryname (#PCDATA)>
<!ATTLIST libraryname %boost.common.attrib;>
<!ELEMENT library-reference ANY>
<!ATTLIST library-reference
%boost.common.attrib;>
<!ELEMENT librarylist EMPTY>
<!ATTLIST librarylist %boost.common.attrib;>
<!ELEMENT librarycategorylist (librarycategorydef)*>
<!ATTLIST librarycategorylist %boost.common.attrib;>
<!ELEMENT librarycategorydef (#PCDATA)>
<!ATTLIST librarycategorydef
name CDATA #REQUIRED
%boost.common.attrib;>
<!ELEMENT header ANY>
<!ATTLIST header
name CDATA #REQUIRED
%boost.common.attrib;>
<!ELEMENT namespace (%boost.namespace.mix;)*>
<!ATTLIST namespace
name CDATA #REQUIRED
%boost.common.attrib;>
<!ELEMENT class (%boost.class.content;)>
<!ATTLIST class
name CDATA #REQUIRED
%boost.common.attrib;>
<!ELEMENT struct (%boost.class.content;)>
<!ATTLIST struct
name CDATA #REQUIRED
%boost.common.attrib;>
<!ELEMENT union (%boost.class.content;)>
<!ATTLIST union
name CDATA #REQUIRED
%boost.common.attrib;>
<!ELEMENT class-specialization (%boost.class-specialization.content;)>
<!ATTLIST class-specialization
name CDATA #REQUIRED
%boost.common.attrib;>
<!ELEMENT struct-specialization (%boost.class-specialization.content;)>
<!ATTLIST struct-specialization
name CDATA #REQUIRED
%boost.common.attrib;>
<!ELEMENT union-specialization (%boost.class-specialization.content;)>
<!ATTLIST union-specialization
name CDATA #REQUIRED
%boost.common.attrib;>
<!ELEMENT access (%boost.class.members;)+>
<!ATTLIST access
name CDATA #REQUIRED
%boost.common.attrib;>
<!--========= C++ Templates =========-->
<!ELEMENT template (%boost.template.mix;)*>
<!ATTLIST template %boost.common.attrib;>
<!ELEMENT template-type-parameter (default?, purpose?)>
<!ATTLIST template-type-parameter
name CDATA #REQUIRED
pack CDATA #IMPLIED
%boost.common.attrib;>
<!ELEMENT template-nontype-parameter (type, default?, purpose?)>
<!ATTLIST template-nontype-parameter
name CDATA #REQUIRED
pack CDATA #IMPLIED
%boost.common.attrib;>
<!ELEMENT template-varargs EMPTY>
<!ATTLIST template-varargs %boost.common.attrib;>
<!ELEMENT specialization (template-arg)*>
<!ATTLIST specialization %boost.common.attrib;>
<!ELEMENT template-arg ANY>
<!ATTLIST template-arg
pack CDATA #IMPLIED
%boost.common.attrib;>
<!ELEMENT default ANY>
<!ATTLIST default %boost.common.attrib;>
<!ELEMENT inherit (type, purpose?)>
<!ATTLIST inherit
access CDATA #IMPLIED
pack CDATA #IMPLIED
%boost.common.attrib;>
<!ELEMENT purpose ANY>
<!ATTLIST purpose %boost.common.attrib;>
<!ELEMENT description ANY>
<!ATTLIST description %boost.common.attrib;>
<!ELEMENT type ANY>
<!ATTLIST type %boost.common.attrib;>
<!ELEMENT typedef (type, purpose?, description?)>
<!ATTLIST typedef
name CDATA #REQUIRED
%boost.common.attrib;>
<!ELEMENT enum (enumvalue*, purpose?, description?)>
<!ATTLIST enum
name CDATA #REQUIRED
%boost.common.attrib;>
<!ELEMENT enumvalue (default?, purpose?, description?)>
<!ATTLIST enumvalue
name CDATA #REQUIRED
%boost.common.attrib;>
<!ELEMENT static-constant (type, default, purpose?, description?)>
<!ATTLIST static-constant
name CDATA #REQUIRED
%boost.common.attrib;>
<!ELEMENT data-member (type, purpose?, description?)>
<!ATTLIST data-member
name CDATA #REQUIRED
specifiers CDATA #IMPLIED
%boost.common.attrib;>
<!ELEMENT paramtype ANY>
<!ATTLIST paramtype %boost.common.attrib;>
<!ELEMENT effects ANY>
<!ATTLIST effects %boost.common.attrib;>
<!ELEMENT postconditions ANY>
<!ATTLIST postconditions %boost.common.attrib;>
<!ELEMENT method-group (method|overloaded-method)*>
<!ATTLIST method-group
name CDATA #REQUIRED
%boost.common.attrib;>
<!ELEMENT constructor (template?, parameter*, %boost.function.semantics;)>
<!ATTLIST constructor
specifiers CDATA #IMPLIED
%boost.common.attrib;>
<!ELEMENT destructor (%boost.function.semantics;)>
<!ATTLIST destructor
specifiers CDATA #IMPLIED
%boost.common.attrib;>
<!ELEMENT method (template?, type, parameter*, %boost.function.semantics;)>
<!ATTLIST method
name CDATA #REQUIRED
cv CDATA #IMPLIED
specifiers CDATA #IMPLIED
%boost.common.attrib;>
<!ELEMENT function (template?, type, parameter*, %boost.function.semantics;)>
<!ATTLIST function
name CDATA #REQUIRED
specifiers CDATA #IMPLIED
%boost.common.attrib;>
<!ELEMENT overloaded-method (signature*, %boost.function.semantics;)>
<!ATTLIST overloaded-method
name CDATA #REQUIRED
%boost.common.attrib;>
<!ELEMENT overloaded-function (signature*, %boost.function.semantics;)>
<!ATTLIST overloaded-function
name CDATA #REQUIRED
%boost.common.attrib;>
<!ELEMENT signature (template?, type, parameter*)>
<!ATTLIST signature
cv CDATA #IMPLIED
specifiers CDATA #IMPLIED
%boost.common.attrib;>
<!ELEMENT requires ANY>
<!ATTLIST requires %boost.common.attrib;>
<!ELEMENT returns ANY>
<!ATTLIST returns %boost.common.attrib;>
<!ELEMENT throws ANY>
<!ATTLIST throws %boost.common.attrib;>
<!ELEMENT complexity ANY>
<!ATTLIST complexity %boost.common.attrib;>
<!ELEMENT notes ANY>
<!ATTLIST notes %boost.common.attrib;>
<!ELEMENT rationale ANY>
<!ATTLIST rationale %boost.common.attrib;>
<!ELEMENT functionname (#PCDATA)>
<!ATTLIST functionname
alt CDATA #IMPLIED
%boost.common.attrib;>
<!ELEMENT enumname (#PCDATA)>
<!ATTLIST enumname
alt CDATA #IMPLIED
%boost.common.attrib;>
<!ELEMENT macroname (#PCDATA)>
<!ATTLIST macroname
alt CDATA #IMPLIED
%boost.common.attrib;>
<!ELEMENT headername (#PCDATA)>
<!ATTLIST headername
alt CDATA #IMPLIED
%boost.common.attrib;>
<!ELEMENT globalname (#PCDATA)>
<!ATTLIST globalname
alt CDATA #IMPLIED
%boost.common.attrib;>
<!ELEMENT copy-assignment
(template?, type?, parameter*, %boost.function.semantics;)>
<!ATTLIST copy-assignment
cv CDATA #IMPLIED
specifiers CDATA #IMPLIED
%boost.common.attrib;>
<!ELEMENT free-function-group (function|overloaded-function)*>
<!ATTLIST free-function-group
name CDATA #REQUIRED
%boost.common.attrib;>
<!ELEMENT precondition ANY>
<!ATTLIST precondition %boost.common.attrib;>
<!ELEMENT code ANY>
<!ATTLIST code %boost.common.attrib;>
<!ELEMENT using-namespace EMPTY>
<!ATTLIST using-namespace
name CDATA #REQUIRED
%boost.common.attrib;>
<!ELEMENT using-class EMPTY>
<!ATTLIST using-class
name CDATA #REQUIRED
%boost.common.attrib;>
<!--========== Boost Testsuite Extensions ==========-->
<!ENTITY % boost.testsuite.tests
"compile-test|link-test|run-test|
compile-fail-test|link-fail-test|run-fail-test">
<!ENTITY % boost.testsuite.test.content
"source*, lib*, requirement*, purpose, if-fails?">
<!ELEMENT testsuite ((%boost.testsuite.tests;)+)>
<!ATTLIST testsuite %boost.common.attrib;>
<!ELEMENT compile-test (%boost.testsuite.test.content;)>
<!ATTLIST compile-test
filename CDATA #REQUIRED
name CDATA #IMPLIED>
<!ELEMENT link-test (%boost.testsuite.test.content;)>
<!ATTLIST link-test
filename CDATA #REQUIRED
name CDATA #IMPLIED>
<!ELEMENT run-test (%boost.testsuite.test.content;)>
<!ATTLIST run-test
filename CDATA #REQUIRED
name CDATA #IMPLIED>
<!ELEMENT compile-fail-test (%boost.testsuite.test.content;)>
<!ATTLIST compile-fail-test
filename CDATA #REQUIRED
name CDATA #IMPLIED>
<!ELEMENT link-fail-test (%boost.testsuite.test.content;)>
<!ATTLIST link-fail-test
filename CDATA #REQUIRED
name CDATA #IMPLIED>
<!ELEMENT run-fail-test (%boost.testsuite.test.content;)>
<!ATTLIST run-fail-test
filename CDATA #REQUIRED
name CDATA #IMPLIED>
<!ELEMENT source (#PCDATA|snippet)*>
<!ELEMENT snippet EMPTY>
<!ATTLIST snippet
name CDATA #REQUIRED>
<!ELEMENT lib (#PCDATA)>
<!ELEMENT requirement (#PCDATA)>
<!ATTLIST requirement
name CDATA #REQUIRED>
<!ELEMENT if-fails ANY>
<!ELEMENT parameter (paramtype, default?, description?)>
<!ATTLIST parameter
name CDATA #IMPLIED
pack CDATA #IMPLIED>
<!ELEMENT programlisting ANY>
<!ATTLIST programlisting
name CDATA #IMPLIED>
<!--========== Customize the DocBook DTD ==========-->
<!ENTITY % local.tech.char.class "|functionname|libraryname|enumname|headername|macroname|code">
<!ENTITY % local.para.class
"|using-namespace|using-class|librarylist|librarycategorylist">
<!ENTITY % local.descobj.class "|libraryinfo">
<!ENTITY % local.classname.attrib "alt CDATA #IMPLIED">
<!ENTITY % local.methodname.attrib "alt CDATA #IMPLIED">
<!ENTITY % local.refentry.class "|library-reference|testsuite">
<!ENTITY % local.title.char.mix "">
<!ENTITY % programlisting.module "IGNORE">
<!ENTITY % parameter.module "IGNORE">
<!ENTITY % function.module "IGNORE">
<!ENTITY % type.module "IGNORE">
<!--========== Import DocBook DTD ==========-->
<!ENTITY % DocBook PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
%DocBook;

View File

@@ -1,18 +1,18 @@
[section Consensus and Validation]
# Consensus and Validation
[*This section is a work in progress!!]
**This section is a work in progress!!**
Consensus is the task of reaching agreement within a distributed system in the
presence of faulty or even malicious participants. This document outlines the
[@https://ripple.com/files/ripple/consensus/whitepaper.pdf Ripple Consensus
Algorithm] as implemented in [@https://github.com/ripple/rippled rippled], but
[Ripple Consensus Algorithm](https://ripple.com/files/ripple/consensus/whitepaper.pdf)
as implemented in [rippled](https://github.com/ripple/rippled), but
focuses on its utility as a generic consensus algorithm independent of the
detailed mechanics of the Ripple Consensus Ledger. Most notably, the algorithm
does not require fully synchronous communication between all nodes in the
network, or even a fixed network topology, but instead achieves consensus via
collectively trusted subnetworks.
[heading Distributed Agreement]
## Distributed Agreement
A challenge for distributed systems is reaching agreement on changes in shared
state. For the Ripple network, the shared state is the current ledger--account
@@ -20,7 +20,7 @@ information, account balances, order books and other financial data. We will
refer to shared distributed state as a /ledger/ throughout the remainder of this
document.
[$images/consensus/ledger_chain.png [width 50%] [height 50%] ]
![Ledger Chain](images/consensus/ledger_chain.png "Ledger Chain")
As shown above, new ledgers are made by applying a set of transactions to the
prior ledger. For the Ripple network, transactions include payments,
@@ -33,14 +33,14 @@ the set of transactions to include, the order to apply those transactions, and
even the resulting ledger after applying the transactions. This is even more
difficult when some participants are faulty or malicious.
The Ripple network is a decentralized and _trust-full_ network. Anyone is free
The Ripple network is a decentralized and **trust-full** network. Anyone is free
to join and participants are free to choose a subset of peers that are
collectively trusted to not collude in an attempt to defraud the participant.
Leveraging this network of trust, the Ripple algorithm has two main components.
* /Consensus/ in which network participants agree on the transactions to apply
* *Consensus* in which network participants agree on the transactions to apply
to a prior ledger, based on the positions of their chosen peers.
* /Validation/ in which network participants agree on what ledger was
* *Validation* in which network participants agree on what ledger was
generated, based on the ledgers generated by chosen peers.
These phases are continually repeated to process transactions submitted to the
@@ -50,46 +50,46 @@ links between ledgers point backward to the parent. Also note the alternate
Ledger 2 that was generated by some participants, but which failed validation
and was abandoned.
[$images/consensus/block_chain.png]
![Block Chain](images/consensus/block_chain.png "Block Chain")
The remainder of this section describes the Consensus and Validation algorithms
in more detail and is meant as a companion guide to understanding the generic
implementation in =rippled=. The document *does not* discuss correctness,
implementation in `rippled`. The document **does not** discuss correctness,
fault-tolerance or liveness properties of the algorithms or the full details of
how they integrate within =rippled= to support the Ripple Consensus Ledger.
how they integrate within `rippled` to support the Ripple Consensus Ledger.
[section Consensus Overview]
## Consensus Overview
[heading Definitions]
### Definitions
* The /ledger/ is the shared distributed state. Each ledger has a unique ID to
distinguish it from all other ledgers. During consensus, the /previous/,
/prior/ or /last-closed/ ledger is the most recent ledger seen by consensus
* The *ledger* is the shared distributed state. Each ledger has a unique ID to
distinguish it from all other ledgers. During consensus, the *previous*,
*prior* or *last-closed* ledger is the most recent ledger seen by consensus
and is the basis upon which it will build the next ledger.
* A /transaction/ is an instruction for an atomic change in the ledger state. A
* A *transaction* is an instruction for an atomic change in the ledger state. A
unique ID distinguishes a transaction from other transactions.
* A /transaction set/ is a set of transactions under consideration by consensus.
* A *transaction set* is a set of transactions under consideration by consensus.
The goal of consensus is to reach agreement on this set. The generic
consensus algorithm does not rely on an ordering of transactions within the
set, nor does it specify how to apply a transaction set to a ledger to
generate a new ledger. A unique ID distinguishes a set of transactions from
all other sets of transactions.
* A /node/ is one of the distributed actors running the consensus algorithm. It
* A *node* is one of the distributed actors running the consensus algorithm. It
has a unique ID to distinguish it from all other nodes.
* A /peer/ of a node is another node that it has chosen to follow and which it
* A *peer* of a node is another node that it has chosen to follow and which it
believes will not collude with other chosen peers. The choice of peers is not
symmetric, since participants can decide on their chosen sets independently.
* A /position/ is the current belief of the next ledger's transaction set and
close time. Position can refer to the node's own position or the position of a
peer.
* A /proposal/ is one of a sequence of positions a node shares during consensus.
* A *proposal* is one of a sequence of positions a node shares during consensus.
An initial proposal contains the starting position taken by a node before it
considers any peer positions. If a node subsequently updates its position in
response to its peers, it will issue an updated proposal. A proposal is
uniquely identified by the ID of the proposing node, the ID of the position
taken, the ID of the prior ledger the proposal is for, and the sequence number
of the proposal.
* A /dispute/ is a transaction that is either not part of a node's position or
* A *dispute* is a transaction that is either not part of a node's position or
not in a peer's position. During consensus, the node will add or remove
disputed transactions from its position based on that transaction's support
amongst its peers.
@@ -101,61 +101,61 @@ contain the ID of the position of a peer. Since many peers likely have the same
position, this reduces the need to send the full transaction set multiple times.
Instead, a node can request the transaction set from the network if necessary.
[heading Overview ]
[$images/consensus/consensus_overview.png [width 50%] [height 50%] ]
### Overview
![Consensus Overview](images/consensus/consensus_overview.png "Consensus Overview")
The diagram above is an overview of the consensus process from the perspective
of a single participant. Recall that during a single consensus round, a node is
trying to agree with its peers on which transactions to apply to its prior
ledger when generating the next ledger. It also attempts to agree on the
[link effective_close_time network time when the ledger closed]. There are
[network time when the ledger closed](#effective_close_time). There are
3 main phases to a consensus round:
* A call to =startRound= places the node in the =Open= phase. In this phase,
* A call to `startRound` places the node in the `Open` phase. In this phase,
the node is waiting for transactions to include in its open ledger.
* At some point, the node will =Close= the open ledger and transition to the
=Establish= phase. In this phase, the node shares/receives peer proposals on
* At some point, the node will `Close` the open ledger and transition to the
`Establish` phase. In this phase, the node shares/receives peer proposals on
which transactions should be accepted in the closed ledger.
* At some point, the node determines it has reached consensus with its peers on
which transactions to include. It transitions to the =Accept= phase. In this
which transactions to include. It transitions to the `Accept` phase. In this
phase, the node works on applying the transactions to the prior ledger to
generate a new closed ledger. Once the new ledger is completed, the node shares
the validated ledger hash with the network and makes a call to =startRound= to
the validated ledger hash with the network and makes a call to `startRound` to
start the cycle again for the next ledger.
Throughout, a heartbeat timer calls =timerEntry= at a regular frequency to drive
the process forward. Although the =startRound= call occurs at arbitrary times
Throughout, a heartbeat timer calls `timerEntry` at a regular frequency to drive
the process forward. Although the `startRound` call occurs at arbitrary times
based on when the initial round began and the time it takes to apply
transactions, the transitions from =Open= to =Establish= and =Establish= to
=Accept= only occur during calls to =timerEntry=. Similarly, transactions can
transactions, the transitions from `Open` to `Establish` and `Establish` to
`Accept` only occur during calls to `timerEntry`. Similarly, transactions can
arrive at arbitrary times, independent of the heartbeat timer. Transactions
received after the =Open= to =Close= transition and not part of peer proposals
received after the `Open` to `Close` transition and not part of peer proposals
won't be considered until the next consensus round. They are represented above
by the light green triangles.
Peer proposals are issued by a node during a =timerEntry= call, but since peers
do not synchronize =timerEntry= calls, they are received by other peers at
Peer proposals are issued by a node during a `timerEntry` call, but since peers
do not synchronize `timerEntry` calls, they are received by other peers at
arbitrary times. Peer proposals are only considered if received prior to the
=Establish= to =Accept= transition, and only if the peer is working on the same
`Establish` to `Accept` transition, and only if the peer is working on the same
prior ledger. Peer proposals received after consensus is reached will not be
meaningful and are represented above by the circle with the X in it. Only
proposals from chosen peers are considered.
[#effective_close_time]
[heading Effective Close Time]
### Effective Close Time ### {#effective_close_time}
In addition to agreeing on a transaction set, each consensus round tries to
agree on the time the ledger closed. Each node calculates its own close time
when it closes the open ledger. This exact close time is rounded to the nearest
multiple of the current /effective close time resolution/. It is this
/effective close time/ that nodes seek to agree on. This allows servers to
multiple of the current *effective close time resolution*. It is this
*effective close time* that nodes seek to agree on. This allows servers to
derive a common time for a ledger without the need for perfectly synchronized
clocks. As depicted below, the 3 pink arrows represent exact close times from 3
consensus nodes that round to the same effective close time given the current
resolution. The purple arrow represents a peer whose estimate rounds to a
different effective close time given the current resolution.
[$images/consensus/EffCloseTime.png]
![Effective Close Time](images/consensus/EffCloseTime.png "Effective Close Time")
The effective close time is part of the node's position and is shared with peers
in its proposals. Just like the position on the consensus transaction set, a
@@ -168,14 +168,14 @@ subsequent consensus rounds if nodes are unable to reach consensus on an
effective close time and increasing (finer) resolution if nodes consistently
reach close time consensus.
[heading Modes]
### Modes
Internally, a node operates under one of the following consensus modes. Either
of the first two modes may be chosen when a consensus round starts.
* /Proposing/ indicates the node is a full-fledged consensus participant. It
* *Proposing* indicates the node is a full-fledged consensus participant. It
takes on positions and sends proposals to its peers.
* /Observing/ indicates the node is a passive consensus participant. It
* *Observing* indicates the node is a passive consensus participant. It
maintains a position internally, but does not propose that position to its
peers. Instead, it receives peer proposals and updates its position
to track the majority of its peers. This may be preferred if the node is only
@@ -184,21 +184,21 @@ of the first two modes may be chosen when a consensus round starts.
The other two modes are set internally during the consensus round when the node
believes it is no longer working on the dominant ledger chain based on peer
validations. It checks this on every call to =timerEntry=.
validations. It checks this on every call to `timerEntry`.
* /Wrong Ledger/ indicates the node is not working on the correct prior ledger
* *Wrong Ledger* indicates the node is not working on the correct prior ledger
and does not have it available. It requests that ledger from the network, but
continues to work towards consensus this round while waiting. If it had been
/proposing/, it will send a special "bowout" proposal to its peers to indicate
*proposing*, it will send a special "bowout" proposal to its peers to indicate
its change in mode for the rest of this round. For the duration of the round,
it defers to peer positions for determining the consensus outcome as if it
were just /observing/.
* /Switch Ledger/ indicates that the node has acquired the correct prior ledger
were just *observing*.
* *Switch Ledger* indicates that the node has acquired the correct prior ledger
from the network. Although it now has the correct prior ledger, the fact that
it had the wrong one at some point during this round means it is likely behind
and should defer to peer positions for determining the consensus outcome.
[$images/consensus/consensus_modes.png]
![Consensus Modes](images/consensus/consensus_modes.png "Consensus Modes")
Once either wrong ledger or switch ledger are reached, the node cannot
return to proposing or observing until the next consensus round. However,
@@ -212,49 +212,49 @@ time to share over the network, whereas the smaller ID could be shared in a peer
validation much more quickly. Distinguishing the two states allows the node to
decide how best to generate the next ledger once it declares consensus.
[heading Phases]
### Phases
As depicted in the overview diagram, consensus is best viewed as a progression
through 3 phases. There are 4 public methods of the generic consensus algorithm
that determine this progression
* =startRound= begins a consensus round.
* =timerEntry= is called at a regular frequency (=LEDGER_MIN_CLOSE=) and is the
only call to consensus that can change the phase from =Open= to =Establish=
or =Accept=.
* =peerProposal= is called whenever a peer proposal is received and is what
allows a node to update its position in a subsequent =timerEntry= call.
* =gotTxSet= is called when a transaction set is received from the network. This
* `startRound` begins a consensus round.
* `timerEntry` is called at a regular frequency (`LEDGER_MIN_CLOSE`) and is the
only call to consensus that can change the phase from `Open` to `Establish`
or `Accept`.
* `peerProposal` is called whenever a peer proposal is received and is what
allows a node to update its position in a subsequent `timerEntry` call.
* `gotTxSet` is called when a transaction set is received from the network. This
is typically in response to a prior request from the node to acquire the
transaction set corresponding to a disagreeing peer's position.
The following subsections describe each consensus phase in more detail and what
actions are taken in response to these calls.
[h6 Open]
#### Open
The =Open= phase is a quiescent period to allow transactions to build up in the
The `Open` phase is a quiescent period to allow transactions to build up in the
node's open ledger. The duration is a trade-off between latency and throughput.
A shorter window reduces the latency to generating the next ledger, but also
reduces transaction throughput due to fewer transactions accepted into the
ledger.
A call to =startRound= would forcibly begin the next consensus round, skipping
A call to `startRound` would forcibly begin the next consensus round, skipping
completion of the current round. This is not expected during normal operation.
Calls to =peerProposal= or =gotTxSet= simply store the proposal or transaction
set for use in the coming =Establish= phase.
Calls to `peerProposal` or `gotTxSet` simply store the proposal or transaction
set for use in the coming `Establish` phase.
A call to =timerEntry= first checks that the node is working on the correct
A call to `timerEntry` first checks that the node is working on the correct
prior ledger. If not, it will update the mode and request the correct ledger.
Otherwise, the node checks whether to switch to the =Establish= phase and close
Otherwise, the node checks whether to switch to the `Establish` phase and close
the ledger.
['Ledger Close]
##### Ledger Close
Under normal circumstances, the open ledger period ends when one of the following
is true
* if there are transactions in the open ledger and more than =LEDGER_MIN_CLOSE=
* if there are transactions in the open ledger and more than `LEDGER_MIN_CLOSE`
have elapsed. This is the typical behavior.
* if there are no open transactions and a suitably longer idle interval has
elapsed. This increases the opportunity to get some transaction into
@@ -275,48 +275,48 @@ transaction.
In the example below, we suppose our node has closed with transactions 1,2 and 3. It creates disputes
for transactions 2,3 and 4, since at least one peer position differs on each.
[#disputes_image]
[$images/consensus/disputes.png [width 20%] [height 20%]]
##### disputes ##### {#disputes_image}
![Disputes](images/consensus/disputes.png "Disputes")
[h6 Establish]
#### Establish
The establish phase is the active period of consensus in which the node
exchanges proposals with peers in an attempt to reach agreement on the consensus
transactions and effective close time.
A call to =startRound= would forcibly begin the next consensus round, skipping
A call to `startRound` would forcibly begin the next consensus round, skipping
completion of the current round. This is not expected during normal operation.
Calls to =peerProposal= or =gotTxSet= that reflect new positions will generate
Calls to `peerProposal` or `gotTxSet` that reflect new positions will generate
disputed transactions for any new disagreements and will update the peer's vote
for all disputed transactions.
A call to =timerEntry= first checks that the node is working from the correct
A call to `timerEntry` first checks that the node is working from the correct
prior ledger. If not, the node will update the mode and request the correct
ledger. Otherwise, the node updates the node's position and considers whether
to switch to the =Accepted= phase and declare consensus reached. However, at
least =LEDGER_MIN_CONSENSUS= time must have elapsed before doing either. This
to switch to the `Accepted` phase and declare consensus reached. However, at
least `LEDGER_MIN_CONSENSUS` time must have elapsed before doing either. This
allows peers an opportunity to take an initial position and share it.
['Update Position]
##### Update Position
In order to achieve consensus, the node is looking for a transaction set that is
supported by a super-majority of peers. The node works towards this set by
adding or removing disputed transactions from its position based on an
increasing threshold for inclusion.
[$images/consensus/threshold.png [width 50%] [height 50%]]
![Threshold](images/consensus/threshold.png "Threshold")
By starting with a lower threshold, a node initially allows a wide set of
transactions into its position. If the establish round continues and the node is
"stuck", a higher threshold can focus on accepting transactions with the most
support. The constants that define the thresholds and durations at which the
thresholds change are given by `AV_XXX_CONSENSUS_PCT` and
`AV_XXX_CONSENSUS_TIME` respectively, where =XXX= is =INIT=,=MID=,=LATE= and
=STUCK=. The effective close time position is updated using the same
`AV_XXX_CONSENSUS_TIME` respectively, where `XXX` is `INIT`,`MID`,`LATE` and
`STUCK`. The effective close time position is updated using the same
thresholds.
Given the [link disputes_image example disputes above] and an initial threshold
Given the [example disputes above](#disputes_image) and an initial threshold
of 50%, our node would retain its position since transaction 1 was not in
dispute and transactions 2 and 3 have 75% support. Since its position did not
change, it would not need to send a new proposal to peers. Peer C would not
@@ -333,7 +333,7 @@ Lastly, if our node were not in the proposing mode, it would not include its own
vote and just take the majority (>50%) position of its peers. In this example,
our node would maintain its position of transactions 1, 2 and 3.
['Checking Consensus]
##### Checking Consensus
After updating its position, the node checks for supermajority agreement with
its peers on its current position. This agreement is of the exact transaction
@@ -347,11 +347,11 @@ Consensus is declared when the following 3 clauses are true:
* `LEDGER_MIN_CONSENSUS` time has elapsed in the establish phase
* At least 75% of the prior round proposers have proposed OR this establish
phase is `LEDGER_MIN_CONSENSUS` longer than the last round's establish phase
* =minimumConsensusPercentage= of ourself and our peers share the same position
* `minimumConsensusPercentage` of ourself and our peers share the same position
The middle condition ensures slower peers have a chance to share positions, but
prevents waiting too long on peers that have disconnected. Additionally, a node
can declare that consensus has moved on if =minimumConsensusPercentage= peers
can declare that consensus has moved on if `minimumConsensusPercentage` peers
have sent validations and moved on to the next ledger. This outcome indicates
the node has fallen behind its peers and needs to catch up.
@@ -359,45 +359,43 @@ If a node is not proposing, it does not include its own position when
calculating the percent of agreeing participants but otherwise follows the above
logic.
['Accepting Consensus]
##### Accepting Consensus
Once consensus is reached (or moved on), the node switches to the =Accept= phase
Once consensus is reached (or moved on), the node switches to the `Accept` phase
and signals to the implementing code that the round is complete. That code is
responsible for using the consensus transaction set to generate the next ledger
and calling =startRound= to begin the next round. The implementation has total
and calling `startRound` to begin the next round. The implementation has total
freedom on ordering transactions, deciding what to do if consensus moved on,
determining whether to retry or abandon local transactions that did not make the
consensus set and updating any internal state based on the consensus progress.
#### Accept
[h6 Accept]
The =Accept= phase is the terminal phase of the consensus algorithm. Calls to
=timerEntry=, =peerProposal= and =gotTxSet= will not change the internal
The `Accept` phase is the terminal phase of the consensus algorithm. Calls to
`timerEntry`, `peerProposal` and `gotTxSet` will not change the internal
consensus state while in the accept phase. The expectation is that the
application specific code is working to generate the new ledger based on the
consensus outcome. Once complete, that code should make a call to =startRound=
to kick off the next consensus round. The =startRound= call includes the new
consensus outcome. Once complete, that code should make a call to `startRound`
to kick off the next consensus round. The `startRound` call includes the new
prior ledger, prior ledger ID and whether the round should begin in the
proposing or observing mode. After setting some initial state, the phase
transitions to =Open=. The node will also check if the provided prior ledger
transitions to `Open`. The node will also check if the provided prior ledger
and ID are correct, updating the mode and requesting the proper ledger from the
network if necessary.
[endsect] [/Consensus Overview]
[section Consensus Type Requirements]
## Consensus Type Requirements
The consensus type requirements are given below as minimal implementation stubs.
Actual implementations would augment these stubs with members appropriate for
managing the details of transactions and ledgers within the larger application
framework.
[heading Transaction]
The transaction type =Tx= encapsulates a single transaction under consideration
### Transaction
The transaction type `Tx` encapsulates a single transaction under consideration
by consensus.
```
```{.cpp}
struct Tx
{
using ID = ...;
@@ -407,13 +405,14 @@ struct Tx
};
```
[heading Transaction Set]
The transaction set type =TxSet= represents a set of [^Tx]s that are collectively
under consideration by consensus. A =TxSet= can be compared against other [^TxSet]s
### Transaction Set
The transaction set type `TxSet` represents a set of `Tx`s that are collectively
under consideration by consensus. A `TxSet` can be compared against other `TxSet`s
(typically from peers) and can be modified to add or remove transactions via
the mutable subtype.
```
```{.cpp}
struct TxSet
{
using Tx = Tx;
@@ -446,14 +445,16 @@ struct TxSet
};
```
[heading Ledger] The =Ledger= type represents the state shared amongst the
### Ledger
The `Ledger` type represents the state shared amongst the
distributed participants. Notice that the details of how the next ledger is
generated from the prior ledger and the consensus accepted transaction set is
not part of the interface. Within the generic code, this type is primarily used
to know that peers are working on the same tip of the ledger chain and to
provide some basic timing data for consensus.
```
```{.cpp}
struct Ledger
{
using ID = ...;
@@ -483,10 +484,13 @@ struct Ledger
};
```
[heading PeerProposal] The =PeerProposal= type represents the signed position taken
### PeerProposal
The `PeerProposal` type represents the signed position taken
by a peer during consensus. The only type requirement is owning an instance of a
generic =ConsensusProposal=.
```
generic `ConsensusProposal`.
```{.cpp}
// Represents our proposed position or a peer's proposed position
// and is provided with the generic code
template <class NodeID_t, class LedgerID_t, class Position_t> class ConsensusProposal;
@@ -502,15 +506,16 @@ struct PeerPosition
// ... implementation specific
};
```
[heading Generic Consensus Interface]
The generic =Consensus= relies on =Adaptor= template class to implement a set
### Generic Consensus Interface
The generic `Consensus` relies on `Adaptor` template class to implement a set
of helper functions that plug the consensus algorithm into a specific application.
The =Adaptor= class also defines the types above needed by the algorithm. Below
The `Adaptor` class also defines the types above needed by the algorithm. Below
are excerpts of the generic consensus implementation and of helper types that will
interact with the concrete implementing class.
```
```{.cpp}
// Represents a transction under dispute this round
template <class Tx_t, class NodeID_t> class DisputedTx;
@@ -583,11 +588,12 @@ public:
// ... details
};
```
[heading Adapting Generic Consensus]
### Adapting Generic Consensus
The stub below shows the set of callback/helper functions required in the implementing class.
```
```{.cpp}
struct Adaptor
{
using Ledger_t = Ledger;
@@ -651,30 +657,27 @@ struct Adaptor
The implementing class hides many details of the peer communication
model from the generic code.
* The =share= member functions are responsible for sharing the given type with a
* The `share` member functions are responsible for sharing the given type with a
node's peers, but are agnostic to the mechanism. Ideally, messages are delivered
faster than =LEDGER_GRANULARITY=.
faster than `LEDGER_GRANULARITY`.
* The generic code does not specify how transactions are submitted by clients,
propagated through the network or stored in the open ledger. Indeed, the open
ledger is only conceptual from the perspective of the generic code---the
initial position and transaction set are opaquely generated in a
`Consensus::Result` instance returned from the =onClose= callback.
* The calls to =acquireLedger= and =acquireTxSet= only have non-trivial return
`Consensus::Result` instance returned from the `onClose` callback.
* The calls to `acquireLedger` and `acquireTxSet` only have non-trivial return
if the ledger or transaction set of interest is available. The implementing
class is free to block while acquiring, or return the empty option while
servicing the request asynchronously. Due to legacy reasons, the two calls
are not symmetric. =acquireTxSet= requires the host application to call
=gotTxSet= when an asynchronous =acquire= completes. Conversely,
=acquireLedger= will be called again later by the consensus code if it still
are not symmetric. `acquireTxSet` requires the host application to call
`gotTxSet` when an asynchronous `acquire` completes. Conversely,
`acquireLedger` will be called again later by the consensus code if it still
desires the ledger with the hope that the asynchronous acquisition is
complete.
[endsect] [/Consensus Type Requirements]
[section Validation]
## Validation
Coming Soon!
[endsect] [/Validation]
[endsect] [/Consensus and Validation]

Submodule docs/docca deleted from 335dbf9c36

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.9 KiB

After

Width:  |  Height:  |  Size: 13 KiB

BIN
docs/images/flow1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 180 KiB

BIN
docs/images/flow2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 143 KiB

BIN
docs/images/ripple.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

View File

@@ -1,14 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "boostbook.dtd">
<!--
Copyright (c) 2013-2016 Vinnie Falco (vinnie dot falco at gmail dot com)
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
-->
<section id="rippled.index">
<title>Index</title>
<index/>
</section>

View File

@@ -1,39 +0,0 @@
[/
Copyright (c) Copyright (c) 2012-2017 Ripple Labs Inc.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
]
[library rippled
[quickbook 1.6]
[copyright 2012 - 2017 Ripple Labs Inc.]
[purpose C++ Library]
[license
Distributed under the ISC License
]
[authors [Labs, Ripple]]
[category template]
[category generic]
]
[template mdash[] '''&mdash; ''']
[template indexterm1[term1] '''<indexterm><primary>'''[term1]'''</primary></indexterm>''']
[template indexterm2[term1 term2] '''<indexterm><primary>'''[term1]'''</primary><secondary>'''[term2]'''</secondary></indexterm>''']
[include consensus.qbk]
[section:ref Reference]
[include temp/reference.qbk]
[endsect]
[xinclude index.xml]

View File

@@ -1,11 +0,0 @@
#!/bin/bash
# Copyright (c) 2013-2016 Vinnie Falco (vinnie dot falco at gmail dot com)
#
# Distributed under the Boost Software License, Version 1.0. (See accompanying
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
mkdir -p temp
doxygen source.dox
xsltproc temp/combine.xslt temp/index.xml > temp/all.xml
xsltproc reference.xsl temp/all.xml > temp/reference.qbk

View File

@@ -1,61 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "boostbook.dtd">
<!--
Copyright (c) Copyright (c) 2012, 2013 Ripple Labs Inc.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-->
<informaltable frame="all">
<tgroup cols="3">
<colspec colname="a"/>
<colspec colname="b"/>
<colspec colname="c"/>
<thead>
<row>
<entry valign="center" namest="a" nameend="c">
<bridgehead renderas="sect2">Core</bridgehead>
</entry>
</row>
</thead>
<tbody>
<row>
<entry valign="top">
<bridgehead renderas="sect3">Classes</bridgehead>
<simplelist type="vert" columns="1">
</simplelist>
<bridgehead renderas="sect3">Constants</bridgehead>
<simplelist type="vert" columns="1">
</simplelist>
</entry>
<entry valign="top">
<bridgehead renderas="sect3">Functions</bridgehead>
<simplelist type="vert" columns="1">
</simplelist>
<bridgehead renderas="sect3">Type Traits</bridgehead>
<simplelist type="vert" columns="1">
</simplelist>
</entry>
<entry valign="top">
<bridgehead renderas="sect3">Types</bridgehead>
<simplelist type="vert" columns="1">
</simplelist>
<bridgehead renderas="sect3">Concepts</bridgehead>
<simplelist type="vert" columns="1">
</simplelist>
</entry>
</row>
</tbody>
</tgroup>
</informaltable>

View File

@@ -1,14 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<!-- Variables (Edit for your project) -->
<xsl:variable name="doc-ref" select="'rippled.ref.'"/>
<xsl:variable name="doc-ns" select="'ripple'"/>
<xsl:variable name="debug" select="0"/>
<xsl:variable name="private" select="0"/>
<!-- End Variables -->
<xsl:include href="docca/include/docca/doxygen.xsl"/>
</xsl:stylesheet>

24
docs/sample_chart.doc Normal file
View File

@@ -0,0 +1,24 @@
/*!
\page somestatechart Example state diagram
\startuml SomeState "my state diagram"
scale 600 width
[*] -> State1
State1 --> State2 : Succeeded
State1 --> [*] : Aborted
State2 --> State3 : Succeeded
State2 --> [*] : Aborted
state State3 {
state "Accumulate Enough Data\nLong State Name" as long1
long1 : Just a test
[*] --> long1
long1 --> long1 : New Data
long1 --> ProcessData : Enough Data
}
State3 --> State3 : Failed
State3 --> [*] : Succeeded / Save Result
State3 --> [*] : Aborted
\enduml
*/

View File

@@ -6,6 +6,7 @@ PROJECT_NAME = "rippled"
PROJECT_NUMBER =
PROJECT_BRIEF = C++ Library
PROJECT_LOGO =
PROJECT_LOGO = images/LogoForDocumentation.png
OUTPUT_DIRECTORY =
CREATE_SUBDIRS = NO
ALLOW_UNICODE_NAMES = NO
@@ -125,6 +126,41 @@ INPUT = \
../src/ripple/app/tx/applySteps.h \
../src/ripple/app/tx/impl/InvariantCheck.h \
../src/ripple/app/consensus/RCLValidations.h \
../src/README.md \
../src/ripple/README.md \
../README.md \
../RELEASENOTES.md \
../docs/CodingStyle.md \
../docs/CheatSheet.md \
../docs/README.md \
../docs/sample_chart.doc \
../docs/HeapProfiling.md \
../docs/Docker.md \
../docs/consensus.md \
../Builds/XCode/README.md \
../Builds/VisualStudio2015/README.md \
../src/ripple/consensus/README.md \
../src/ripple/app/consensus/README.md \
../src/test/csf/README.md \
../src/ripple/basics/README.md \
../src/ripple/crypto/README.md \
../src/ripple/peerfinder/README.md \
../src/ripple/app/misc/README.md \
../src/ripple/app/misc/FeeEscalation.md \
../src/ripple/app/ledger/README.md \
../src/ripple/app/paths/README.md \
../src/ripple/app/tx/README.md \
../src/ripple/proto/README.md \
../src/ripple/shamap/README.md \
../src/ripple/protocol/README.md \
../src/ripple/json/README.md \
../src/ripple/json/TODO.md \
../src/ripple/resource/README.md \
../src/ripple/rpc/README.md \
../src/ripple/overlay/README.md \
../src/ripple/nodestore/README.md \
../src/ripple/nodestore/Benchmarks.md \
INPUT_ENCODING = UTF-8
FILE_PATTERNS =
@@ -136,12 +172,16 @@ EXCLUDE_SYMBOLS =
EXAMPLE_PATH =
EXAMPLE_PATTERNS =
EXAMPLE_RECURSIVE = NO
IMAGE_PATH =
IMAGE_PATH = \
./images/ \
./images/consensus/ \
../src/test/csf/ \
INPUT_FILTER =
FILTER_PATTERNS =
FILTER_SOURCE_FILES = NO
FILTER_SOURCE_PATTERNS =
USE_MDFILE_AS_MAINPAGE =
USE_MDFILE_AS_MAINPAGE = ../src/README.md
#---------------------------------------------------------------------------
# Configuration options related to source browsing
@@ -168,8 +208,8 @@ IGNORE_PREFIX =
#---------------------------------------------------------------------------
# Configuration options related to the HTML output
#---------------------------------------------------------------------------
GENERATE_HTML = NO
HTML_OUTPUT = dhtm
GENERATE_HTML = YES
HTML_OUTPUT = html_doc
HTML_FILE_EXTENSION = .html
HTML_HEADER =
HTML_FOOTER =
@@ -269,8 +309,8 @@ MAN_LINKS = NO
#---------------------------------------------------------------------------
# Configuration options related to the XML output
#---------------------------------------------------------------------------
GENERATE_XML = YES
XML_OUTPUT = temp/
GENERATE_XML = NO
XML_OUTPUT = temp
XML_PROGRAMLISTING = YES
#---------------------------------------------------------------------------
@@ -346,7 +386,7 @@ DOT_PATH =
DOTFILE_DIRS =
MSCFILE_DIRS =
DIAFILE_DIRS =
PLANTUML_JAR_PATH =
PLANTUML_JAR_PATH = $(PLANTUML_JAR)
PLANTUML_INCLUDE_PATH =
DOT_GRAPH_MAX_NODES = 50
MAX_DOT_GRAPH_DEPTH = 0