mirror of
https://github.com/fluencelabs/tendermint
synced 2025-07-24 08:41:59 +00:00
Compare commits
523 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
c64a3c74c8 | ||
|
722f8a1b6f | ||
|
d903057011 | ||
|
74106c8bea | ||
|
94006855d1 | ||
|
a963af4c46 | ||
|
a1400aee73 | ||
|
789666ef78 | ||
|
c66e1514de | ||
|
a163f08e4e | ||
|
9b0b0b02d0 | ||
|
5439da6323 | ||
|
9703a8825d | ||
|
9035546884 | ||
|
aff063b79b | ||
|
66c4f7aeae | ||
|
262c8daa04 | ||
|
1dbe7b7e68 | ||
|
93a3f701fe | ||
|
e46ae15859 | ||
|
75c9303c68 | ||
|
bd050c1d03 | ||
|
3ffda994c2 | ||
|
6a85aecfb7 | ||
|
d103aaf53f | ||
|
17e1df0cbd | ||
|
ff8ddee708 | ||
|
20bb522592 | ||
|
715ec19c96 | ||
|
d51b196992 | ||
|
5a4459935b | ||
|
3132f7fad4 | ||
|
80399e60fb | ||
|
b271c40783 | ||
|
37ce4e549e | ||
|
e4db5f8dcd | ||
|
6fe8ea966a | ||
|
1377ef1e1f | ||
|
95980d944b | ||
|
7a7f5782bc | ||
|
e785d6851c | ||
|
f04a087546 | ||
|
94c8dd1c55 | ||
|
bbf2bd1d81 | ||
|
4f7fac8076 | ||
|
a3640ef809 | ||
|
1034a35b3a | ||
|
f9ae7730fe | ||
|
b980ef8bea | ||
|
50ea68a426 | ||
|
f5ad8ef860 | ||
|
8ce588d984 | ||
|
2aa2b63cad | ||
|
17c924de7e | ||
|
ebe97d3956 | ||
|
44dad6d70b | ||
|
2f4ab0c068 | ||
|
65487586f8 | ||
|
d02c5d1e30 | ||
|
9d81a74429 | ||
|
e8127456ca | ||
|
db419a308e | ||
|
48e1227f92 | ||
|
3b461bfbe9 | ||
|
2bcd7e5962 | ||
|
b7925cd34f | ||
|
c3769b88e4 | ||
|
65b479dd65 | ||
|
7eb2674e2b | ||
|
e79b642d8d | ||
|
47256cfda2 | ||
|
a12785aa60 | ||
|
95e3e7afcd | ||
|
399c7ea8ed | ||
|
a7d695408a | ||
|
a28fdfd3a8 | ||
|
851232d1b5 | ||
|
7fac16dc7f | ||
|
80e6e0fa05 | ||
|
52d3eca67c | ||
|
ab9881471a | ||
|
8b5c692a6a | ||
|
603d173b87 | ||
|
92102a84dc | ||
|
a88ccb9396 | ||
|
1b51cbc224 | ||
|
fec8de831a | ||
|
7d00575898 | ||
|
3d333f5cac | ||
|
63deea9675 | ||
|
a66b20aff4 | ||
|
34896f2988 | ||
|
8f741b44d6 | ||
|
4bffda0dc2 | ||
|
5a211ff791 | ||
|
d831b443da | ||
|
aa40f8a868 | ||
|
2912f40f8e | ||
|
efb8f6fc1f | ||
|
62965e68f1 | ||
|
585b163d94 | ||
|
4a03eb7baf | ||
|
445ddbf040 | ||
|
664d4ebf4c | ||
|
2f1c7a3646 | ||
|
0e09c09c30 | ||
|
9a2935cff6 | ||
|
8833335948 | ||
|
d73a7397b5 | ||
|
043ba85a9e | ||
|
df704e99b1 | ||
|
2914b73e30 | ||
|
858cad05f1 | ||
|
d42a308887 | ||
|
358f7ad8e9 | ||
|
0d8ca4ec10 | ||
|
5cb7e151fb | ||
|
426938e2b4 | ||
|
2429cfb2b7 | ||
|
7d414cb7b2 | ||
|
e893f9bc1f | ||
|
71e133553e | ||
|
82106913f1 | ||
|
0192e101ce | ||
|
a7c9de49c0 | ||
|
77cbccdd55 | ||
|
de4022dcce | ||
|
e3d403e6b7 | ||
|
e31150398e | ||
|
1eb7a8a2cc | ||
|
9bd1f28b8d | ||
|
ffb806f2b2 | ||
|
af30cef574 | ||
|
73a4cfb06a | ||
|
c6190b3859 | ||
|
1f3e1eec83 | ||
|
b3a14da617 | ||
|
c00faa8960 | ||
|
1d10217df2 | ||
|
91ce3af564 | ||
|
d8dd7491e2 | ||
|
f297602c14 | ||
|
cbfbc72ad8 | ||
|
9692f68d50 | ||
|
6680240fbe | ||
|
85710237fd | ||
|
d5ffce28fd | ||
|
9620e36ed7 | ||
|
1644773e69 | ||
|
8879640901 | ||
|
02afeba9fa | ||
|
6f77e1cec4 | ||
|
705bf7dd1f | ||
|
38b3cfafb8 | ||
|
39e354e12e | ||
|
c245768377 | ||
|
c36867e971 | ||
|
9ffbb92e1a | ||
|
1ade893555 | ||
|
62c6b48277 | ||
|
2a0fbdfc97 | ||
|
3905c11934 | ||
|
5efc536ba3 | ||
|
30d602d6ed | ||
|
5dd6fbcd04 | ||
|
5c74dd7f5b | ||
|
e77e5d013a | ||
|
c36ba95cf7 | ||
|
8bfb54d1aa | ||
|
4b7260cdc5 | ||
|
ae85a7ae41 | ||
|
dd5f81e430 | ||
|
a1d529e5cf | ||
|
ce6eab5ea9 | ||
|
20576cab5f | ||
|
862d7eb82c | ||
|
32ead683ce | ||
|
bbe151c1d2 | ||
|
060091402b | ||
|
b1d433314b | ||
|
8e0ed4ddd0 | ||
|
45021f017b | ||
|
cc45151c4d | ||
|
c0e373bad0 | ||
|
95048b21b2 | ||
|
639aedd5a1 | ||
|
43c86c2a9c | ||
|
7aa0957fc5 | ||
|
e0fbe6fb3e | ||
|
51d74ebdfa | ||
|
7872ade626 | ||
|
f152658f6c | ||
|
a754009f6b | ||
|
6544b4fb77 | ||
|
8869363697 | ||
|
38d51cf9cd | ||
|
f73b089e3f | ||
|
94ed32b80d | ||
|
47931208b5 | ||
|
f927f0a736 | ||
|
43f8ea58ba | ||
|
4c4a945658 | ||
|
769c7d015e | ||
|
989ff83c4c | ||
|
9708c66576 | ||
|
cd7666c4ce | ||
|
76da726d2a | ||
|
279d6a0ebb | ||
|
45a7ae2e62 | ||
|
cd5173f9a5 | ||
|
e1e50843ed | ||
|
9667e027f3 | ||
|
42f58ceb4b | ||
|
081bd0805e | ||
|
877e8e31f7 | ||
|
330f38a77a | ||
|
af04238bb9 | ||
|
d294200176 | ||
|
34fe5274e0 | ||
|
28c248f747 | ||
|
38f321f843 | ||
|
4dfe77416a | ||
|
2c2164c0ca | ||
|
621b67e145 | ||
|
728ac86ab1 | ||
|
697b71ee8d | ||
|
12baa7c1c5 | ||
|
7e81a89919 | ||
|
7e6df2fce4 | ||
|
9a971d8a19 | ||
|
28e9a0addd | ||
|
a0d21cef7d | ||
|
e105b10fc8 | ||
|
eb3f6e65a0 | ||
|
9ff1bd8c9c | ||
|
5109f89516 | ||
|
f3c02f587b | ||
|
42394aec2b | ||
|
85e562004c | ||
|
94a5087e0f | ||
|
6e2caf5a06 | ||
|
83f49f0dff | ||
|
f9ae600a61 | ||
|
23ad16b90e | ||
|
94f0c7449a | ||
|
b818d98875 | ||
|
8f657f8862 | ||
|
6848f8b407 | ||
|
7dc7109dc9 | ||
|
2cad2d22fd | ||
|
94c721641c | ||
|
99ac80f39b | ||
|
d9824c1cc4 | ||
|
b08326cb3b | ||
|
3f55cc3430 | ||
|
be9c7fce9c | ||
|
e8d2c0b0db | ||
|
4f47a762a0 | ||
|
961e936100 | ||
|
87724cc451 | ||
|
9dc43e0d1c | ||
|
f1ae1ec8f9 | ||
|
00a0f4e6c4 | ||
|
bed33467b1 | ||
|
96828217c3 | ||
|
dfee48fcff | ||
|
92869b5b35 | ||
|
2055ae2e2a | ||
|
7146619aa8 | ||
|
191b2301a1 | ||
|
8f438fa893 | ||
|
69cfb9c88e | ||
|
8aeb5a98bd | ||
|
bb2bfbc22a | ||
|
1b1462607b | ||
|
555d591c80 | ||
|
63ba27f186 | ||
|
b6a7dc4832 | ||
|
717c612ba7 | ||
|
3485cac7fb | ||
|
cad2b3ce5a | ||
|
b6bc56e906 | ||
|
e9918a7323 | ||
|
d46b5db056 | ||
|
b64a323da7 | ||
|
6890cd2ae5 | ||
|
38846aebfe | ||
|
212df60671 | ||
|
6bfcc917ad | ||
|
e6ed8e70ac | ||
|
36db612249 | ||
|
76fbcadf2b | ||
|
a05c3ceb46 | ||
|
f87edb756f | ||
|
cfc1b4f426 | ||
|
8dd9f653f4 | ||
|
9bbe30d9ff | ||
|
fec7af121a | ||
|
4240e60612 | ||
|
fa3864c226 | ||
|
d205ae1f98 | ||
|
9181822f65 | ||
|
9f65485b62 | ||
|
7ab861358a | ||
|
5f500ec891 | ||
|
b7dbf4a528 | ||
|
f7e1cb79ee | ||
|
464b404f48 | ||
|
6598719e7f | ||
|
d6e81ff27c | ||
|
ca9bad2b04 | ||
|
86e9e7d7c5 | ||
|
e2f9ffb7ff | ||
|
feeffc7836 | ||
|
006ed44e48 | ||
|
150902a566 | ||
|
0ea3e33049 | ||
|
d6e2d90d56 | ||
|
e67b298cef | ||
|
73ced040a3 | ||
|
d7c936abfa | ||
|
773f7aac5b | ||
|
e212bf1aa0 | ||
|
dcb86f4d12 | ||
|
55c0a79aa6 | ||
|
bc398a5859 | ||
|
4cb362d625 | ||
|
b6af7e78d8 | ||
|
22fb175d62 | ||
|
3c1a1a8bf5 | ||
|
1e033b6051 | ||
|
4a9d237c8e | ||
|
eeab55dc07 | ||
|
516e872346 | ||
|
f529684277 | ||
|
aff0fe5c5c | ||
|
d0b990bfdd | ||
|
f46d0444e1 | ||
|
a607ff5789 | ||
|
88b4ca3bc3 | ||
|
cb45f21888 | ||
|
27643cd9f9 | ||
|
620713de77 | ||
|
b2c3951c5c | ||
|
1c5e36725f | ||
|
ccf13fae0c | ||
|
54a9364565 | ||
|
7942f216fc | ||
|
f0c733ccbd | ||
|
be8b7124aa | ||
|
d268b1558e | ||
|
db4bba72a2 | ||
|
e7a96b469a | ||
|
213833d9e2 | ||
|
9b8e2ece03 | ||
|
f67b87b548 | ||
|
7736585d46 | ||
|
f65977b019 | ||
|
d9a9dcf757 | ||
|
b715d3caf7 | ||
|
f38703a9f4 | ||
|
08bb01cb55 | ||
|
35525d5281 | ||
|
8896959014 | ||
|
2af729727f | ||
|
856e428057 | ||
|
f1e2f0a1f6 | ||
|
f66e92d5fb | ||
|
fba994d5ba | ||
|
065bd80846 | ||
|
59ac3973d3 | ||
|
e280cbdead | ||
|
2efdd069c6 | ||
|
cb8e2e46d0 | ||
|
2c1261c3b7 | ||
|
1cea4dd43f | ||
|
6398aa7b5a | ||
|
a789923d73 | ||
|
78ddcc08e1 | ||
|
571cebc826 | ||
|
993c016b70 | ||
|
103e339dec | ||
|
3e4259e264 | ||
|
01aebbb6ee | ||
|
c30893d867 | ||
|
9a0629564a | ||
|
08a079ce16 | ||
|
7239e41c4a | ||
|
c996b13dae | ||
|
e3d43c8d45 | ||
|
75fa12cabf | ||
|
76f4a964e4 | ||
|
a758baf37e | ||
|
f29a97c4df | ||
|
72169b0bc1 | ||
|
c8778ff790 | ||
|
e14cbf3cca | ||
|
aa3ec15dc4 | ||
|
1494c953e3 | ||
|
7fc429b72f | ||
|
eaa3fa28ed | ||
|
92f10e9206 | ||
|
d184ca1432 | ||
|
86d999a4e9 | ||
|
9577fb0ca4 | ||
|
44613da2b0 | ||
|
1ce930157f | ||
|
b25e2b4eeb | ||
|
92438185fc | ||
|
ee74f9a3a8 | ||
|
07baf56cde | ||
|
ab5802a50f | ||
|
457516b194 | ||
|
4e16ee6d78 | ||
|
f427590622 | ||
|
7587726f6e | ||
|
f62aae63de | ||
|
62e6344473 | ||
|
fb457c2c9c | ||
|
e1f268b9d2 | ||
|
3d5abdc3bd | ||
|
76e18e7eba | ||
|
309812389a | ||
|
1c1fbcd70f | ||
|
ec2e1d4460 | ||
|
f53fb46302 | ||
|
d07e164796 | ||
|
35a2a58ac0 | ||
|
3b96458416 | ||
|
c94c1ff89a | ||
|
294292f586 | ||
|
4911c66b6d | ||
|
667e92e635 | ||
|
aa0fa0e6d8 | ||
|
19e332840b | ||
|
649a485275 | ||
|
4c4bce9469 | ||
|
121926d898 | ||
|
5e5968801c | ||
|
4750dbba77 | ||
|
5e56b2ea0e | ||
|
f33edeb23a | ||
|
a8d530dfda | ||
|
b552974a09 | ||
|
b708e91bce | ||
|
eee17f2a5c | ||
|
05e6a730eb | ||
|
9442a069a3 | ||
|
ed9dda0c17 | ||
|
115b1505f7 | ||
|
5a9d14f025 | ||
|
d00b637959 | ||
|
de94e9b4ea | ||
|
7522dea243 | ||
|
08166b05f5 | ||
|
14b0589d6b | ||
|
31ee29d2f0 | ||
|
3044f66ba9 | ||
|
c053c15231 | ||
|
6e00ce9bbd | ||
|
dee06a92d9 | ||
|
06e5b8c2df | ||
|
a83c27a282 | ||
|
1c8496406a | ||
|
81dbd7afc5 | ||
|
7d95b5232f | ||
|
4ae36d4e76 | ||
|
c8e0eca7e5 | ||
|
101418cf75 | ||
|
a6130910bf | ||
|
68b07b9c97 | ||
|
674d1d3e1b | ||
|
f36d60552f | ||
|
7ee9bb4ea2 | ||
|
8af2fe79e1 | ||
|
da08d589b5 | ||
|
fb28fd4c13 | ||
|
31a54b0840 | ||
|
ce69eaa75e | ||
|
4be0a1017b | ||
|
df98d5e1af | ||
|
4bcf61129d | ||
|
4f39f0be48 | ||
|
f7f64a58d6 | ||
|
6a30f422ce | ||
|
975807c744 | ||
|
1a65dbebb9 | ||
|
5c9ec9344a | ||
|
fd3dc5f5a7 | ||
|
315dcd449b | ||
|
5406622a64 | ||
|
201c8864b6 | ||
|
09eb442de7 | ||
|
94b8e28b21 | ||
|
11230b8aea | ||
|
069c870614 | ||
|
8c6ae55bd0 | ||
|
d3b54b204f | ||
|
ee4f8c2ab2 | ||
|
60cea4415b | ||
|
5f721bcfa0 | ||
|
1b81863ef7 | ||
|
82882bf7c2 | ||
|
bb72373f30 | ||
|
0925afcd18 | ||
|
75d31daacd | ||
|
b6090ad183 | ||
|
8b735b36be | ||
|
0825aa5d64 | ||
|
d52f690e56 | ||
|
2b3fc11697 | ||
|
bfbfb646b9 | ||
|
bb52f23ff6 | ||
|
85874a3765 | ||
|
ec8fd017a5 | ||
|
b7be9208fd | ||
|
de1d5f6353 | ||
|
1af021846e | ||
|
673e346ba4 | ||
|
e6e9f3ac6b | ||
|
d835cfe3e7 | ||
|
1b8aacd2ee | ||
|
a24a364fb3 |
7
.gitignore
vendored
7
.gitignore
vendored
@@ -27,3 +27,10 @@ scripts/cutWALUntil/cutWALUntil
|
||||
|
||||
libs/pubsub/query/fuzz_test/output
|
||||
shunit2
|
||||
|
||||
*/vendor
|
||||
*/.glide
|
||||
.terraform
|
||||
terraform.tfstate
|
||||
terraform.tfstate.backup
|
||||
terraform.tfstate.d
|
||||
|
26
CHANGELOG.md
26
CHANGELOG.md
@@ -1,5 +1,30 @@
|
||||
# Changelog
|
||||
|
||||
## 0.22.4
|
||||
|
||||
*July 14th, 2018*
|
||||
|
||||
BREAKING CHANGES:
|
||||
- [genesis] removed deprecated `app_options` field.
|
||||
- [types] Genesis.AppStateJSON -> Genesis.AppState
|
||||
|
||||
FEATURES:
|
||||
- [tools] Merged in from github.com/tendermint/tools
|
||||
|
||||
BUG FIXES:
|
||||
- [tools/tm-bench] Various fixes
|
||||
- [consensus] Wait for WAL to stop on shutdown
|
||||
- [abci] Fix #1891, pending requests cannot hang when abci server dies. Previously a crash in BeginBlock could leave tendermint in broken state.
|
||||
|
||||
## 0.22.3
|
||||
|
||||
*July 10th, 2018*
|
||||
|
||||
IMPROVEMENTS
|
||||
- Update dependencies
|
||||
* pin all values in Gopkg.toml to version or commit
|
||||
* update golang/protobuf to v1.1.0
|
||||
|
||||
## 0.22.2
|
||||
|
||||
*July 10th, 2018*
|
||||
@@ -32,6 +57,7 @@ BUG FIXES
|
||||
already in the validator set.
|
||||
* [consensus] Shut down WAL properly.
|
||||
|
||||
|
||||
## 0.22.0
|
||||
|
||||
*July 2nd, 2018*
|
||||
|
27
Gopkg.lock
generated
27
Gopkg.lock
generated
@@ -11,10 +11,9 @@
|
||||
branch = "master"
|
||||
name = "github.com/btcsuite/btcd"
|
||||
packages = ["btcec"]
|
||||
revision = "86fed781132ac890ee03e906e4ecd5d6fa180c64"
|
||||
revision = "fdfc19097e7ac6b57035062056f5b7b4638b8898"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/btcsuite/btcutil"
|
||||
packages = [
|
||||
"base58",
|
||||
@@ -29,16 +28,15 @@
|
||||
version = "v1.1.0"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/ebuchman/fail-test"
|
||||
packages = ["."]
|
||||
revision = "95f809107225be108efcf10a3509e4ea6ceef3c4"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/fortytw2/leaktest"
|
||||
packages = ["."]
|
||||
revision = "b008db64ef8daabb22ff6daa557f33b41d8f6ccd"
|
||||
revision = "a5ef70473c97b71626b9abeda80ee92ba2a7de9e"
|
||||
version = "v1.2.0"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/fsnotify/fsnotify"
|
||||
@@ -180,13 +178,12 @@
|
||||
version = "v1.0.0"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/prometheus/client_golang"
|
||||
packages = [
|
||||
"prometheus",
|
||||
"prometheus/promhttp"
|
||||
]
|
||||
revision = "d6a9817c4afc94d51115e4a30d449056a3fbf547"
|
||||
revision = "ae27198cdd90bf12cd134ad79d1366a6cf49f632"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
@@ -213,10 +210,9 @@
|
||||
"nfs",
|
||||
"xfs"
|
||||
]
|
||||
revision = "40f013a808ec4fa79def444a1a56de4d1727efcb"
|
||||
revision = "ae68e2d4c00fed4943b5f6698d504a5fe083da8a"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/rcrowley/go-metrics"
|
||||
packages = ["."]
|
||||
revision = "e2704e165165ec55d062f5919b4b29494e9fa790"
|
||||
@@ -266,8 +262,8 @@
|
||||
"assert",
|
||||
"require"
|
||||
]
|
||||
revision = "f35b8ab0b5a2cef36673838d662e249dd9c94686"
|
||||
version = "v1.2.2"
|
||||
revision = "12b6f73e6084dad08a7c6e575284b177ecafbc71"
|
||||
version = "v1.2.1"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
@@ -286,7 +282,7 @@
|
||||
"leveldb/table",
|
||||
"leveldb/util"
|
||||
]
|
||||
revision = "e2150783cd35f5b607daca48afd8c57ec54cc995"
|
||||
revision = "c4c61651e9e37fa117f53c5a906d3b63090d8445"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
@@ -326,7 +322,6 @@
|
||||
revision = "a49355c7e3f8fe157a85be2f77e6e269a0f89602"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "golang.org/x/net"
|
||||
packages = [
|
||||
"context",
|
||||
@@ -338,7 +333,7 @@
|
||||
"netutil",
|
||||
"trace"
|
||||
]
|
||||
revision = "4cb1c02c05b0e749b0365f61ae859a8e0cfceed9"
|
||||
revision = "292b43bbf7cb8d35ddf40f8d5100ef3837cced3f"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
@@ -347,7 +342,7 @@
|
||||
"cpu",
|
||||
"unix"
|
||||
]
|
||||
revision = "7138fd3d9dc8335c567ca206f4333fb75eb05d56"
|
||||
revision = "1b2967e3c290b7c545b3db0deeda16e9be4f98a2"
|
||||
|
||||
[[projects]]
|
||||
name = "golang.org/x/text"
|
||||
@@ -414,6 +409,6 @@
|
||||
[solve-meta]
|
||||
analyzer-name = "dep"
|
||||
analyzer-version = 1
|
||||
inputs-digest = "6e854634d6c203278ce83bef7725cecbcf90023b0d0e440fb3374acedacbd5ad"
|
||||
inputs-digest = "b0718135d5ade0a75c6b8fe703f70eb9d8064ba871ec31abd9ace3c4ab944100"
|
||||
solver-name = "gps-cdcl"
|
||||
solver-version = 1
|
||||
|
73
Gopkg.toml
73
Gopkg.toml
@@ -23,16 +23,12 @@
|
||||
# non-go = false
|
||||
# go-tests = true
|
||||
# unused-packages = true
|
||||
#
|
||||
###########################################################
|
||||
# NOTE: All packages should be pinned to specific versions.
|
||||
# Packages without releases must pin to a commit.
|
||||
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/ebuchman/fail-test"
|
||||
branch = "master"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/fortytw2/leaktest"
|
||||
branch = "master"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/go-kit/kit"
|
||||
version = "=0.6.0"
|
||||
@@ -47,16 +43,12 @@
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/gorilla/websocket"
|
||||
version = "~1.2.0"
|
||||
version = "=1.2.0"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/pkg/errors"
|
||||
version = "=0.8.0"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/rcrowley/go-metrics"
|
||||
branch = "master"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/spf13/cobra"
|
||||
version = "=0.0.1"
|
||||
@@ -67,29 +59,60 @@
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/stretchr/testify"
|
||||
version = "~1.2.1"
|
||||
version = "=1.2.1"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/tendermint/go-amino"
|
||||
version = "~0.10.1"
|
||||
version = "=0.10.1"
|
||||
|
||||
[[constraint]]
|
||||
name = "google.golang.org/grpc"
|
||||
version = "~1.11.3"
|
||||
version = "=1.11.3"
|
||||
|
||||
# this got updated and broke, so locked to an old working commit ...
|
||||
[[constraint]]
|
||||
name = "github.com/fortytw2/leaktest"
|
||||
version = "=1.2.0"
|
||||
|
||||
###################################
|
||||
## Some repos dont have releases.
|
||||
## Pin to revision
|
||||
|
||||
## We can remove this one by updating protobuf to v1.1.0
|
||||
## but then the grpc tests break with
|
||||
#--- FAIL: TestBroadcastTx (0.01s)
|
||||
#panic: message/group field common.KVPair:bytes without pointer [recovered]
|
||||
# panic: message/group field common.KVPair:bytes without pointer
|
||||
#
|
||||
# ...
|
||||
#
|
||||
# github.com/tendermint/tendermint/rpc/grpc_test.TestBroadcastTx(0xc420a5ab40)
|
||||
# /go/src/github.com/tendermint/tendermint/rpc/grpc/grpc_test.go:29 +0x141
|
||||
[[override]]
|
||||
name = "google.golang.org/genproto"
|
||||
revision = "7fd901a49ba6a7f87732eb344f6e3c5b19d1b200"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/ebuchman/fail-test"
|
||||
revision = "95f809107225be108efcf10a3509e4ea6ceef3c4"
|
||||
|
||||
# last revision used by go-crypto
|
||||
[[constraint]]
|
||||
name = "github.com/btcsuite/btcutil"
|
||||
revision = "d4cc87b860166d00d6b5b9e0d3b3d71d6088d4d4"
|
||||
|
||||
# Haven't made a release since 2016.
|
||||
[[constraint]]
|
||||
name = "github.com/prometheus/client_golang"
|
||||
revision = "ae27198cdd90bf12cd134ad79d1366a6cf49f632"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/rcrowley/go-metrics"
|
||||
revision = "e2704e165165ec55d062f5919b4b29494e9fa790"
|
||||
|
||||
[[constraint]]
|
||||
name = "golang.org/x/net"
|
||||
revision = "292b43bbf7cb8d35ddf40f8d5100ef3837cced3f"
|
||||
|
||||
[prune]
|
||||
go-tests = true
|
||||
unused-packages = true
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/prometheus/client_golang"
|
||||
branch = "master"
|
||||
|
||||
[[constraint]]
|
||||
branch = "master"
|
||||
name = "golang.org/x/net"
|
||||
|
@@ -357,6 +357,13 @@ func (cli *socketClient) queueRequest(req *types.Request) *ReqRes {
|
||||
}
|
||||
|
||||
func (cli *socketClient) flushQueue() {
|
||||
// mark all in-flight messages as resolved (they will get cli.Error())
|
||||
for req := cli.reqSent.Front(); req != nil; req = req.Next() {
|
||||
reqres := req.Value.(*ReqRes)
|
||||
reqres.Done()
|
||||
}
|
||||
|
||||
// mark all queued messages as resolved
|
||||
LOOP:
|
||||
for {
|
||||
select {
|
||||
|
@@ -2,10 +2,17 @@ package abcicli_test
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/tendermint/tendermint/abci/client"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
abcicli "github.com/tendermint/tendermint/abci/client"
|
||||
"github.com/tendermint/tendermint/abci/server"
|
||||
"github.com/tendermint/tendermint/abci/types"
|
||||
cmn "github.com/tendermint/tendermint/libs/common"
|
||||
)
|
||||
|
||||
func TestSocketClientStopForErrorDeadlock(t *testing.T) {
|
||||
@@ -26,3 +33,89 @@ func TestSocketClientStopForErrorDeadlock(t *testing.T) {
|
||||
t.Fatalf("Test took too long, potential deadlock still exists")
|
||||
}
|
||||
}
|
||||
|
||||
func TestProperSyncCalls(t *testing.T) {
|
||||
app := slowApp{}
|
||||
|
||||
s, c := setupClientServer(t, app)
|
||||
defer s.Stop()
|
||||
defer c.Stop()
|
||||
|
||||
resp := make(chan error, 1)
|
||||
go func() {
|
||||
// This is BeginBlockSync unrolled....
|
||||
reqres := c.BeginBlockAsync(types.RequestBeginBlock{})
|
||||
c.FlushSync()
|
||||
res := reqres.Response.GetBeginBlock()
|
||||
require.NotNil(t, res)
|
||||
resp <- c.Error()
|
||||
}()
|
||||
|
||||
select {
|
||||
case <-time.After(time.Second):
|
||||
require.Fail(t, "No response arrived")
|
||||
case err, ok := <-resp:
|
||||
require.True(t, ok, "Must not close channel")
|
||||
assert.NoError(t, err, "This should return success")
|
||||
}
|
||||
}
|
||||
|
||||
func TestHangingSyncCalls(t *testing.T) {
|
||||
app := slowApp{}
|
||||
|
||||
s, c := setupClientServer(t, app)
|
||||
defer s.Stop()
|
||||
defer c.Stop()
|
||||
|
||||
resp := make(chan error, 1)
|
||||
go func() {
|
||||
// Start BeginBlock and flush it
|
||||
reqres := c.BeginBlockAsync(types.RequestBeginBlock{})
|
||||
flush := c.FlushAsync()
|
||||
// wait 20 ms for all events to travel socket, but
|
||||
// no response yet from server
|
||||
time.Sleep(20 * time.Millisecond)
|
||||
// kill the server, so the connections break
|
||||
s.Stop()
|
||||
|
||||
// wait for the response from BeginBlock
|
||||
reqres.Wait()
|
||||
flush.Wait()
|
||||
resp <- c.Error()
|
||||
}()
|
||||
|
||||
select {
|
||||
case <-time.After(time.Second):
|
||||
require.Fail(t, "No response arrived")
|
||||
case err, ok := <-resp:
|
||||
require.True(t, ok, "Must not close channel")
|
||||
assert.Error(t, err, "We should get EOF error")
|
||||
}
|
||||
}
|
||||
|
||||
func setupClientServer(t *testing.T, app types.Application) (
|
||||
cmn.Service, abcicli.Client) {
|
||||
// some port between 20k and 30k
|
||||
port := 20000 + cmn.RandInt32()%10000
|
||||
addr := fmt.Sprintf("localhost:%d", port)
|
||||
|
||||
s, err := server.NewServer(addr, "socket", app)
|
||||
require.NoError(t, err)
|
||||
err = s.Start()
|
||||
require.NoError(t, err)
|
||||
|
||||
c := abcicli.NewSocketClient(addr, true)
|
||||
err = c.Start()
|
||||
require.NoError(t, err)
|
||||
|
||||
return s, c
|
||||
}
|
||||
|
||||
type slowApp struct {
|
||||
types.BaseApplication
|
||||
}
|
||||
|
||||
func (slowApp) BeginBlock(req types.RequestBeginBlock) types.ResponseBeginBlock {
|
||||
time.Sleep(200 * time.Millisecond)
|
||||
return types.ResponseBeginBlock{}
|
||||
}
|
||||
|
@@ -80,6 +80,9 @@ func (conR *ConsensusReactor) OnStop() {
|
||||
conR.BaseReactor.OnStop()
|
||||
conR.unsubscribeFromBroadcastEvents()
|
||||
conR.conS.Stop()
|
||||
if !conR.FastSync() {
|
||||
conR.conS.Wait()
|
||||
}
|
||||
}
|
||||
|
||||
// SwitchToConsensus switches from fast_sync mode to consensus mode.
|
||||
|
@@ -273,7 +273,7 @@ func (h *Handshaker) ReplayBlocks(state sm.State, appHash []byte, appBlockHeight
|
||||
ChainId: h.genDoc.ChainID,
|
||||
ConsensusParams: csParams,
|
||||
Validators: validators,
|
||||
AppStateBytes: h.genDoc.AppStateJSON,
|
||||
AppStateBytes: h.genDoc.AppState,
|
||||
}
|
||||
res, err := proxyApp.Consensus().InitChainSync(req)
|
||||
if err != nil {
|
||||
|
@@ -1,8 +1,4 @@
|
||||
Fast Sync
|
||||
=========
|
||||
|
||||
Background
|
||||
----------
|
||||
# Fast Sync
|
||||
|
||||
In a proof of work blockchain, syncing with the chain is the same
|
||||
process as staying up-to-date with the consensus: download blocks, and
|
||||
@@ -14,21 +10,19 @@ scratch can take a very long time. It's much faster to just download
|
||||
blocks and check the merkle tree of validators than to run the real-time
|
||||
consensus gossip protocol.
|
||||
|
||||
Fast Sync
|
||||
---------
|
||||
## Using Fast Sync
|
||||
|
||||
To support faster syncing, tendermint offers a ``fast-sync`` mode, which
|
||||
is enabled by default, and can be toggled in the ``config.toml`` or via
|
||||
``--fast_sync=false``.
|
||||
To support faster syncing, tendermint offers a `fast-sync` mode, which
|
||||
is enabled by default, and can be toggled in the `config.toml` or via
|
||||
`--fast_sync=false`.
|
||||
|
||||
In this mode, the tendermint daemon will sync hundreds of times faster
|
||||
than if it used the real-time consensus process. Once caught up, the
|
||||
daemon will switch out of fast sync and into the normal consensus mode.
|
||||
After running for some time, the node is considered ``caught up`` if it
|
||||
After running for some time, the node is considered `caught up` if it
|
||||
has at least one peer and it's height is at least as high as the max
|
||||
reported peer height. See `the IsCaughtUp
|
||||
method <https://github.com/tendermint/tendermint/blob/b467515719e686e4678e6da4e102f32a491b85a0/blockchain/pool.go#L128>`__.
|
||||
reported peer height. See [the IsCaughtUp
|
||||
method](https://github.com/tendermint/tendermint/blob/b467515719e686e4678e6da4e102f32a491b85a0/blockchain/pool.go#L128).
|
||||
|
||||
If we're lagging sufficiently, we should go back to fast syncing, but
|
||||
this is an open issue:
|
||||
https://github.com/tendermint/tendermint/issues/129
|
||||
this is an [open issue](https://github.com/tendermint/tendermint/issues/129).
|
@@ -149,7 +149,33 @@ func MakeParts(obj interface{}, partSize int) []Part
|
||||
|
||||
## Merkle Trees
|
||||
|
||||
Simple Merkle trees are used in numerous places in Tendermint to compute a cryptographic digest of a data structure.
|
||||
For an overview of Merkle trees, see
|
||||
[wikipedia](https://en.wikipedia.org/wiki/Merkle_tree)
|
||||
|
||||
|
||||
A Simple Tree is a simple compact binary tree for a static list of items. Simple Merkle trees are used in numerous places in Tendermint to compute a cryptographic digest of a data structure. In a Simple Tree, the transactions and validation signatures of a block are hashed using this simple merkle tree logic.
|
||||
|
||||
If the number of items is not a power of two, the tree will not be full
|
||||
and some leaf nodes will be at different levels. Simple Tree tries to
|
||||
keep both sides of the tree the same size, but the left side may be one
|
||||
greater, for example:
|
||||
|
||||
```
|
||||
Simple Tree with 6 items Simple Tree with 7 items
|
||||
|
||||
* *
|
||||
/ \ / \
|
||||
/ \ / \
|
||||
/ \ / \
|
||||
/ \ / \
|
||||
* * * *
|
||||
/ \ / \ / \ / \
|
||||
/ \ / \ / \ / \
|
||||
/ \ / \ / \ / \
|
||||
* h2 * h5 * * * h6
|
||||
/ \ / \ / \ / \ / \
|
||||
h0 h1 h3 h4 h0 h1 h2 h3 h4 h5
|
||||
```
|
||||
|
||||
Tendermint always uses the `TMHASH` hash function, which is the first 20-bytes
|
||||
of the SHA256:
|
||||
@@ -235,6 +261,18 @@ func computeHashFromAunts(index, total int, leafHash []byte, innerHashes [][]byt
|
||||
}
|
||||
```
|
||||
|
||||
### Simple Tree with Dictionaries
|
||||
|
||||
The Simple Tree is used to merkelize a list of items, so to merkelize a
|
||||
(short) dictionary of key-value pairs, encode the dictionary as an
|
||||
ordered list of ``KVPair`` structs. The block hash is such a hash
|
||||
derived from all the fields of the block ``Header``. The state hash is
|
||||
similarly derived.
|
||||
|
||||
### IAVL+ Tree
|
||||
|
||||
Because Tendermint only uses a Simple Merkle Tree, application developers are expect to use their own Merkle tree in their applications. For example, the IAVL+ Tree - an immutable self-balancing binary tree for persisting application state is used by the [Cosmos SDK](https://github.com/cosmos/cosmos-sdk/blob/develop/docs/core/multistore.md)
|
||||
|
||||
## JSON
|
||||
|
||||
### Amino
|
||||
|
@@ -1,9 +1,329 @@
|
||||
We are working to finalize an updated Tendermint specification with formal
|
||||
proofs of safety and liveness.
|
||||
# Byzantine Consensus Algorithm
|
||||
|
||||
In the meantime, see the [description in the
|
||||
docs](http://tendermint.readthedocs.io/en/master/specification/byzantine-consensus-algorithm.html).
|
||||
## Terms
|
||||
|
||||
There are also relevant but somewhat outdated descriptions in Jae Kwon's [original
|
||||
whitepaper](https://tendermint.com/static/docs/tendermint.pdf) and Ethan Buchman's [master's
|
||||
thesis](https://atrium.lib.uoguelph.ca/xmlui/handle/10214/9769).
|
||||
- The network is composed of optionally connected *nodes*. Nodes
|
||||
directly connected to a particular node are called *peers*.
|
||||
- The consensus process in deciding the next block (at some *height*
|
||||
`H`) is composed of one or many *rounds*.
|
||||
- `NewHeight`, `Propose`, `Prevote`, `Precommit`, and `Commit`
|
||||
represent state machine states of a round. (aka `RoundStep` or
|
||||
just "step").
|
||||
- A node is said to be *at* a given height, round, and step, or at
|
||||
`(H,R,S)`, or at `(H,R)` in short to omit the step.
|
||||
- To *prevote* or *precommit* something means to broadcast a [prevote
|
||||
vote](https://godoc.org/github.com/tendermint/tendermint/types#Vote)
|
||||
or [first precommit
|
||||
vote](https://godoc.org/github.com/tendermint/tendermint/types#FirstPrecommit)
|
||||
for something.
|
||||
- A vote *at* `(H,R)` is a vote signed with the bytes for `H` and `R`
|
||||
included in its [sign-bytes](block-structure.html#vote-sign-bytes).
|
||||
- *+2/3* is short for "more than 2/3"
|
||||
- *1/3+* is short for "1/3 or more"
|
||||
- A set of +2/3 of prevotes for a particular block or `<nil>` at
|
||||
`(H,R)` is called a *proof-of-lock-change* or *PoLC* for short.
|
||||
|
||||
## State Machine Overview
|
||||
|
||||
At each height of the blockchain a round-based protocol is run to
|
||||
determine the next block. Each round is composed of three *steps*
|
||||
(`Propose`, `Prevote`, and `Precommit`), along with two special steps
|
||||
`Commit` and `NewHeight`.
|
||||
|
||||
In the optimal scenario, the order of steps is:
|
||||
|
||||
```
|
||||
NewHeight -> (Propose -> Prevote -> Precommit)+ -> Commit -> NewHeight ->...
|
||||
```
|
||||
|
||||
The sequence `(Propose -> Prevote -> Precommit)` is called a *round*.
|
||||
There may be more than one round required to commit a block at a given
|
||||
height. Examples for why more rounds may be required include:
|
||||
|
||||
- The designated proposer was not online.
|
||||
- The block proposed by the designated proposer was not valid.
|
||||
- The block proposed by the designated proposer did not propagate
|
||||
in time.
|
||||
- The block proposed was valid, but +2/3 of prevotes for the proposed
|
||||
block were not received in time for enough validator nodes by the
|
||||
time they reached the `Precommit` step. Even though +2/3 of prevotes
|
||||
are necessary to progress to the next step, at least one validator
|
||||
may have voted `<nil>` or maliciously voted for something else.
|
||||
- The block proposed was valid, and +2/3 of prevotes were received for
|
||||
enough nodes, but +2/3 of precommits for the proposed block were not
|
||||
received for enough validator nodes.
|
||||
|
||||
Some of these problems are resolved by moving onto the next round &
|
||||
proposer. Others are resolved by increasing certain round timeout
|
||||
parameters over each successive round.
|
||||
|
||||
## State Machine Diagram
|
||||
|
||||
```
|
||||
+-------------------------------------+
|
||||
v |(Wait til `CommmitTime+timeoutCommit`)
|
||||
+-----------+ +-----+-----+
|
||||
+----------> | Propose +--------------+ | NewHeight |
|
||||
| +-----------+ | +-----------+
|
||||
| | ^
|
||||
|(Else, after timeoutPrecommit) v |
|
||||
+-----+-----+ +-----------+ |
|
||||
| Precommit | <------------------------+ Prevote | |
|
||||
+-----+-----+ +-----------+ |
|
||||
|(When +2/3 Precommits for block found) |
|
||||
v |
|
||||
+--------------------------------------------------------------------+
|
||||
| Commit |
|
||||
| |
|
||||
| * Set CommitTime = now; |
|
||||
| * Wait for block, then stage/save/commit block; |
|
||||
+--------------------------------------------------------------------+
|
||||
```
|
||||
|
||||
Background Gossip
|
||||
=================
|
||||
|
||||
A node may not have a corresponding validator private key, but it
|
||||
nevertheless plays an active role in the consensus process by relaying
|
||||
relevant meta-data, proposals, blocks, and votes to its peers. A node
|
||||
that has the private keys of an active validator and is engaged in
|
||||
signing votes is called a *validator-node*. All nodes (not just
|
||||
validator-nodes) have an associated state (the current height, round,
|
||||
and step) and work to make progress.
|
||||
|
||||
Between two nodes there exists a `Connection`, and multiplexed on top of
|
||||
this connection are fairly throttled `Channel`s of information. An
|
||||
epidemic gossip protocol is implemented among some of these channels to
|
||||
bring peers up to speed on the most recent state of consensus. For
|
||||
example,
|
||||
|
||||
- Nodes gossip `PartSet` parts of the current round's proposer's
|
||||
proposed block. A LibSwift inspired algorithm is used to quickly
|
||||
broadcast blocks across the gossip network.
|
||||
- Nodes gossip prevote/precommit votes. A node `NODE_A` that is ahead
|
||||
of `NODE_B` can send `NODE_B` prevotes or precommits for `NODE_B`'s
|
||||
current (or future) round to enable it to progress forward.
|
||||
- Nodes gossip prevotes for the proposed PoLC (proof-of-lock-change)
|
||||
round if one is proposed.
|
||||
- Nodes gossip to nodes lagging in blockchain height with block
|
||||
[commits](https://godoc.org/github.com/tendermint/tendermint/types#Commit)
|
||||
for older blocks.
|
||||
- Nodes opportunistically gossip `HasVote` messages to hint peers what
|
||||
votes it already has.
|
||||
- Nodes broadcast their current state to all neighboring peers. (but
|
||||
is not gossiped further)
|
||||
|
||||
There's more, but let's not get ahead of ourselves here.
|
||||
|
||||
## Proposals
|
||||
|
||||
A proposal is signed and published by the designated proposer at each
|
||||
round. The proposer is chosen by a deterministic and non-choking round
|
||||
robin selection algorithm that selects proposers in proportion to their
|
||||
voting power (see
|
||||
[implementation](https://github.com/tendermint/tendermint/blob/develop/types/validator_set.go)).
|
||||
|
||||
A proposal at `(H,R)` is composed of a block and an optional latest
|
||||
`PoLC-Round < R` which is included iff the proposer knows of one. This
|
||||
hints the network to allow nodes to unlock (when safe) to ensure the
|
||||
liveness property.
|
||||
|
||||
## State Machine Spec
|
||||
|
||||
### Propose Step (height:H,round:R)
|
||||
|
||||
Upon entering `Propose`: - The designated proposer proposes a block at
|
||||
`(H,R)`.
|
||||
|
||||
The `Propose` step ends: - After `timeoutProposeR` after entering
|
||||
`Propose`. --> goto `Prevote(H,R)` - After receiving proposal block
|
||||
and all prevotes at `PoLC-Round`. --> goto `Prevote(H,R)` - After
|
||||
[common exit conditions](#common-exit-conditions)
|
||||
|
||||
### Prevote Step (height:H,round:R)
|
||||
|
||||
Upon entering `Prevote`, each validator broadcasts its prevote vote.
|
||||
|
||||
- First, if the validator is locked on a block since `LastLockRound`
|
||||
but now has a PoLC for something else at round `PoLC-Round` where
|
||||
`LastLockRound < PoLC-Round < R`, then it unlocks.
|
||||
- If the validator is still locked on a block, it prevotes that.
|
||||
- Else, if the proposed block from `Propose(H,R)` is good, it
|
||||
prevotes that.
|
||||
- Else, if the proposal is invalid or wasn't received on time, it
|
||||
prevotes `<nil>`.
|
||||
|
||||
The `Prevote` step ends: - After +2/3 prevotes for a particular block or
|
||||
`<nil>`. -->; goto `Precommit(H,R)` - After `timeoutPrevote` after
|
||||
receiving any +2/3 prevotes. --> goto `Precommit(H,R)` - After
|
||||
[common exit conditions](#common-exit-conditions)
|
||||
|
||||
### Precommit Step (height:H,round:R)
|
||||
|
||||
Upon entering `Precommit`, each validator broadcasts its precommit vote.
|
||||
- If the validator has a PoLC at `(H,R)` for a particular block `B`, it
|
||||
(re)locks (or changes lock to) and precommits `B` and sets
|
||||
`LastLockRound = R`. - Else, if the validator has a PoLC at `(H,R)` for
|
||||
`<nil>`, it unlocks and precommits `<nil>`. - Else, it keeps the lock
|
||||
unchanged and precommits `<nil>`.
|
||||
|
||||
A precommit for `<nil>` means "I didn’t see a PoLC for this round, but I
|
||||
did get +2/3 prevotes and waited a bit".
|
||||
|
||||
The Precommit step ends: - After +2/3 precommits for `<nil>`. -->
|
||||
goto `Propose(H,R+1)` - After `timeoutPrecommit` after receiving any
|
||||
+2/3 precommits. --> goto `Propose(H,R+1)` - After [common exit
|
||||
conditions](#common-exit-conditions)
|
||||
|
||||
### Common exit conditions
|
||||
|
||||
- After +2/3 precommits for a particular block. --> goto
|
||||
`Commit(H)`
|
||||
- After any +2/3 prevotes received at `(H,R+x)`. --> goto
|
||||
`Prevote(H,R+x)`
|
||||
- After any +2/3 precommits received at `(H,R+x)`. --> goto
|
||||
`Precommit(H,R+x)`
|
||||
|
||||
### Commit Step (height:H)
|
||||
|
||||
- Set `CommitTime = now()`
|
||||
- Wait until block is received. --> goto `NewHeight(H+1)`
|
||||
|
||||
### NewHeight Step (height:H)
|
||||
|
||||
- Move `Precommits` to `LastCommit` and increment height.
|
||||
- Set `StartTime = CommitTime+timeoutCommit`
|
||||
- Wait until `StartTime` to receive straggler commits. --> goto
|
||||
`Propose(H,0)`
|
||||
|
||||
## Proofs
|
||||
|
||||
### Proof of Safety
|
||||
|
||||
Assume that at most -1/3 of the voting power of validators is byzantine.
|
||||
If a validator commits block `B` at round `R`, it's because it saw +2/3
|
||||
of precommits at round `R`. This implies that 1/3+ of honest nodes are
|
||||
still locked at round `R' > R`. These locked validators will remain
|
||||
locked until they see a PoLC at `R' > R`, but this won't happen because
|
||||
1/3+ are locked and honest, so at most -2/3 are available to vote for
|
||||
anything other than `B`.
|
||||
|
||||
### Proof of Liveness
|
||||
|
||||
If 1/3+ honest validators are locked on two different blocks from
|
||||
different rounds, a proposers' `PoLC-Round` will eventually cause nodes
|
||||
locked from the earlier round to unlock. Eventually, the designated
|
||||
proposer will be one that is aware of a PoLC at the later round. Also,
|
||||
`timeoutProposalR` increments with round `R`, while the size of a
|
||||
proposal are capped, so eventually the network is able to "fully gossip"
|
||||
the whole proposal (e.g. the block & PoLC).
|
||||
|
||||
### Proof of Fork Accountability
|
||||
|
||||
Define the JSet (justification-vote-set) at height `H` of a validator
|
||||
`V1` to be all the votes signed by the validator at `H` along with
|
||||
justification PoLC prevotes for each lock change. For example, if `V1`
|
||||
signed the following precommits: `Precommit(B1 @ round 0)`,
|
||||
`Precommit(<nil> @ round 1)`, `Precommit(B2 @ round 4)` (note that no
|
||||
precommits were signed for rounds 2 and 3, and that's ok),
|
||||
`Precommit(B1 @ round 0)` must be justified by a PoLC at round 0, and
|
||||
`Precommit(B2 @ round 4)` must be justified by a PoLC at round 4; but
|
||||
the precommit for `<nil>` at round 1 is not a lock-change by definition
|
||||
so the JSet for `V1` need not include any prevotes at round 1, 2, or 3
|
||||
(unless `V1` happened to have prevoted for those rounds).
|
||||
|
||||
Further, define the JSet at height `H` of a set of validators `VSet` to
|
||||
be the union of the JSets for each validator in `VSet`. For a given
|
||||
commit by honest validators at round `R` for block `B` we can construct
|
||||
a JSet to justify the commit for `B` at `R`. We say that a JSet
|
||||
*justifies* a commit at `(H,R)` if all the committers (validators in the
|
||||
commit-set) are each justified in the JSet with no duplicitous vote
|
||||
signatures (by the committers).
|
||||
|
||||
- **Lemma**: When a fork is detected by the existence of two
|
||||
conflicting [commits](./validators.html#commiting-a-block), the
|
||||
union of the JSets for both commits (if they can be compiled) must
|
||||
include double-signing by at least 1/3+ of the validator set.
|
||||
**Proof**: The commit cannot be at the same round, because that
|
||||
would immediately imply double-signing by 1/3+. Take the union of
|
||||
the JSets of both commits. If there is no double-signing by at least
|
||||
1/3+ of the validator set in the union, then no honest validator
|
||||
could have precommitted any different block after the first commit.
|
||||
Yet, +2/3 did. Reductio ad absurdum.
|
||||
|
||||
As a corollary, when there is a fork, an external process can determine
|
||||
the blame by requiring each validator to justify all of its round votes.
|
||||
Either we will find 1/3+ who cannot justify at least one of their votes,
|
||||
and/or, we will find 1/3+ who had double-signed.
|
||||
|
||||
### Alternative algorithm
|
||||
|
||||
Alternatively, we can take the JSet of a commit to be the "full commit".
|
||||
That is, if light clients and validators do not consider a block to be
|
||||
committed unless the JSet of the commit is also known, then we get the
|
||||
desirable property that if there ever is a fork (e.g. there are two
|
||||
conflicting "full commits"), then 1/3+ of the validators are immediately
|
||||
punishable for double-signing.
|
||||
|
||||
There are many ways to ensure that the gossip network efficiently share
|
||||
the JSet of a commit. One solution is to add a new message type that
|
||||
tells peers that this node has (or does not have) a +2/3 majority for B
|
||||
(or) at (H,R), and a bitarray of which votes contributed towards that
|
||||
majority. Peers can react by responding with appropriate votes.
|
||||
|
||||
We will implement such an algorithm for the next iteration of the
|
||||
Tendermint consensus protocol.
|
||||
|
||||
Other potential improvements include adding more data in votes such as
|
||||
the last known PoLC round that caused a lock change, and the last voted
|
||||
round/step (or, we may require that validators not skip any votes). This
|
||||
may make JSet verification/gossip logic easier to implement.
|
||||
|
||||
### Censorship Attacks
|
||||
|
||||
Due to the definition of a block
|
||||
[commit](../../tendermint-core/validator.md#commiting-a-block), any 1/3+ coalition of
|
||||
validators can halt the blockchain by not broadcasting their votes. Such
|
||||
a coalition can also censor particular transactions by rejecting blocks
|
||||
that include these transactions, though this would result in a
|
||||
significant proportion of block proposals to be rejected, which would
|
||||
slow down the rate of block commits of the blockchain, reducing its
|
||||
utility and value. The malicious coalition might also broadcast votes in
|
||||
a trickle so as to grind blockchain block commits to a near halt, or
|
||||
engage in any combination of these attacks.
|
||||
|
||||
If a global active adversary were also involved, it can partition the
|
||||
network in such a way that it may appear that the wrong subset of
|
||||
validators were responsible for the slowdown. This is not just a
|
||||
limitation of Tendermint, but rather a limitation of all consensus
|
||||
protocols whose network is potentially controlled by an active
|
||||
adversary.
|
||||
|
||||
### Overcoming Forks and Censorship Attacks
|
||||
|
||||
For these types of attacks, a subset of the validators through external
|
||||
means should coordinate to sign a reorg-proposal that chooses a fork
|
||||
(and any evidence thereof) and the initial subset of validators with
|
||||
their signatures. Validators who sign such a reorg-proposal forego its
|
||||
collateral on all other forks. Clients should verify the signatures on
|
||||
the reorg-proposal, verify any evidence, and make a judgement or prompt
|
||||
the end-user for a decision. For example, a phone wallet app may prompt
|
||||
the user with a security warning, while a refrigerator may accept any
|
||||
reorg-proposal signed by +1/2 of the original validators.
|
||||
|
||||
No non-synchronous Byzantine fault-tolerant algorithm can come to
|
||||
consensus when 1/3+ of validators are dishonest, yet a fork assumes that
|
||||
1/3+ of validators have already been dishonest by double-signing or
|
||||
lock-changing without justification. So, signing the reorg-proposal is a
|
||||
coordination problem that cannot be solved by any non-synchronous
|
||||
protocol (i.e. automatically, and without making assumptions about the
|
||||
reliability of the underlying network). It must be provided by means
|
||||
external to the weakly-synchronous Tendermint consensus algorithm. For
|
||||
now, we leave the problem of reorg-proposal coordination to human
|
||||
coordination via internet media. Validators must take care to ensure
|
||||
that there are no significant network partitions, to avoid situations
|
||||
where two conflicting reorg-proposals are signed.
|
||||
|
||||
Assuming that the external coordination medium and protocol is robust,
|
||||
it follows that forks are less of a concern than [censorship
|
||||
attacks](#censorship-attacks).
|
||||
|
@@ -1,218 +0,0 @@
|
||||
Block Structure
|
||||
===============
|
||||
|
||||
The tendermint consensus engine records all agreements by a
|
||||
supermajority of nodes into a blockchain, which is replicated among all
|
||||
nodes. This blockchain is accessible via various rpc endpoints, mainly
|
||||
``/block?height=`` to get the full block, as well as
|
||||
``/blockchain?minHeight=_&maxHeight=_`` to get a list of headers. But
|
||||
what exactly is stored in these blocks?
|
||||
|
||||
Block
|
||||
~~~~~
|
||||
|
||||
A
|
||||
`Block <https://godoc.org/github.com/tendermint/tendermint/types#Block>`__
|
||||
contains:
|
||||
|
||||
- a `Header <#header>`__ contains merkle hashes for various chain
|
||||
states
|
||||
- the
|
||||
`Data <https://godoc.org/github.com/tendermint/tendermint/types#Data>`__
|
||||
is all transactions which are to be processed
|
||||
- the `LastCommit <#commit>`__ > 2/3 signatures for the last block
|
||||
|
||||
The signatures returned along with block ``H`` are those validating
|
||||
block ``H-1``. This can be a little confusing, but we must also consider
|
||||
that the ``Header`` also contains the ``LastCommitHash``. It would be
|
||||
impossible for a Header to include the commits that sign it, as it would
|
||||
cause an infinite loop here. But when we get block ``H``, we find
|
||||
``Header.LastCommitHash``, which must match the hash of ``LastCommit``.
|
||||
|
||||
Header
|
||||
~~~~~~
|
||||
|
||||
The
|
||||
`Header <https://godoc.org/github.com/tendermint/tendermint/types#Header>`__
|
||||
contains lots of information (follow link for up-to-date info). Notably,
|
||||
it maintains the ``Height``, the ``LastBlockID`` (to make it a chain),
|
||||
and hashes of the data, the app state, and the validator set. This is
|
||||
important as the only item that is signed by the validators is the
|
||||
``Header``, and all other data must be validated against one of the
|
||||
merkle hashes in the ``Header``.
|
||||
|
||||
The ``DataHash`` can provide a nice check on the
|
||||
`Data <https://godoc.org/github.com/tendermint/tendermint/types#Data>`__
|
||||
returned in this same block. If you are subscribed to new blocks, via
|
||||
tendermint RPC, in order to display or process the new transactions you
|
||||
should at least validate that the ``DataHash`` is valid. If it is
|
||||
important to verify autheniticity, you must wait for the ``LastCommit``
|
||||
from the next block to make sure the block header (including
|
||||
``DataHash``) was properly signed.
|
||||
|
||||
The ``ValidatorHash`` contains a hash of the current
|
||||
`Validators <https://godoc.org/github.com/tendermint/tendermint/types#Validator>`__.
|
||||
Tracking all changes in the validator set is complex, but a client can
|
||||
quickly compare this hash with the `hash of the currently known
|
||||
validators <https://godoc.org/github.com/tendermint/tendermint/types#ValidatorSet.Hash>`__
|
||||
to see if there have been changes.
|
||||
|
||||
The ``AppHash`` serves as the basis for validating any merkle proofs
|
||||
that come from the ABCI application. It represents the
|
||||
state of the actual application, rather that the state of the blockchain
|
||||
itself. This means it's necessary in order to perform any business
|
||||
logic, such as verifying an account balance.
|
||||
|
||||
**Note** After the transactions are committed to a block, they still
|
||||
need to be processed in a separate step, which happens between the
|
||||
blocks. If you find a given transaction in the block at height ``H``,
|
||||
the effects of running that transaction will be first visible in the
|
||||
``AppHash`` from the block header at height ``H+1``.
|
||||
|
||||
Like the ``LastCommit`` issue, this is a requirement of the immutability
|
||||
of the block chain, as the application only applies transactions *after*
|
||||
they are commited to the chain.
|
||||
|
||||
Commit
|
||||
~~~~~~
|
||||
|
||||
The
|
||||
`Commit <https://godoc.org/github.com/tendermint/tendermint/types#Commit>`__
|
||||
contains a set of
|
||||
`Votes <https://godoc.org/github.com/tendermint/tendermint/types#Vote>`__
|
||||
that were made by the validator set to reach consensus on this block.
|
||||
This is the key to the security in any PoS system, and actually no data
|
||||
that cannot be traced back to a block header with a valid set of Votes
|
||||
can be trusted. Thus, getting the Commit data and verifying the votes is
|
||||
extremely important.
|
||||
|
||||
As mentioned above, in order to find the ``precommit votes`` for block
|
||||
header ``H``, we need to query block ``H+1``. Then we need to check the
|
||||
votes, make sure they really are for that block, and properly formatted.
|
||||
Much of this code is implemented in Go in the
|
||||
`light-client <https://github.com/tendermint/light-client>`__ package.
|
||||
If you look at the code, you will notice that we need to provide the
|
||||
``chainID`` of the blockchain in order to properly calculate the votes.
|
||||
This is to protect anyone from swapping votes between chains to fake (or
|
||||
frame) a validator. Also note that this ``chainID`` is in the
|
||||
``genesis.json`` from *Tendermint*, not the ``genesis.json`` from the
|
||||
basecoin app (`that is a different
|
||||
chainID... <https://github.com/cosmos/cosmos-sdk/issues/32>`__).
|
||||
|
||||
Once we have those votes, and we calculated the proper `sign
|
||||
bytes <https://godoc.org/github.com/tendermint/tendermint/types#Vote.WriteSignBytes>`__
|
||||
using the chainID and a `nice helper
|
||||
function <https://godoc.org/github.com/tendermint/tendermint/types#SignBytes>`__,
|
||||
we can verify them. The light client is responsible for maintaining a
|
||||
set of validators that we trust. Each vote only stores the validators
|
||||
``Address``, as well as the ``Signature``. Assuming we have a local copy
|
||||
of the trusted validator set, we can look up the ``Public Key`` of the
|
||||
validator given its ``Address``, then verify that the ``Signature``
|
||||
matches the ``SignBytes`` and ``Public Key``. Then we sum up the total
|
||||
voting power of all validators, whose votes fulfilled all these
|
||||
stringent requirements. If the total number of voting power for a single
|
||||
block is greater than 2/3 of all voting power, then we can finally trust
|
||||
the block header, the AppHash, and the proof we got from the ABCI
|
||||
application.
|
||||
|
||||
Vote Sign Bytes
|
||||
^^^^^^^^^^^^^^^
|
||||
|
||||
The ``sign-bytes`` of a vote is produced by taking a
|
||||
`stable-json <https://github.com/substack/json-stable-stringify>`__-like
|
||||
deterministic JSON `wire <./wire-protocol.html>`__ encoding of
|
||||
the vote (excluding the ``Signature`` field), and wrapping it with
|
||||
``{"chain_id":"my_chain","vote":...}``.
|
||||
|
||||
For example, a precommit vote might have the following ``sign-bytes``:
|
||||
|
||||
.. code:: json
|
||||
|
||||
{"chain_id":"my_chain","vote":{"block_hash":"611801F57B4CE378DF1A3FFF1216656E89209A99","block_parts_header":{"hash":"B46697379DBE0774CC2C3B656083F07CA7E0F9CE","total":123},"height":1234,"round":1,"type":2}}
|
||||
|
||||
Block Hash
|
||||
~~~~~~~~~~
|
||||
|
||||
The `block
|
||||
hash <https://godoc.org/github.com/tendermint/tendermint/types#Block.Hash>`__
|
||||
is the `Simple Tree hash <./merkle.html#simple-tree-with-dictionaries>`__
|
||||
of the fields of the block ``Header`` encoded as a list of
|
||||
``KVPair``\ s.
|
||||
|
||||
Transaction
|
||||
~~~~~~~~~~~
|
||||
|
||||
A transaction is any sequence of bytes. It is up to your
|
||||
ABCI application to accept or reject transactions.
|
||||
|
||||
BlockID
|
||||
~~~~~~~
|
||||
|
||||
Many of these data structures refer to the
|
||||
`BlockID <https://godoc.org/github.com/tendermint/tendermint/types#BlockID>`__,
|
||||
which is the ``BlockHash`` (hash of the block header, also referred to
|
||||
by the next block) along with the ``PartSetHeader``. The
|
||||
``PartSetHeader`` is explained below and is used internally to
|
||||
orchestrate the p2p propogation. For clients, it is basically opaque
|
||||
bytes, but they must match for all votes.
|
||||
|
||||
PartSetHeader
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
The
|
||||
`PartSetHeader <https://godoc.org/github.com/tendermint/tendermint/types#PartSetHeader>`__
|
||||
contains the total number of pieces in a
|
||||
`PartSet <https://godoc.org/github.com/tendermint/tendermint/types#PartSet>`__,
|
||||
and the Merkle root hash of those pieces.
|
||||
|
||||
PartSet
|
||||
~~~~~~~
|
||||
|
||||
PartSet is used to split a byteslice of data into parts (pieces) for
|
||||
transmission. By splitting data into smaller parts and computing a
|
||||
Merkle root hash on the list, you can verify that a part is legitimately
|
||||
part of the complete data, and the part can be forwarded to other peers
|
||||
before all the parts are known. In short, it's a fast way to securely
|
||||
propagate a large chunk of data (like a block) over a gossip network.
|
||||
|
||||
PartSet was inspired by the LibSwift project.
|
||||
|
||||
Usage:
|
||||
|
||||
.. code:: go
|
||||
|
||||
data := RandBytes(2 << 20) // Something large
|
||||
|
||||
partSet := NewPartSetFromData(data)
|
||||
partSet.Total() // Total number of 4KB parts
|
||||
partSet.Count() // Equal to the Total, since we already have all the parts
|
||||
partSet.Hash() // The Merkle root hash
|
||||
partSet.BitArray() // A BitArray of partSet.Total() 1's
|
||||
|
||||
header := partSet.Header() // Send this to the peer
|
||||
header.Total // Total number of parts
|
||||
header.Hash // The merkle root hash
|
||||
|
||||
// Now we'll reconstruct the data from the parts
|
||||
partSet2 := NewPartSetFromHeader(header)
|
||||
partSet2.Total() // Same total as partSet.Total()
|
||||
partSet2.Count() // Zero, since this PartSet doesn't have any parts yet.
|
||||
partSet2.Hash() // Same hash as in partSet.Hash()
|
||||
partSet2.BitArray() // A BitArray of partSet.Total() 0's
|
||||
|
||||
// In a gossip network the parts would arrive in arbitrary order, perhaps
|
||||
// in response to explicit requests for parts, or optimistically in response
|
||||
// to the receiving peer's partSet.BitArray().
|
||||
for !partSet2.IsComplete() {
|
||||
part := receivePartFromGossipNetwork()
|
||||
added, err := partSet2.AddPart(part)
|
||||
if err != nil {
|
||||
// A wrong part,
|
||||
// the merkle trail does not hash to partSet2.Hash()
|
||||
} else if !added {
|
||||
// A duplicate part already received
|
||||
}
|
||||
}
|
||||
|
||||
data2, _ := ioutil.ReadAll(partSet2.GetReader())
|
||||
bytes.Equal(data, data2) // true
|
@@ -1,349 +0,0 @@
|
||||
Byzantine Consensus Algorithm
|
||||
=============================
|
||||
|
||||
Terms
|
||||
-----
|
||||
|
||||
- The network is composed of optionally connected *nodes*. Nodes
|
||||
directly connected to a particular node are called *peers*.
|
||||
- The consensus process in deciding the next block (at some *height*
|
||||
``H``) is composed of one or many *rounds*.
|
||||
- ``NewHeight``, ``Propose``, ``Prevote``, ``Precommit``, and
|
||||
``Commit`` represent state machine states of a round. (aka
|
||||
``RoundStep`` or just "step").
|
||||
- A node is said to be *at* a given height, round, and step, or at
|
||||
``(H,R,S)``, or at ``(H,R)`` in short to omit the step.
|
||||
- To *prevote* or *precommit* something means to broadcast a `prevote
|
||||
vote <https://godoc.org/github.com/tendermint/tendermint/types#Vote>`__
|
||||
or `first precommit
|
||||
vote <https://godoc.org/github.com/tendermint/tendermint/types#FirstPrecommit>`__
|
||||
for something.
|
||||
- A vote *at* ``(H,R)`` is a vote signed with the bytes for ``H`` and
|
||||
``R`` included in its
|
||||
`sign-bytes <block-structure.html#vote-sign-bytes>`__.
|
||||
- *+2/3* is short for "more than 2/3"
|
||||
- *1/3+* is short for "1/3 or more"
|
||||
- A set of +2/3 of prevotes for a particular block or ``<nil>`` at
|
||||
``(H,R)`` is called a *proof-of-lock-change* or *PoLC* for short.
|
||||
|
||||
State Machine Overview
|
||||
----------------------
|
||||
|
||||
At each height of the blockchain a round-based protocol is run to
|
||||
determine the next block. Each round is composed of three *steps*
|
||||
(``Propose``, ``Prevote``, and ``Precommit``), along with two special
|
||||
steps ``Commit`` and ``NewHeight``.
|
||||
|
||||
In the optimal scenario, the order of steps is:
|
||||
|
||||
::
|
||||
|
||||
NewHeight -> (Propose -> Prevote -> Precommit)+ -> Commit -> NewHeight ->...
|
||||
|
||||
The sequence ``(Propose -> Prevote -> Precommit)`` is called a *round*.
|
||||
There may be more than one round required to commit a block at a given
|
||||
height. Examples for why more rounds may be required include:
|
||||
|
||||
- The designated proposer was not online.
|
||||
- The block proposed by the designated proposer was not valid.
|
||||
- The block proposed by the designated proposer did not propagate in
|
||||
time.
|
||||
- The block proposed was valid, but +2/3 of prevotes for the proposed
|
||||
block were not received in time for enough validator nodes by the
|
||||
time they reached the ``Precommit`` step. Even though +2/3 of
|
||||
prevotes are necessary to progress to the next step, at least one
|
||||
validator may have voted ``<nil>`` or maliciously voted for something
|
||||
else.
|
||||
- The block proposed was valid, and +2/3 of prevotes were received for
|
||||
enough nodes, but +2/3 of precommits for the proposed block were not
|
||||
received for enough validator nodes.
|
||||
|
||||
Some of these problems are resolved by moving onto the next round &
|
||||
proposer. Others are resolved by increasing certain round timeout
|
||||
parameters over each successive round.
|
||||
|
||||
State Machine Diagram
|
||||
---------------------
|
||||
|
||||
::
|
||||
|
||||
+-------------------------------------+
|
||||
v |(Wait til `CommmitTime+timeoutCommit`)
|
||||
+-----------+ +-----+-----+
|
||||
+----------> | Propose +--------------+ | NewHeight |
|
||||
| +-----------+ | +-----------+
|
||||
| | ^
|
||||
|(Else, after timeoutPrecommit) v |
|
||||
+-----+-----+ +-----------+ |
|
||||
| Precommit | <------------------------+ Prevote | |
|
||||
+-----+-----+ +-----------+ |
|
||||
|(When +2/3 Precommits for block found) |
|
||||
v |
|
||||
+--------------------------------------------------------------------+
|
||||
| Commit |
|
||||
| |
|
||||
| * Set CommitTime = now; |
|
||||
| * Wait for block, then stage/save/commit block; |
|
||||
+--------------------------------------------------------------------+
|
||||
|
||||
Background Gossip
|
||||
-----------------
|
||||
|
||||
A node may not have a corresponding validator private key, but it
|
||||
nevertheless plays an active role in the consensus process by relaying
|
||||
relevant meta-data, proposals, blocks, and votes to its peers. A node
|
||||
that has the private keys of an active validator and is engaged in
|
||||
signing votes is called a *validator-node*. All nodes (not just
|
||||
validator-nodes) have an associated state (the current height, round,
|
||||
and step) and work to make progress.
|
||||
|
||||
Between two nodes there exists a ``Connection``, and multiplexed on top
|
||||
of this connection are fairly throttled ``Channel``\ s of information.
|
||||
An epidemic gossip protocol is implemented among some of these channels
|
||||
to bring peers up to speed on the most recent state of consensus. For
|
||||
example,
|
||||
|
||||
- Nodes gossip ``PartSet`` parts of the current round's proposer's
|
||||
proposed block. A LibSwift inspired algorithm is used to quickly
|
||||
broadcast blocks across the gossip network.
|
||||
- Nodes gossip prevote/precommit votes. A node NODE\_A that is ahead of
|
||||
NODE\_B can send NODE\_B prevotes or precommits for NODE\_B's current
|
||||
(or future) round to enable it to progress forward.
|
||||
- Nodes gossip prevotes for the proposed PoLC (proof-of-lock-change)
|
||||
round if one is proposed.
|
||||
- Nodes gossip to nodes lagging in blockchain height with block
|
||||
`commits <https://godoc.org/github.com/tendermint/tendermint/types#Commit>`__
|
||||
for older blocks.
|
||||
- Nodes opportunistically gossip ``HasVote`` messages to hint peers
|
||||
what votes it already has.
|
||||
- Nodes broadcast their current state to all neighboring peers. (but is
|
||||
not gossiped further)
|
||||
|
||||
There's more, but let's not get ahead of ourselves here.
|
||||
|
||||
Proposals
|
||||
---------
|
||||
|
||||
A proposal is signed and published by the designated proposer at each
|
||||
round. The proposer is chosen by a deterministic and non-choking round
|
||||
robin selection algorithm that selects proposers in proportion to their
|
||||
voting power. (see
|
||||
`implementation <https://github.com/tendermint/tendermint/blob/develop/types/validator_set.go>`__)
|
||||
|
||||
A proposal at ``(H,R)`` is composed of a block and an optional latest
|
||||
``PoLC-Round < R`` which is included iff the proposer knows of one. This
|
||||
hints the network to allow nodes to unlock (when safe) to ensure the
|
||||
liveness property.
|
||||
|
||||
State Machine Spec
|
||||
------------------
|
||||
|
||||
Propose Step (height:H,round:R)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Upon entering ``Propose``: - The designated proposer proposes a block at
|
||||
``(H,R)``.
|
||||
|
||||
The ``Propose`` step ends: - After ``timeoutProposeR`` after entering
|
||||
``Propose``. --> goto ``Prevote(H,R)`` - After receiving proposal block
|
||||
and all prevotes at ``PoLC-Round``. --> goto ``Prevote(H,R)`` - After
|
||||
`common exit conditions <#common-exit-conditions>`__
|
||||
|
||||
Prevote Step (height:H,round:R)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Upon entering ``Prevote``, each validator broadcasts its prevote vote.
|
||||
|
||||
- First, if the validator is locked on a block since ``LastLockRound``
|
||||
but now has a PoLC for something else at round ``PoLC-Round`` where
|
||||
``LastLockRound < PoLC-Round < R``, then it unlocks.
|
||||
- If the validator is still locked on a block, it prevotes that.
|
||||
- Else, if the proposed block from ``Propose(H,R)`` is good, it
|
||||
prevotes that.
|
||||
- Else, if the proposal is invalid or wasn't received on time, it
|
||||
prevotes ``<nil>``.
|
||||
|
||||
The ``Prevote`` step ends: - After +2/3 prevotes for a particular block
|
||||
or ``<nil>``. --> goto ``Precommit(H,R)`` - After ``timeoutPrevote``
|
||||
after receiving any +2/3 prevotes. --> goto ``Precommit(H,R)`` - After
|
||||
`common exit conditions <#common-exit-conditions>`__
|
||||
|
||||
Precommit Step (height:H,round:R)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Upon entering ``Precommit``, each validator broadcasts its precommit
|
||||
vote. - If the validator has a PoLC at ``(H,R)`` for a particular block
|
||||
``B``, it (re)locks (or changes lock to) and precommits ``B`` and sets
|
||||
``LastLockRound = R``. - Else, if the validator has a PoLC at ``(H,R)``
|
||||
for ``<nil>``, it unlocks and precommits ``<nil>``. - Else, it keeps the
|
||||
lock unchanged and precommits ``<nil>``.
|
||||
|
||||
A precommit for ``<nil>`` means "I didn’t see a PoLC for this round, but
|
||||
I did get +2/3 prevotes and waited a bit".
|
||||
|
||||
The Precommit step ends: - After +2/3 precommits for ``<nil>``. --> goto
|
||||
``Propose(H,R+1)`` - After ``timeoutPrecommit`` after receiving any +2/3
|
||||
precommits. --> goto ``Propose(H,R+1)`` - After `common exit
|
||||
conditions <#common-exit-conditions>`__
|
||||
|
||||
common exit conditions
|
||||
^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
- After +2/3 precommits for a particular block. --> goto ``Commit(H)``
|
||||
- After any +2/3 prevotes received at ``(H,R+x)``. --> goto
|
||||
``Prevote(H,R+x)``
|
||||
- After any +2/3 precommits received at ``(H,R+x)``. --> goto
|
||||
``Precommit(H,R+x)``
|
||||
|
||||
Commit Step (height:H)
|
||||
~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
- Set ``CommitTime = now()``
|
||||
- Wait until block is received. --> goto ``NewHeight(H+1)``
|
||||
|
||||
NewHeight Step (height:H)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
- Move ``Precommits`` to ``LastCommit`` and increment height.
|
||||
- Set ``StartTime = CommitTime+timeoutCommit``
|
||||
- Wait until ``StartTime`` to receive straggler commits. --> goto
|
||||
``Propose(H,0)``
|
||||
|
||||
Proofs
|
||||
------
|
||||
|
||||
Proof of Safety
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
Assume that at most -1/3 of the voting power of validators is byzantine.
|
||||
If a validator commits block ``B`` at round ``R``, it's because it saw
|
||||
+2/3 of precommits at round ``R``. This implies that 1/3+ of honest
|
||||
nodes are still locked at round ``R' > R``. These locked validators will
|
||||
remain locked until they see a PoLC at ``R' > R``, but this won't happen
|
||||
because 1/3+ are locked and honest, so at most -2/3 are available to
|
||||
vote for anything other than ``B``.
|
||||
|
||||
Proof of Liveness
|
||||
~~~~~~~~~~~~~~~~~
|
||||
|
||||
If 1/3+ honest validators are locked on two different blocks from
|
||||
different rounds, a proposers' ``PoLC-Round`` will eventually cause
|
||||
nodes locked from the earlier round to unlock. Eventually, the
|
||||
designated proposer will be one that is aware of a PoLC at the later
|
||||
round. Also, ``timeoutProposalR`` increments with round ``R``, while the
|
||||
size of a proposal are capped, so eventually the network is able to
|
||||
"fully gossip" the whole proposal (e.g. the block & PoLC).
|
||||
|
||||
Proof of Fork Accountability
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Define the JSet (justification-vote-set) at height ``H`` of a validator
|
||||
``V1`` to be all the votes signed by the validator at ``H`` along with
|
||||
justification PoLC prevotes for each lock change. For example, if ``V1``
|
||||
signed the following precommits: ``Precommit(B1 @ round 0)``,
|
||||
``Precommit(<nil> @ round 1)``, ``Precommit(B2 @ round 4)`` (note that
|
||||
no precommits were signed for rounds 2 and 3, and that's ok),
|
||||
``Precommit(B1 @ round 0)`` must be justified by a PoLC at round 0, and
|
||||
``Precommit(B2 @ round 4)`` must be justified by a PoLC at round 4; but
|
||||
the precommit for ``<nil>`` at round 1 is not a lock-change by
|
||||
definition so the JSet for ``V1`` need not include any prevotes at round
|
||||
1, 2, or 3 (unless ``V1`` happened to have prevoted for those rounds).
|
||||
|
||||
Further, define the JSet at height ``H`` of a set of validators ``VSet``
|
||||
to be the union of the JSets for each validator in ``VSet``. For a given
|
||||
commit by honest validators at round ``R`` for block ``B`` we can
|
||||
construct a JSet to justify the commit for ``B`` at ``R``. We say that a
|
||||
JSet *justifies* a commit at ``(H,R)`` if all the committers (validators
|
||||
in the commit-set) are each justified in the JSet with no duplicitous
|
||||
vote signatures (by the committers).
|
||||
|
||||
- **Lemma**: When a fork is detected by the existence of two
|
||||
conflicting `commits <./validators.html#commiting-a-block>`__,
|
||||
the union of the JSets for both commits (if they can be compiled)
|
||||
must include double-signing by at least 1/3+ of the validator set.
|
||||
**Proof**: The commit cannot be at the same round, because that would
|
||||
immediately imply double-signing by 1/3+. Take the union of the JSets
|
||||
of both commits. If there is no double-signing by at least 1/3+ of
|
||||
the validator set in the union, then no honest validator could have
|
||||
precommitted any different block after the first commit. Yet, +2/3
|
||||
did. Reductio ad absurdum.
|
||||
|
||||
As a corollary, when there is a fork, an external process can determine
|
||||
the blame by requiring each validator to justify all of its round votes.
|
||||
Either we will find 1/3+ who cannot justify at least one of their votes,
|
||||
and/or, we will find 1/3+ who had double-signed.
|
||||
|
||||
Alternative algorithm
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Alternatively, we can take the JSet of a commit to be the "full commit".
|
||||
That is, if light clients and validators do not consider a block to be
|
||||
committed unless the JSet of the commit is also known, then we get the
|
||||
desirable property that if there ever is a fork (e.g. there are two
|
||||
conflicting "full commits"), then 1/3+ of the validators are immediately
|
||||
punishable for double-signing.
|
||||
|
||||
There are many ways to ensure that the gossip network efficiently share
|
||||
the JSet of a commit. One solution is to add a new message type that
|
||||
tells peers that this node has (or does not have) a +2/3 majority for B
|
||||
(or ) at (H,R), and a bitarray of which votes contributed towards that
|
||||
majority. Peers can react by responding with appropriate votes.
|
||||
|
||||
We will implement such an algorithm for the next iteration of the
|
||||
Tendermint consensus protocol.
|
||||
|
||||
Other potential improvements include adding more data in votes such as
|
||||
the last known PoLC round that caused a lock change, and the last voted
|
||||
round/step (or, we may require that validators not skip any votes). This
|
||||
may make JSet verification/gossip logic easier to implement.
|
||||
|
||||
Censorship Attacks
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Due to the definition of a block
|
||||
`commit <validators.html#commiting-a-block>`__, any 1/3+
|
||||
coalition of validators can halt the blockchain by not broadcasting
|
||||
their votes. Such a coalition can also censor particular transactions by
|
||||
rejecting blocks that include these transactions, though this would
|
||||
result in a significant proportion of block proposals to be rejected,
|
||||
which would slow down the rate of block commits of the blockchain,
|
||||
reducing its utility and value. The malicious coalition might also
|
||||
broadcast votes in a trickle so as to grind blockchain block commits to
|
||||
a near halt, or engage in any combination of these attacks.
|
||||
|
||||
If a global active adversary were also involved, it can partition the
|
||||
network in such a way that it may appear that the wrong subset of
|
||||
validators were responsible for the slowdown. This is not just a
|
||||
limitation of Tendermint, but rather a limitation of all consensus
|
||||
protocols whose network is potentially controlled by an active
|
||||
adversary.
|
||||
|
||||
Overcoming Forks and Censorship Attacks
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
For these types of attacks, a subset of the validators through external
|
||||
means should coordinate to sign a reorg-proposal that chooses a fork
|
||||
(and any evidence thereof) and the initial subset of validators with
|
||||
their signatures. Validators who sign such a reorg-proposal forego its
|
||||
collateral on all other forks. Clients should verify the signatures on
|
||||
the reorg-proposal, verify any evidence, and make a judgement or prompt
|
||||
the end-user for a decision. For example, a phone wallet app may prompt
|
||||
the user with a security warning, while a refrigerator may accept any
|
||||
reorg-proposal signed by +1/2 of the original validators.
|
||||
|
||||
No non-synchronous Byzantine fault-tolerant algorithm can come to
|
||||
consensus when 1/3+ of validators are dishonest, yet a fork assumes that
|
||||
1/3+ of validators have already been dishonest by double-signing or
|
||||
lock-changing without justification. So, signing the reorg-proposal is a
|
||||
coordination problem that cannot be solved by any non-synchronous
|
||||
protocol (i.e. automatically, and without making assumptions about the
|
||||
reliability of the underlying network). It must be provided by means
|
||||
external to the weakly-synchronous Tendermint consensus algorithm. For
|
||||
now, we leave the problem of reorg-proposal coordination to human
|
||||
coordination via internet media. Validators must take care to ensure
|
||||
that there are no significant network partitions, to avoid situations
|
||||
where two conflicting reorg-proposals are signed.
|
||||
|
||||
Assuming that the external coordination medium and protocol is robust,
|
||||
it follows that forks are less of a concern than `censorship
|
||||
attacks <#censorship-attacks>`__.
|
@@ -1,70 +0,0 @@
|
||||
Corruption
|
||||
==========
|
||||
|
||||
Important step
|
||||
--------------
|
||||
|
||||
Make sure you have a backup of the Tendermint data directory.
|
||||
|
||||
Possible causes
|
||||
---------------
|
||||
|
||||
Remember that most corruption is caused by hardware issues:
|
||||
|
||||
- RAID controllers with faulty / worn out battery backup, and an unexpected power loss
|
||||
- Hard disk drives with write-back cache enabled, and an unexpected power loss
|
||||
- Cheap SSDs with insufficient power-loss protection, and an unexpected power-loss
|
||||
- Defective RAM
|
||||
- Defective or overheating CPU(s)
|
||||
|
||||
Other causes can be:
|
||||
|
||||
- Database systems configured with fsync=off and an OS crash or power loss
|
||||
- Filesystems configured to use write barriers plus a storage layer that ignores write barriers. LVM is a particular culprit.
|
||||
- Tendermint bugs
|
||||
- Operating system bugs
|
||||
- Admin error
|
||||
- directly modifying Tendermint data-directory contents
|
||||
|
||||
(Source: https://wiki.postgresql.org/wiki/Corruption)
|
||||
|
||||
WAL Corruption
|
||||
--------------
|
||||
|
||||
If consensus WAL is corrupted at the lastest height and you are trying to start
|
||||
Tendermint, replay will fail with panic.
|
||||
|
||||
Recovering from data corruption can be hard and time-consuming. Here are two approaches you can take:
|
||||
|
||||
1) Delete the WAL file and restart Tendermint. It will attempt to sync with other peers.
|
||||
2) Try to repair the WAL file manually:
|
||||
|
||||
1. Create a backup of the corrupted WAL file:
|
||||
|
||||
.. code:: bash
|
||||
|
||||
cp "$TMHOME/data/cs.wal/wal" > /tmp/corrupted_wal_backup
|
||||
|
||||
2. Use ./scripts/wal2json to create a human-readable version
|
||||
|
||||
.. code:: bash
|
||||
|
||||
./scripts/wal2json/wal2json "$TMHOME/data/cs.wal/wal" > /tmp/corrupted_wal
|
||||
|
||||
3. Search for a "CORRUPTED MESSAGE" line.
|
||||
4. By looking at the previous message and the message after the corrupted one
|
||||
and looking at the logs, try to rebuild the message. If the consequent
|
||||
messages are marked as corrupted too (this may happen if length header
|
||||
got corrupted or some writes did not make it to the WAL ~ truncation),
|
||||
then remove all the lines starting from the corrupted one and restart
|
||||
Tendermint.
|
||||
|
||||
.. code:: bash
|
||||
|
||||
$EDITOR /tmp/corrupted_wal
|
||||
|
||||
5. After editing, convert this file back into binary form by running:
|
||||
|
||||
.. code:: bash
|
||||
|
||||
./scripts/json2wal/json2wal /tmp/corrupted_wal > "$TMHOME/data/cs.wal/wal"
|
@@ -1,71 +0,0 @@
|
||||
Genesis
|
||||
=======
|
||||
|
||||
The genesis.json file in ``$TMHOME/config`` defines the initial TendermintCore
|
||||
state upon genesis of the blockchain (`see
|
||||
definition <https://github.com/tendermint/tendermint/blob/master/types/genesis.go>`__).
|
||||
|
||||
Fields
|
||||
~~~~~~
|
||||
|
||||
- ``genesis_time``: Official time of blockchain start.
|
||||
- ``chain_id``: ID of the blockchain. This must be unique for every
|
||||
blockchain. If your testnet blockchains do not have unique chain IDs,
|
||||
you will have a bad time.
|
||||
- ``validators``:
|
||||
- ``pub_key``: The first element specifies the pub\_key type. 1 ==
|
||||
Ed25519. The second element are the pubkey bytes.
|
||||
- ``power``: The validator's voting power.
|
||||
- ``name``: Name of the validator (optional).
|
||||
- ``app_hash``: The expected application hash (as returned by the
|
||||
``ResponseInfo`` ABCI message) upon genesis. If the app's hash does not
|
||||
match, Tendermint will panic.
|
||||
- ``app_state``: The application state (e.g. initial distribution of tokens).
|
||||
|
||||
Sample genesis.json
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. code:: json
|
||||
|
||||
{
|
||||
"genesis_time": "2016-02-05T06:02:31.526Z",
|
||||
"chain_id": "chain-tTH4mi",
|
||||
"validators": [
|
||||
{
|
||||
"pub_key": [
|
||||
1,
|
||||
"9BC5112CB9614D91CE423FA8744885126CD9D08D9FC9D1F42E552D662BAA411E"
|
||||
],
|
||||
"power": 1,
|
||||
"name": "mach1"
|
||||
},
|
||||
{
|
||||
"pub_key": [
|
||||
1,
|
||||
"F46A5543D51F31660D9F59653B4F96061A740FF7433E0DC1ECBC30BE8494DE06"
|
||||
],
|
||||
"power": 1,
|
||||
"name": "mach2"
|
||||
},
|
||||
{
|
||||
"pub_key": [
|
||||
1,
|
||||
"0E7B423C1635FD07C0FC3603B736D5D27953C1C6CA865BB9392CD79DE1A682BB"
|
||||
],
|
||||
"power": 1,
|
||||
"name": "mach3"
|
||||
},
|
||||
{
|
||||
"pub_key": [
|
||||
1,
|
||||
"4F49237B9A32EB50682EDD83C48CE9CDB1D02A7CFDADCFF6EC8C1FAADB358879"
|
||||
],
|
||||
"power": 1,
|
||||
"name": "mach4"
|
||||
}
|
||||
],
|
||||
"app_hash": "15005165891224E721CB664D15CB972240F5703F",
|
||||
"app_state": {
|
||||
{"account": "Bob", "coins": 5000}
|
||||
}
|
||||
}
|
@@ -1,33 +0,0 @@
|
||||
Light Client Protocol
|
||||
=====================
|
||||
|
||||
Light clients are an important part of the complete blockchain system
|
||||
for most applications. Tendermint provides unique speed and security
|
||||
properties for light client applications.
|
||||
|
||||
See our `lite package
|
||||
<https://godoc.org/github.com/tendermint/tendermint/lite>`__.
|
||||
|
||||
Overview
|
||||
--------
|
||||
|
||||
The objective of the light client protocol is to get a
|
||||
`commit <./validators.html#committing-a-block>`__ for a recent
|
||||
`block hash <./block-structure.html#block-hash>`__ where the commit
|
||||
includes a majority of signatures from the last known validator set.
|
||||
From there, all the application state is verifiable with `merkle
|
||||
proofs <./merkle.html#iavl-tree>`__.
|
||||
|
||||
Properties
|
||||
----------
|
||||
|
||||
- You get the full collateralized security benefits of Tendermint; No
|
||||
need to wait for confirmations.
|
||||
- You get the full speed benefits of Tendermint; transactions commit
|
||||
instantly.
|
||||
- You can get the most recent version of the application state
|
||||
non-interactively (without committing anything to the blockchain).
|
||||
For example, this means that you can get the most recent value of a
|
||||
name from the name-registry without worrying about fork censorship
|
||||
attacks, without posting a commit and waiting for confirmations. It's
|
||||
fast, secure, and free!
|
@@ -1,88 +0,0 @@
|
||||
Merkle
|
||||
======
|
||||
|
||||
For an overview of Merkle trees, see
|
||||
`wikipedia <https://en.wikipedia.org/wiki/Merkle_tree>`__.
|
||||
|
||||
There are two types of Merkle trees used in Tendermint.
|
||||
|
||||
- **IAVL+ Tree**: An immutable self-balancing binary
|
||||
tree for persistent application state
|
||||
- **Simple Tree**: A simple compact binary tree for
|
||||
a static list of items
|
||||
|
||||
IAVL+ Tree
|
||||
----------
|
||||
|
||||
The purpose of this data structure is to provide persistent storage for
|
||||
key-value pairs (e.g. account state, name-registrar data, and
|
||||
per-contract data) such that a deterministic merkle root hash can be
|
||||
computed. The tree is balanced using a variant of the `AVL
|
||||
algorithm <http://en.wikipedia.org/wiki/AVL_tree>`__ so all operations
|
||||
are O(log(n)).
|
||||
|
||||
Nodes of this tree are immutable and indexed by its hash. Thus any node
|
||||
serves as an immutable snapshot which lets us stage uncommitted
|
||||
transactions from the mempool cheaply, and we can instantly roll back to
|
||||
the last committed state to process transactions of a newly committed
|
||||
block (which may not be the same set of transactions as those from the
|
||||
mempool).
|
||||
|
||||
In an AVL tree, the heights of the two child subtrees of any node differ
|
||||
by at most one. Whenever this condition is violated upon an update, the
|
||||
tree is rebalanced by creating O(log(n)) new nodes that point to
|
||||
unmodified nodes of the old tree. In the original AVL algorithm, inner
|
||||
nodes can also hold key-value pairs. The AVL+ algorithm (note the plus)
|
||||
modifies the AVL algorithm to keep all values on leaf nodes, while only
|
||||
using branch-nodes to store keys. This simplifies the algorithm while
|
||||
minimizing the size of merkle proofs
|
||||
|
||||
In Ethereum, the analog is the `Patricia
|
||||
trie <http://en.wikipedia.org/wiki/Radix_tree>`__. There are tradeoffs.
|
||||
Keys do not need to be hashed prior to insertion in IAVL+ trees, so this
|
||||
provides faster iteration in the key space which may benefit some
|
||||
applications. The logic is simpler to implement, requiring only two
|
||||
types of nodes -- inner nodes and leaf nodes. The IAVL+ tree is a binary
|
||||
tree, so merkle proofs are much shorter than the base 16 Patricia trie.
|
||||
On the other hand, while IAVL+ trees provide a deterministic merkle root
|
||||
hash, it depends on the order of updates. In practice this shouldn't be
|
||||
a problem, since you can efficiently encode the tree structure when
|
||||
serializing the tree contents.
|
||||
|
||||
Simple Tree
|
||||
-----------
|
||||
|
||||
For merkelizing smaller static lists, use the Simple Tree. The
|
||||
transactions and validation signatures of a block are hashed using this
|
||||
simple merkle tree logic.
|
||||
|
||||
If the number of items is not a power of two, the tree will not be full
|
||||
and some leaf nodes will be at different levels. Simple Tree tries to
|
||||
keep both sides of the tree the same size, but the left side may be one
|
||||
greater.
|
||||
|
||||
::
|
||||
|
||||
Simple Tree with 6 items Simple Tree with 7 items
|
||||
|
||||
* *
|
||||
/ \ / \
|
||||
/ \ / \
|
||||
/ \ / \
|
||||
/ \ / \
|
||||
* * * *
|
||||
/ \ / \ / \ / \
|
||||
/ \ / \ / \ / \
|
||||
/ \ / \ / \ / \
|
||||
* h2 * h5 * * * h6
|
||||
/ \ / \ / \ / \ / \
|
||||
h0 h1 h3 h4 h0 h1 h2 h3 h4 h5
|
||||
|
||||
Simple Tree with Dictionaries
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The Simple Tree is used to merkelize a list of items, so to merkelize a
|
||||
(short) dictionary of key-value pairs, encode the dictionary as an
|
||||
ordered list of ``KVPair`` structs. The block hash is such a hash
|
||||
derived from all the fields of the block ``Header``. The state hash is
|
||||
similarly derived.
|
@@ -1 +0,0 @@
|
||||
Spec moved to [docs/spec](https://github.com/tendermint/tendermint/tree/master/docs/spec).
|
@@ -1,172 +0,0 @@
|
||||
Wire Protocol
|
||||
=============
|
||||
|
||||
The `Tendermint wire protocol <https://github.com/tendermint/go-wire>`__
|
||||
encodes data in `c-style binary <#binary>`__ and `JSON <#json>`__ form.
|
||||
|
||||
Supported types
|
||||
---------------
|
||||
|
||||
- Primitive types
|
||||
- ``uint8`` (aka ``byte``), ``uint16``, ``uint32``, ``uint64``
|
||||
- ``int8``, ``int16``, ``int32``, ``int64``
|
||||
- ``uint``, ``int``: variable length (un)signed integers
|
||||
- ``string``, ``[]byte``
|
||||
- ``time``
|
||||
- Derived types
|
||||
- structs
|
||||
- var-length arrays of a particular type
|
||||
- fixed-length arrays of a particular type
|
||||
- interfaces: registered union types preceded by a ``type byte``
|
||||
- pointers
|
||||
|
||||
Binary
|
||||
------
|
||||
|
||||
**Fixed-length primitive types** are encoded with 1,2,3, or 4 big-endian
|
||||
bytes. - ``uint8`` (aka ``byte``), ``uint16``, ``uint32``, ``uint64``:
|
||||
takes 1,2,3, and 4 bytes respectively - ``int8``, ``int16``, ``int32``,
|
||||
``int64``: takes 1,2,3, and 4 bytes respectively - ``time``: ``int64``
|
||||
representation of nanoseconds since epoch
|
||||
|
||||
**Variable-length integers** are encoded with a single leading byte
|
||||
representing the length of the following big-endian bytes. For signed
|
||||
negative integers, the most significant bit of the leading byte is a 1.
|
||||
|
||||
- ``uint``: 1-byte length prefixed variable-size (0 ~ 255 bytes)
|
||||
unsigned integers
|
||||
- ``int``: 1-byte length prefixed variable-size (0 ~ 127 bytes) signed
|
||||
integers
|
||||
|
||||
NOTE: While the number 0 (zero) is encoded with a single byte ``x00``,
|
||||
the number 1 (one) takes two bytes to represent: ``x0101``. This isn't
|
||||
the most efficient representation, but the rules are easier to remember.
|
||||
|
||||
+---------------+----------------+----------------+
|
||||
| number | binary | binary ``int`` |
|
||||
| | ``uint`` | |
|
||||
+===============+================+================+
|
||||
| 0 | ``x00`` | ``x00`` |
|
||||
+---------------+----------------+----------------+
|
||||
| 1 | ``x0101`` | ``x0101`` |
|
||||
+---------------+----------------+----------------+
|
||||
| 2 | ``x0102`` | ``x0102`` |
|
||||
+---------------+----------------+----------------+
|
||||
| 256 | ``x020100`` | ``x020100`` |
|
||||
+---------------+----------------+----------------+
|
||||
| 2^(127\ *8)-1 | ``x800100...`` | overflow |
|
||||
| \| | | |
|
||||
| ``x7FFFFF...` | | |
|
||||
| ` | | |
|
||||
| \| | | |
|
||||
| ``x7FFFFF...` | | |
|
||||
| ` | | |
|
||||
| \| \| | | |
|
||||
| 2^(127*\ 8) | | |
|
||||
+---------------+----------------+----------------+
|
||||
| 2^(255\*8)-1 |
|
||||
| \| |
|
||||
| ``xFFFFFF...` |
|
||||
| ` |
|
||||
| \| overflow |
|
||||
| \| \| -1 \| |
|
||||
| n/a \| |
|
||||
| ``x8101`` \| |
|
||||
| \| -2 \| n/a |
|
||||
| \| ``x8102`` |
|
||||
| \| \| -256 \| |
|
||||
| n/a \| |
|
||||
| ``x820100`` |
|
||||
| \| |
|
||||
+---------------+----------------+----------------+
|
||||
|
||||
**Structures** are encoded by encoding the field values in order of
|
||||
declaration.
|
||||
|
||||
.. code:: go
|
||||
|
||||
type Foo struct {
|
||||
MyString string
|
||||
MyUint32 uint32
|
||||
}
|
||||
var foo = Foo{"626172", math.MaxUint32}
|
||||
|
||||
/* The binary representation of foo:
|
||||
0103626172FFFFFFFF
|
||||
0103: `int` encoded length of string, here 3
|
||||
626172: 3 bytes of string "bar"
|
||||
FFFFFFFF: 4 bytes of uint32 MaxUint32
|
||||
*/
|
||||
|
||||
**Variable-length arrays** are encoded with a leading ``int`` denoting
|
||||
the length of the array followed by the binary representation of the
|
||||
items. **Fixed-length arrays** are similar but aren't preceded by the
|
||||
leading ``int``.
|
||||
|
||||
.. code:: go
|
||||
|
||||
foos := []Foo{foo, foo}
|
||||
|
||||
/* The binary representation of foos:
|
||||
01020103626172FFFFFFFF0103626172FFFFFFFF
|
||||
0102: `int` encoded length of array, here 2
|
||||
0103626172FFFFFFFF: the first `foo`
|
||||
0103626172FFFFFFFF: the second `foo`
|
||||
*/
|
||||
|
||||
foos := [2]Foo{foo, foo} // fixed-length array
|
||||
|
||||
/* The binary representation of foos:
|
||||
0103626172FFFFFFFF0103626172FFFFFFFF
|
||||
0103626172FFFFFFFF: the first `foo`
|
||||
0103626172FFFFFFFF: the second `foo`
|
||||
*/
|
||||
|
||||
**Interfaces** can represent one of any number of concrete types. The
|
||||
concrete types of an interface must first be declared with their
|
||||
corresponding ``type byte``. An interface is then encoded with the
|
||||
leading ``type byte``, then the binary encoding of the underlying
|
||||
concrete type.
|
||||
|
||||
NOTE: The byte ``x00`` is reserved for the ``nil`` interface value and
|
||||
``nil`` pointer values.
|
||||
|
||||
.. code:: go
|
||||
|
||||
type Animal interface{}
|
||||
type Dog uint32
|
||||
type Cat string
|
||||
|
||||
RegisterInterface(
|
||||
struct{ Animal }{}, // Convenience for referencing the 'Animal' interface
|
||||
ConcreteType{Dog(0), 0x01}, // Register the byte 0x01 to denote a Dog
|
||||
ConcreteType{Cat(""), 0x02}, // Register the byte 0x02 to denote a Cat
|
||||
)
|
||||
|
||||
var animal Animal = Dog(02)
|
||||
|
||||
/* The binary representation of animal:
|
||||
010102
|
||||
01: the type byte for a `Dog`
|
||||
0102: the bytes of Dog(02)
|
||||
*/
|
||||
|
||||
**Pointers** are encoded with a single leading byte ``x00`` for ``nil``
|
||||
pointers, otherwise encoded with a leading byte ``x01`` followed by the
|
||||
binary encoding of the value pointed to.
|
||||
|
||||
NOTE: It's easy to convert pointer types into interface types, since the
|
||||
``type byte`` ``x00`` is always ``nil``.
|
||||
|
||||
JSON
|
||||
----
|
||||
|
||||
The JSON codec is compatible with the ```binary`` <#binary>`__ codec,
|
||||
and is fairly intuitive if you're already familiar with golang's JSON
|
||||
encoding. Some quirks are noted below:
|
||||
|
||||
- variable-length and fixed-length bytes are encoded as uppercase
|
||||
hexadecimal strings
|
||||
- interface values are encoded as an array of two items:
|
||||
``[type_byte, concrete_value]``
|
||||
- times are encoded as rfc2822 strings
|
206
docs/tendermint-core/block-structure.md
Normal file
206
docs/tendermint-core/block-structure.md
Normal file
@@ -0,0 +1,206 @@
|
||||
# Block Structure
|
||||
|
||||
The tendermint consensus engine records all agreements by a
|
||||
supermajority of nodes into a blockchain, which is replicated among all
|
||||
nodes. This blockchain is accessible via various rpc endpoints, mainly
|
||||
`/block?height=` to get the full block, as well as
|
||||
`/blockchain?minHeight=_&maxHeight=_` to get a list of headers. But what
|
||||
exactly is stored in these blocks?
|
||||
|
||||
## Block
|
||||
|
||||
A
|
||||
[Block](https://godoc.org/github.com/tendermint/tendermint/types#Block)
|
||||
contains:
|
||||
|
||||
- a [Header](#header) contains merkle hashes for various chain states
|
||||
- the
|
||||
[Data](https://godoc.org/github.com/tendermint/tendermint/types#Data)
|
||||
is all transactions which are to be processed
|
||||
- the [LastCommit](#commit) > 2/3 signatures for the last block
|
||||
|
||||
The signatures returned along with block `H` are those validating block
|
||||
`H-1`. This can be a little confusing, but we must also consider that
|
||||
the `Header` also contains the `LastCommitHash`. It would be impossible
|
||||
for a Header to include the commits that sign it, as it would cause an
|
||||
infinite loop here. But when we get block `H`, we find
|
||||
`Header.LastCommitHash`, which must match the hash of `LastCommit`.
|
||||
|
||||
## Header
|
||||
|
||||
The
|
||||
[Header](https://godoc.org/github.com/tendermint/tendermint/types#Header)
|
||||
contains lots of information (follow link for up-to-date info). Notably,
|
||||
it maintains the `Height`, the `LastBlockID` (to make it a chain), and
|
||||
hashes of the data, the app state, and the validator set. This is
|
||||
important as the only item that is signed by the validators is the
|
||||
`Header`, and all other data must be validated against one of the merkle
|
||||
hashes in the `Header`.
|
||||
|
||||
The `DataHash` can provide a nice check on the
|
||||
[Data](https://godoc.org/github.com/tendermint/tendermint/types#Data)
|
||||
returned in this same block. If you are subscribed to new blocks, via
|
||||
tendermint RPC, in order to display or process the new transactions you
|
||||
should at least validate that the `DataHash` is valid. If it is
|
||||
important to verify autheniticity, you must wait for the `LastCommit`
|
||||
from the next block to make sure the block header (including `DataHash`)
|
||||
was properly signed.
|
||||
|
||||
The `ValidatorHash` contains a hash of the current
|
||||
[Validators](https://godoc.org/github.com/tendermint/tendermint/types#Validator).
|
||||
Tracking all changes in the validator set is complex, but a client can
|
||||
quickly compare this hash with the [hash of the currently known
|
||||
validators](https://godoc.org/github.com/tendermint/tendermint/types#ValidatorSet.Hash)
|
||||
to see if there have been changes.
|
||||
|
||||
The `AppHash` serves as the basis for validating any merkle proofs that
|
||||
come from the ABCI application. It represents the state of the actual
|
||||
application, rather that the state of the blockchain itself. This means
|
||||
it's necessary in order to perform any business logic, such as verifying
|
||||
an account balance.
|
||||
|
||||
**Note** After the transactions are committed to a block, they still
|
||||
need to be processed in a separate step, which happens between the
|
||||
blocks. If you find a given transaction in the block at height `H`, the
|
||||
effects of running that transaction will be first visible in the
|
||||
`AppHash` from the block header at height `H+1`.
|
||||
|
||||
Like the `LastCommit` issue, this is a requirement of the immutability
|
||||
of the block chain, as the application only applies transactions *after*
|
||||
they are commited to the chain.
|
||||
|
||||
## Commit
|
||||
|
||||
The
|
||||
[Commit](https://godoc.org/github.com/tendermint/tendermint/types#Commit)
|
||||
contains a set of
|
||||
[Votes](https://godoc.org/github.com/tendermint/tendermint/types#Vote)
|
||||
that were made by the validator set to reach consensus on this block.
|
||||
This is the key to the security in any PoS system, and actually no data
|
||||
that cannot be traced back to a block header with a valid set of Votes
|
||||
can be trusted. Thus, getting the Commit data and verifying the votes is
|
||||
extremely important.
|
||||
|
||||
As mentioned above, in order to find the `precommit votes` for block
|
||||
header `H`, we need to query block `H+1`. Then we need to check the
|
||||
votes, make sure they really are for that block, and properly formatted.
|
||||
Much of this code is implemented in Go in the
|
||||
[light-client](https://github.com/tendermint/light-client) package. If
|
||||
you look at the code, you will notice that we need to provide the
|
||||
`chainID` of the blockchain in order to properly calculate the votes.
|
||||
This is to protect anyone from swapping votes between chains to fake (or
|
||||
frame) a validator. Also note that this `chainID` is in the
|
||||
`genesis.json` from *Tendermint*, not the `genesis.json` from the
|
||||
basecoin app ([that is a different
|
||||
chainID...](https://github.com/cosmos/cosmos-sdk/issues/32)).
|
||||
|
||||
Once we have those votes, and we calculated the proper [sign
|
||||
bytes](https://godoc.org/github.com/tendermint/tendermint/types#Vote.WriteSignBytes)
|
||||
using the chainID and a [nice helper
|
||||
function](https://godoc.org/github.com/tendermint/tendermint/types#SignBytes),
|
||||
we can verify them. The light client is responsible for maintaining a
|
||||
set of validators that we trust. Each vote only stores the validators
|
||||
`Address`, as well as the `Signature`. Assuming we have a local copy of
|
||||
the trusted validator set, we can look up the `Public Key` of the
|
||||
validator given its `Address`, then verify that the `Signature` matches
|
||||
the `SignBytes` and `Public Key`. Then we sum up the total voting power
|
||||
of all validators, whose votes fulfilled all these stringent
|
||||
requirements. If the total number of voting power for a single block is
|
||||
greater than 2/3 of all voting power, then we can finally trust the
|
||||
block header, the AppHash, and the proof we got from the ABCI
|
||||
application.
|
||||
|
||||
### Vote Sign Bytes
|
||||
|
||||
The `sign-bytes` of a vote is produced by taking a
|
||||
[stable-json](https://github.com/substack/json-stable-stringify)-like
|
||||
deterministic JSON [wire](./wire-protocol.html) encoding of the vote
|
||||
(excluding the `Signature` field), and wrapping it with
|
||||
`{"chain_id":"my_chain","vote":...}`.
|
||||
|
||||
For example, a precommit vote might have the following `sign-bytes`:
|
||||
|
||||
```
|
||||
{"chain_id":"my_chain","vote":{"block_hash":"611801F57B4CE378DF1A3FFF1216656E89209A99","block_parts_header":{"hash":"B46697379DBE0774CC2C3B656083F07CA7E0F9CE","total":123},"height":1234,"round":1,"type":2}}
|
||||
```
|
||||
|
||||
## Block Hash
|
||||
|
||||
The [block
|
||||
hash](https://godoc.org/github.com/tendermint/tendermint/types#Block.Hash)
|
||||
is the [Simple Tree hash](./merkle.html#simple-tree-with-dictionaries)
|
||||
of the fields of the block `Header` encoded as a list of `KVPair`s.
|
||||
|
||||
## Transaction
|
||||
|
||||
A transaction is any sequence of bytes. It is up to your ABCI
|
||||
application to accept or reject transactions.
|
||||
|
||||
## BlockID
|
||||
|
||||
Many of these data structures refer to the
|
||||
[BlockID](https://godoc.org/github.com/tendermint/tendermint/types#BlockID),
|
||||
which is the `BlockHash` (hash of the block header, also referred to by
|
||||
the next block) along with the `PartSetHeader`. The `PartSetHeader` is
|
||||
explained below and is used internally to orchestrate the p2p
|
||||
propogation. For clients, it is basically opaque bytes, but they must
|
||||
match for all votes.
|
||||
|
||||
## PartSetHeader
|
||||
|
||||
The
|
||||
[PartSetHeader](https://godoc.org/github.com/tendermint/tendermint/types#PartSetHeader)
|
||||
contains the total number of pieces in a
|
||||
[PartSet](https://godoc.org/github.com/tendermint/tendermint/types#PartSet),
|
||||
and the Merkle root hash of those pieces.
|
||||
|
||||
## PartSet
|
||||
|
||||
PartSet is used to split a byteslice of data into parts (pieces) for
|
||||
transmission. By splitting data into smaller parts and computing a
|
||||
Merkle root hash on the list, you can verify that a part is legitimately
|
||||
part of the complete data, and the part can be forwarded to other peers
|
||||
before all the parts are known. In short, it's a fast way to securely
|
||||
propagate a large chunk of data (like a block) over a gossip network.
|
||||
|
||||
PartSet was inspired by the LibSwift project.
|
||||
|
||||
Usage:
|
||||
|
||||
```
|
||||
data := RandBytes(2 << 20) // Something large
|
||||
|
||||
partSet := NewPartSetFromData(data)
|
||||
partSet.Total() // Total number of 4KB parts
|
||||
partSet.Count() // Equal to the Total, since we already have all the parts
|
||||
partSet.Hash() // The Merkle root hash
|
||||
partSet.BitArray() // A BitArray of partSet.Total() 1's
|
||||
|
||||
header := partSet.Header() // Send this to the peer
|
||||
header.Total // Total number of parts
|
||||
header.Hash // The merkle root hash
|
||||
|
||||
// Now we'll reconstruct the data from the parts
|
||||
partSet2 := NewPartSetFromHeader(header)
|
||||
partSet2.Total() // Same total as partSet.Total()
|
||||
partSet2.Count() // Zero, since this PartSet doesn't have any parts yet.
|
||||
partSet2.Hash() // Same hash as in partSet.Hash()
|
||||
partSet2.BitArray() // A BitArray of partSet.Total() 0's
|
||||
|
||||
// In a gossip network the parts would arrive in arbitrary order, perhaps
|
||||
// in response to explicit requests for parts, or optimistically in response
|
||||
// to the receiving peer's partSet.BitArray().
|
||||
for !partSet2.IsComplete() {
|
||||
part := receivePartFromGossipNetwork()
|
||||
added, err := partSet2.AddPart(part)
|
||||
if err != nil {
|
||||
// A wrong part,
|
||||
// the merkle trail does not hash to partSet2.Hash()
|
||||
} else if !added {
|
||||
// A duplicate part already received
|
||||
}
|
||||
}
|
||||
|
||||
data2, _ := ioutil.ReadAll(partSet2.GetReader())
|
||||
bytes.Equal(data, data2) // true
|
||||
```
|
30
docs/tendermint-core/light-client-protocol.md
Normal file
30
docs/tendermint-core/light-client-protocol.md
Normal file
@@ -0,0 +1,30 @@
|
||||
# Light Client Protocol
|
||||
|
||||
Light clients are an important part of the complete blockchain system
|
||||
for most applications. Tendermint provides unique speed and security
|
||||
properties for light client applications.
|
||||
|
||||
See our [lite
|
||||
package](https://godoc.org/github.com/tendermint/tendermint/lite).
|
||||
|
||||
## Overview
|
||||
|
||||
The objective of the light client protocol is to get a
|
||||
[commit](./validators.md#committing-a-block) for a recent [block
|
||||
hash](../spec/consensus/consensus.md.md#block-hash) where the commit includes a
|
||||
majority of signatures from the last known validator set. From there,
|
||||
all the application state is verifiable with [merkle
|
||||
proofs](./merkle.md#iavl-tree).
|
||||
|
||||
## Properties
|
||||
|
||||
- You get the full collateralized security benefits of Tendermint; No
|
||||
need to wait for confirmations.
|
||||
- You get the full speed benefits of Tendermint; transactions
|
||||
commit instantly.
|
||||
- You can get the most recent version of the application state
|
||||
non-interactively (without committing anything to the blockchain).
|
||||
For example, this means that you can get the most recent value of a
|
||||
name from the name-registry without worrying about fork censorship
|
||||
attacks, without posting a commit and waiting for confirmations.
|
||||
It's fast, secure, and free!
|
@@ -104,6 +104,69 @@ signals we use the default behaviour in Go: [Default behavior of signals
|
||||
in Go
|
||||
programs](https://golang.org/pkg/os/signal/#hdr-Default_behavior_of_signals_in_Go_programs).
|
||||
|
||||
## Corruption
|
||||
|
||||
**NOTE:** Make sure you have a backup of the Tendermint data directory.
|
||||
|
||||
### Possible causes
|
||||
|
||||
Remember that most corruption is caused by hardware issues:
|
||||
|
||||
- RAID controllers with faulty / worn out battery backup, and an unexpected power loss
|
||||
- Hard disk drives with write-back cache enabled, and an unexpected power loss
|
||||
- Cheap SSDs with insufficient power-loss protection, and an unexpected power-loss
|
||||
- Defective RAM
|
||||
- Defective or overheating CPU(s)
|
||||
|
||||
Other causes can be:
|
||||
|
||||
- Database systems configured with fsync=off and an OS crash or power loss
|
||||
- Filesystems configured to use write barriers plus a storage layer that ignores write barriers. LVM is a particular culprit.
|
||||
- Tendermint bugs
|
||||
- Operating system bugs
|
||||
- Admin error (e.g., directly modifying Tendermint data-directory contents)
|
||||
|
||||
(Source: https://wiki.postgresql.org/wiki/Corruption)
|
||||
|
||||
### WAL Corruption
|
||||
|
||||
If consensus WAL is corrupted at the lastest height and you are trying to start
|
||||
Tendermint, replay will fail with panic.
|
||||
|
||||
Recovering from data corruption can be hard and time-consuming. Here are two approaches you can take:
|
||||
|
||||
1) Delete the WAL file and restart Tendermint. It will attempt to sync with other peers.
|
||||
2) Try to repair the WAL file manually:
|
||||
|
||||
1. Create a backup of the corrupted WAL file:
|
||||
|
||||
```
|
||||
cp "$TMHOME/data/cs.wal/wal" > /tmp/corrupted_wal_backup
|
||||
```
|
||||
|
||||
2. Use `./scripts/wal2json` to create a human-readable version
|
||||
|
||||
```
|
||||
./scripts/wal2json/wal2json "$TMHOME/data/cs.wal/wal" > /tmp/corrupted_wal
|
||||
```
|
||||
|
||||
3. Search for a "CORRUPTED MESSAGE" line.
|
||||
4. By looking at the previous message and the message after the corrupted one
|
||||
and looking at the logs, try to rebuild the message. If the consequent
|
||||
messages are marked as corrupted too (this may happen if length header
|
||||
got corrupted or some writes did not make it to the WAL ~ truncation),
|
||||
then remove all the lines starting from the corrupted one and restart
|
||||
Tendermint.
|
||||
|
||||
```
|
||||
$EDITOR /tmp/corrupted_wal
|
||||
```
|
||||
5. After editing, convert this file back into binary form by running:
|
||||
|
||||
```
|
||||
./scripts/json2wal/json2wal /tmp/corrupted_wal > "$TMHOME/data/cs.wal/wal"
|
||||
```
|
||||
|
||||
## Hardware
|
||||
|
||||
### Processor and Memory
|
||||
|
@@ -1,12 +1,11 @@
|
||||
Secure P2P
|
||||
==========
|
||||
# Secure P2P
|
||||
|
||||
The Tendermint p2p protocol uses an authenticated encryption scheme
|
||||
based on the `Station-to-Station
|
||||
Protocol <https://en.wikipedia.org/wiki/Station-to-Station_protocol>`__.
|
||||
based on the [Station-to-Station
|
||||
Protocol](https://en.wikipedia.org/wiki/Station-to-Station_protocol).
|
||||
The implementation uses
|
||||
`golang's <https://godoc.org/golang.org/x/crypto/nacl/box>`__ `nacl
|
||||
box <http://nacl.cr.yp.to/box.html>`__ for the actual authenticated
|
||||
[golang's](https://godoc.org/golang.org/x/crypto/nacl/box) [nacl
|
||||
box](http://nacl.cr.yp.to/box.html) for the actual authenticated
|
||||
encryption algorithm.
|
||||
|
||||
Each peer generates an ED25519 key-pair to use as a persistent
|
||||
@@ -19,10 +18,9 @@ their respective ephemeral public keys. This happens in the clear.
|
||||
They then each compute the shared secret. The shared secret is the
|
||||
multiplication of the peer's ephemeral private key by the other peer's
|
||||
ephemeral public key. The result is the same for both peers by the magic
|
||||
of `elliptic
|
||||
curves <https://en.wikipedia.org/wiki/Elliptic_curve_cryptography>`__.
|
||||
The shared secret is used as the symmetric key for the encryption
|
||||
algorithm.
|
||||
of [elliptic
|
||||
curves](https://en.wikipedia.org/wiki/Elliptic_curve_cryptography). The
|
||||
shared secret is used as the symmetric key for the encryption algorithm.
|
||||
|
||||
The two ephemeral public keys are sorted to establish a canonical order.
|
||||
Then a 24-byte nonce is generated by concatenating the public keys and
|
||||
@@ -52,8 +50,7 @@ time it is used. The communications maintain Perfect Forward Secrecy, as
|
||||
the persistent key pair was not used for generating secrets - only for
|
||||
authenticating.
|
||||
|
||||
Caveat
|
||||
------
|
||||
## Caveat
|
||||
|
||||
This system is still vulnerable to a Man-In-The-Middle attack if the
|
||||
persistent public key of the remote node is not known in advance. The
|
||||
@@ -62,17 +59,15 @@ such as the Web-of-Trust or Certificate Authorities. In our case, we can
|
||||
use the blockchain itself as a certificate authority to ensure that we
|
||||
are connected to at least one validator.
|
||||
|
||||
Config
|
||||
------
|
||||
## Config
|
||||
|
||||
Authenticated encryption is enabled by default.
|
||||
|
||||
Additional Reading
|
||||
------------------
|
||||
## Additional Reading
|
||||
|
||||
- `Implementation <https://github.com/tendermint/go-p2p/blob/master/secret_connection.go#L49>`__
|
||||
- `Original STS paper by Whitfield Diffie, Paul C. van Oorschot and
|
||||
Michael J.
|
||||
Wiener <http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.216.6107&rep=rep1&type=pdf>`__
|
||||
- `Further work on secret
|
||||
handshakes <https://dominictarr.github.io/secret-handshake-paper/shs.pdf>`__
|
||||
- [Implementation](https://github.com/tendermint/tendermint/blob/64bae01d007b5bee0d0827ab53259ffd5910b4e6/p2p/conn/secret_connection.go#L47)
|
||||
- [Original STS paper by Whitfield Diffie, Paul C. van Oorschot and
|
||||
Michael J.
|
||||
Wiener](http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.216.6107&rep=rep1&type=pdf)
|
||||
- [Further work on secret
|
||||
handshakes](https://dominictarr.github.io/secret-handshake-paper/shs.pdf)
|
@@ -31,6 +31,73 @@ For more elaborate initialization, see the tesnet command:
|
||||
tendermint testnet --help
|
||||
```
|
||||
|
||||
### Genesis
|
||||
|
||||
The `genesis.json` file in `$TMHOME/config/` defines the initial
|
||||
TendermintCore state upon genesis of the blockchain ([see
|
||||
definition](https://github.com/tendermint/tendermint/blob/master/types/genesis.go)).
|
||||
|
||||
#### Fields
|
||||
|
||||
- `genesis_time`: Official time of blockchain start.
|
||||
- `chain_id`: ID of the blockchain. This must be unique for
|
||||
every blockchain. If your testnet blockchains do not have unique
|
||||
chain IDs, you will have a bad time.
|
||||
- `validators`:
|
||||
- `pub_key`: The first element specifies the `pub_key` type. 1
|
||||
== Ed25519. The second element are the pubkey bytes.
|
||||
- `power`: The validator's voting power.
|
||||
- `name`: Name of the validator (optional).
|
||||
- `app_hash`: The expected application hash (as returned by the
|
||||
`ResponseInfo` ABCI message) upon genesis. If the app's hash does
|
||||
not match, Tendermint will panic.
|
||||
- `app_state`: The application state (e.g. initial distribution
|
||||
of tokens).
|
||||
|
||||
#### Sample genesis.json
|
||||
|
||||
```
|
||||
{
|
||||
"genesis_time": "2018-07-09T22:43:06.255718641Z",
|
||||
"chain_id": "chain-IAkWsK",
|
||||
"validators": [
|
||||
{
|
||||
"pub_key": {
|
||||
"type": "tendermint/PubKeyEd25519",
|
||||
"value": "oX8HhKsErMluxI0QWNSR8djQMSupDvHdAYrHwP7n73k="
|
||||
},
|
||||
"power": "1",
|
||||
"name": "node0"
|
||||
},
|
||||
{
|
||||
"pub_key": {
|
||||
"type": "tendermint/PubKeyEd25519",
|
||||
"value": "UZNSJA9zmeFQj36Rs296lY+WFQ4Rt6s7snPpuKypl5I="
|
||||
},
|
||||
"power": "1",
|
||||
"name": "node1"
|
||||
},
|
||||
{
|
||||
"pub_key": {
|
||||
"type": "tendermint/PubKeyEd25519",
|
||||
"value": "i9GrM6/MHB4zjCelMZBUYHNXYIzl4n0RkDCVmmLhS/o="
|
||||
},
|
||||
"power": "1",
|
||||
"name": "node2"
|
||||
},
|
||||
{
|
||||
"pub_key": {
|
||||
"type": "tendermint/PubKeyEd25519",
|
||||
"value": "0qq7954l87trEqbQV9c7d1gurnjTGMxreXc848ZZ5aw="
|
||||
},
|
||||
"power": "1",
|
||||
"name": "node3"
|
||||
}
|
||||
],
|
||||
"app_hash": ""
|
||||
}
|
||||
```
|
||||
|
||||
## Run
|
||||
|
||||
To run a Tendermint node, use
|
||||
|
@@ -1,5 +1,4 @@
|
||||
Validators
|
||||
==========
|
||||
# Validators
|
||||
|
||||
Validators are responsible for committing new blocks in the blockchain.
|
||||
These validators participate in the consensus protocol by broadcasting
|
||||
@@ -19,25 +18,22 @@ to post any collateral at all.
|
||||
Validators have a cryptographic key-pair and an associated amount of
|
||||
"voting power". Voting power need not be the same.
|
||||
|
||||
Becoming a Validator
|
||||
--------------------
|
||||
## Becoming a Validator
|
||||
|
||||
There are two ways to become validator.
|
||||
|
||||
1. They can be pre-established in the `genesis
|
||||
state <./genesis.html>`__
|
||||
2. The ABCI app responds to the EndBlock message with changes to the
|
||||
existing validator set.
|
||||
1. They can be pre-established in the [genesis state](../../tendermint-core/using-tendermint.md#genesis)
|
||||
2. The ABCI app responds to the EndBlock message with changes to the
|
||||
existing validator set.
|
||||
|
||||
Committing a Block
|
||||
------------------
|
||||
## Committing a Block
|
||||
|
||||
*+2/3 is short for "more than 2/3"*
|
||||
|
||||
A block is committed when +2/3 of the validator set sign `precommit
|
||||
votes <./block-structure.html#vote>`__ for that block at the same
|
||||
``round``. The +2/3 set of precommit votes is
|
||||
called a `*commit* <./block-structure.html#commit>`__. While any
|
||||
+2/3 set of precommits for the same block at the same height&round can
|
||||
serve as validation, the canonical commit is included in the next block
|
||||
(see `LastCommit <./block-structure.html>`__).
|
||||
A block is committed when +2/3 of the validator set sign [precommit
|
||||
votes](../spec/blockchain/blockchain.md#vote) for that block at the same `round`.
|
||||
The +2/3 set of precommit votes is called a
|
||||
[*commit*](../spec/blockchain/blockchain.md#commit). While any +2/3 set of
|
||||
precommits for the same block at the same height&round can serve as
|
||||
validation, the canonical commit is included in the next block (see
|
||||
[LastCommit](../spec/blockchain/blockchain.md#last-commit)).
|
@@ -163,6 +163,8 @@ func (s *Server) Subscribe(ctx context.Context, clientID string, query Query, ou
|
||||
return nil
|
||||
case <-ctx.Done():
|
||||
return ctx.Err()
|
||||
case <-s.Quit():
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
@@ -190,6 +192,8 @@ func (s *Server) Unsubscribe(ctx context.Context, clientID string, query Query)
|
||||
return nil
|
||||
case <-ctx.Done():
|
||||
return ctx.Err()
|
||||
case <-s.Quit():
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
@@ -211,6 +215,8 @@ func (s *Server) UnsubscribeAll(ctx context.Context, clientID string) error {
|
||||
return nil
|
||||
case <-ctx.Done():
|
||||
return ctx.Err()
|
||||
case <-s.Quit():
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
@@ -229,6 +235,8 @@ func (s *Server) PublishWithTags(ctx context.Context, msg interface{}, tags TagM
|
||||
return nil
|
||||
case <-ctx.Done():
|
||||
return ctx.Err()
|
||||
case <-s.Quit():
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -1,10 +1,10 @@
|
||||
gen_query_parser:
|
||||
@go get github.com/pointlander/peg
|
||||
go get -u -v github.com/pointlander/peg
|
||||
peg -inline -switch query.peg
|
||||
|
||||
fuzzy_test:
|
||||
@go get github.com/dvyukov/go-fuzz/go-fuzz
|
||||
@go get github.com/dvyukov/go-fuzz/go-fuzz-build
|
||||
go get -u -v github.com/dvyukov/go-fuzz/go-fuzz
|
||||
go get -u -v github.com/dvyukov/go-fuzz/go-fuzz-build
|
||||
go-fuzz-build github.com/tendermint/tendermint/libs/pubsub/query/fuzz_test
|
||||
go-fuzz -bin=./fuzz_test-fuzz.zip -workdir=./fuzz_test/output
|
||||
|
||||
|
@@ -1,6 +1,8 @@
|
||||
// nolint
|
||||
package query
|
||||
|
||||
//go:generate peg -inline -switch query.peg
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
|
10
node/node.go
10
node/node.go
@@ -486,9 +486,16 @@ func (n *Node) OnStop() {
|
||||
n.BaseService.OnStop()
|
||||
|
||||
n.Logger.Info("Stopping Node")
|
||||
|
||||
// first stop the non-reactor services
|
||||
n.eventBus.Stop()
|
||||
n.indexerService.Stop()
|
||||
|
||||
// now stop the reactors
|
||||
// TODO: gracefully disconnect from peers.
|
||||
n.sw.Stop()
|
||||
|
||||
// finally stop the listeners / external services
|
||||
for _, l := range n.rpcListeners {
|
||||
n.Logger.Info("Closing rpc listener", "listener", l)
|
||||
if err := l.Close(); err != nil {
|
||||
@@ -496,9 +503,6 @@ func (n *Node) OnStop() {
|
||||
}
|
||||
}
|
||||
|
||||
n.eventBus.Stop()
|
||||
n.indexerService.Stop()
|
||||
|
||||
if pvsc, ok := n.privValidator.(*privval.SocketPV); ok {
|
||||
if err := pvsc.Stop(); err != nil {
|
||||
n.Logger.Error("Error stopping priv validator socket client", "err", err)
|
||||
|
@@ -2,6 +2,9 @@ package node
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"syscall"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
@@ -43,6 +46,13 @@ func TestNodeStartStop(t *testing.T) {
|
||||
select {
|
||||
case <-n.Quit():
|
||||
case <-time.After(5 * time.Second):
|
||||
pid := os.Getpid()
|
||||
p, err := os.FindProcess(pid)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
err = p.Signal(syscall.SIGABRT)
|
||||
fmt.Println(err)
|
||||
t.Fatal("timed out waiting for shutdown")
|
||||
}
|
||||
}
|
||||
|
@@ -98,6 +98,6 @@ Each route is available as a GET request, as a JSONRPCv2 POST request, and via J
|
||||
# Examples
|
||||
|
||||
* [Tendermint](https://github.com/tendermint/tendermint/blob/master/rpc/core/routes.go)
|
||||
* [tm-monitor](https://github.com/tendermint/tools/blob/master/tm-monitor/rpc.go)
|
||||
* [tm-monitor](https://github.com/tendermint/tendermint/blob/master/tools/tm-monitor/rpc.go)
|
||||
*/
|
||||
package rpc
|
||||
|
41
scripts/install/install_tendermint_osx.sh
Normal file
41
scripts/install/install_tendermint_osx.sh
Normal file
@@ -0,0 +1,41 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# XXX: this script is intended to be run from
|
||||
# an MacOS machine
|
||||
|
||||
# as written, this script will install
|
||||
# tendermint core from master branch
|
||||
REPO=github.com/tendermint/tendermint
|
||||
|
||||
# change this to a specific release or branch
|
||||
BRANCH=master
|
||||
|
||||
if ! [ -x "$(command -v brew)" ]; then
|
||||
echo 'Error: brew is not installed, to install brew' >&2
|
||||
echo 'follow the instructions here: https://docs.brew.sh/Installation' >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! [ -x "$(command -v go)" ]; then
|
||||
echo 'Error: go is not installed, to install go follow' >&2
|
||||
echo 'the instructions here: https://golang.org/doc/install#tarball' >&2
|
||||
echo 'ALSO MAKE SURE TO SETUP YOUR $GOPATH and $GOBIN in your ~/.profile: https://github.com/golang/go/wiki/SettingGOPATH' >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! [ -x "$(command -v make)" ]; then
|
||||
echo 'Make not installed, installing using brew...'
|
||||
brew install make
|
||||
fi
|
||||
|
||||
# get the code and move into repo
|
||||
go get $REPO
|
||||
cd $GOPATH/src/$REPO
|
||||
|
||||
# build & install
|
||||
git checkout $BRANCH
|
||||
# XXX: uncomment if branch isn't master
|
||||
# git fetch origin $BRANCH
|
||||
make get_tools
|
||||
make get_vendor_deps
|
||||
make install
|
@@ -1,77 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
if [ "$CIRCLE_BRANCH" == "" ]; then
|
||||
echo "this script is meant to be run on CircleCI, exiting"
|
||||
echo 1
|
||||
fi
|
||||
|
||||
# check for changes in the `rpc/core` directory
|
||||
did_rpc_change=$(git diff --name-status $CIRCLE_BRANCH origin/master | grep rpc/core)
|
||||
|
||||
if [ "$did_rpc_change" == "" ]; then
|
||||
echo "no changes detected in rpc/core, exiting"
|
||||
exit 0
|
||||
else
|
||||
echo "changes detected in rpc/core, continuing"
|
||||
fi
|
||||
|
||||
# only run this script on changes to rpc/core committed to develop
|
||||
if [ "$CIRCLE_BRANCH" != "master" ]; then
|
||||
echo "the branch being built isn't master, exiting"
|
||||
exit 0
|
||||
else
|
||||
echo "on master, building the RPC docs"
|
||||
fi
|
||||
|
||||
# godoc2md used to convert the go documentation from
|
||||
# `rpc/core` into a markdown file consumed by Slate
|
||||
go get github.com/davecheney/godoc2md
|
||||
|
||||
# slate works via forks, and we'll be committing to
|
||||
# master branch, which will trigger our fork to run
|
||||
# the `./deploy.sh` and publish via the `gh-pages` branch
|
||||
slate_repo=github.com/tendermint/slate
|
||||
slate_path="$GOPATH"/src/"$slate_repo"
|
||||
|
||||
if [ ! -d "$slate_path" ]; then
|
||||
git clone https://"$slate_repo".git $slate_path
|
||||
fi
|
||||
|
||||
# the main file we need to update if rpc/core changed
|
||||
destination="$slate_path"/source/index.html.md
|
||||
|
||||
# we remove it then re-create it with the latest changes
|
||||
rm $destination
|
||||
|
||||
header="---
|
||||
title: RPC Reference
|
||||
|
||||
language_tabs:
|
||||
- shell
|
||||
- go
|
||||
|
||||
toc_footers:
|
||||
- <a href='https://tendermint.com/'>Tendermint</a>
|
||||
- <a href='https://github.com/lord/slate'>Documentation Powered by Slate</a>
|
||||
|
||||
search: true
|
||||
---"
|
||||
|
||||
# write header to the main slate file
|
||||
echo "$header" > "$destination"
|
||||
|
||||
# generate a markdown from the godoc comments, using a template
|
||||
rpc_docs=$(godoc2md -template rpc/core/doc_template.txt github.com/tendermint/tendermint/rpc/core | grep -v -e "pipe.go" -e "routes.go" -e "dev.go" | sed 's$/src/target$https://github.com/tendermint/tendermint/tree/master/rpc/core$')
|
||||
|
||||
# append core RPC docs
|
||||
echo "$rpc_docs" >> "$destination"
|
||||
|
||||
# commit the changes
|
||||
cd $slate_path
|
||||
|
||||
git config --global user.email "github@tendermint.com"
|
||||
git config --global user.name "tenderbot"
|
||||
|
||||
git commit -a -m "Update tendermint RPC docs via CircleCI"
|
||||
git push -q https://${GITHUB_ACCESS_TOKEN}@github.com/tendermint/slate.git master
|
@@ -29,9 +29,8 @@ type Genesis struct {
|
||||
ConsensusParams *types.ConsensusParams `json:"consensus_params,omitempty"`
|
||||
Validators []GenesisValidator `json:"validators"`
|
||||
AppHash cmn.HexBytes `json:"app_hash"`
|
||||
AppStateJSON json.RawMessage `json:"app_state,omitempty"`
|
||||
AppState json.RawMessage `json:"app_state,omitempty"`
|
||||
AppOptions json.RawMessage `json:"app_options,omitempty"` // DEPRECATED
|
||||
|
||||
}
|
||||
|
||||
type NodeKey struct {
|
||||
@@ -112,12 +111,12 @@ func convertGenesis(cdc *amino.Codec, jsonBytes []byte) ([]byte, error) {
|
||||
ChainID: genesis.ChainID,
|
||||
ConsensusParams: genesis.ConsensusParams,
|
||||
// Validators
|
||||
AppHash: genesis.AppHash,
|
||||
AppStateJSON: genesis.AppStateJSON,
|
||||
AppHash: genesis.AppHash,
|
||||
AppState: genesis.AppState,
|
||||
}
|
||||
|
||||
if genesis.AppOptions != nil {
|
||||
genesisNew.AppStateJSON = genesis.AppOptions
|
||||
genesisNew.AppState = genesis.AppOptions
|
||||
}
|
||||
|
||||
for _, v := range genesis.Validators {
|
||||
|
3
tools/README.md
Normal file
3
tools/README.md
Normal file
@@ -0,0 +1,3 @@
|
||||
# tools
|
||||
|
||||
Tools for working with tendermint and associated technologies. Documentation can be found in the `README.md` of each the `tm-bench/` and `tm-monitor/` directories.
|
4
tools/build/.gitignore
vendored
Normal file
4
tools/build/.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
BUILD
|
||||
RPMS
|
||||
SPECS
|
||||
tmp
|
204
tools/build/LICENSE
Normal file
204
tools/build/LICENSE
Normal file
@@ -0,0 +1,204 @@
|
||||
Tendermint Core
|
||||
License: Apache2.0
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "{}"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright 2016 All in Bits, Inc
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
289
tools/build/Makefile
Normal file
289
tools/build/Makefile
Normal file
@@ -0,0 +1,289 @@
|
||||
##
|
||||
# Extra checks, because we do not use autoconf.
|
||||
##
|
||||
|
||||
requirements_check = true
|
||||
gpg_check = false
|
||||
go_min_version = 1.9.4
|
||||
gpg_key = 2122CBE9
|
||||
|
||||
ifeq ($(requirements_check),true)
|
||||
ifndef GOPATH
|
||||
$(error GOPATH not set)
|
||||
else
|
||||
go_version := $(shell go version | sed "s/^.* go\([0-9\.]*\) .*$$/\1/" )
|
||||
$(info Found go version $(go_version))
|
||||
go_version_check := $(shell echo -e "$(go_min_version)\n$(go_version)" | sort -V | head -1)
|
||||
ifneq ($(go_min_version),$(go_version_check))
|
||||
$(error go version go_min_version or above is required)
|
||||
endif
|
||||
endif
|
||||
ifeq ($(gpg_check),true)
|
||||
gpg_check := $(shell gpg -K | grep '/$(gpg_key) ' | sed 's,^.*/\($(gpg_key)\) .*$$,\1,')
|
||||
ifneq ($(gpg_check),$(gpg_key))
|
||||
$(error GPG key $(gpg_key) not found.)
|
||||
else
|
||||
$(info GPG key $(gpg_key) found)
|
||||
endif
|
||||
ifndef GPG_PASSPHRASE
|
||||
$(error GPG_PASSPHRASE not set)
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
###
|
||||
# Here comes the real deal
|
||||
###
|
||||
|
||||
binaries = tendermint basecoind ethermint gaia
|
||||
build-binaries = build-tendermint build-basecoind build-ethermint build-gaia
|
||||
package-rpm = package-rpm-tendermint package-rpm-basecoind package-rpm-ethermint package-rpm-gaia
|
||||
install-rpm = install-rpm-tendermint install-rpm-basecoind install-rpm-ethermint install-rpm-gaia
|
||||
package-deb = package-deb-tendermint package-deb-basecoind package-deb-ethermint package-deb-gaia
|
||||
install-deb = install-deb-tendermint install-deb-basecoind install-deb-ethermint install-deb-gaia
|
||||
|
||||
all: $(binaries)
|
||||
build: $(build-binaries)
|
||||
package: $(package-rpm) $(package-deb)
|
||||
install: $(install-rpm) $(install-deb)
|
||||
$(binaries): %: build-% package-rpm-% package-deb-%
|
||||
|
||||
###
|
||||
# Build the binaries
|
||||
###
|
||||
|
||||
git-branch:
|
||||
$(eval GIT_BRANCH=$(shell echo $${GIT_BRANCH:-master}))
|
||||
|
||||
gopath-setup:
|
||||
test -d $(GOPATH) || mkdir -p $(GOPATH)
|
||||
test -d $(GOPATH)/bin || mkdir -p $(GOPATH)/bin
|
||||
test -d $(GOPATH)/src || mkdir -p $(GOPATH)/src
|
||||
|
||||
build-tendermint: git-branch gopath-setup
|
||||
@echo "*** Building tendermint"
|
||||
go get -d -u github.com/tendermint/tendermint/cmd/tendermint
|
||||
cd $(GOPATH)/src/github.com/tendermint/tendermint && git checkout "$(GIT_BRANCH)" && git pull
|
||||
export PATH=$(GOPATH)/bin:$(PATH) && $(MAKE) -C $(GOPATH)/src/github.com/tendermint/tendermint get_tools get_vendor_deps build
|
||||
cp $(GOPATH)/src/github.com/tendermint/tendermint/build/tendermint $(GOPATH)/bin
|
||||
@echo "*** Built tendermint"
|
||||
|
||||
build-ethermint: git-branch gopath-setup
|
||||
@echo "*** Building ethermint"
|
||||
go get -d -u github.com/tendermint/ethermint/cmd/ethermint
|
||||
cd $(GOPATH)/src/github.com/tendermint/ethermint && git checkout "$(GIT_BRANCH)" && git pull
|
||||
export PATH=$(GOPATH)/bin:$(PATH) && $(MAKE) -C $(GOPATH)/src/github.com/tendermint/ethermint get_vendor_deps build
|
||||
cp $(GOPATH)/src/github.com/tendermint/ethermint/build/ethermint $(GOPATH)/bin
|
||||
@echo "*** Built ethermint"
|
||||
|
||||
build-gaia: git-branch gopath-setup
|
||||
@echo "*** Building gaia"
|
||||
go get -d -u go github.com/cosmos/gaia || echo "Workaround for go downloads."
|
||||
cd $(GOPATH)/src/github.com/cosmos/gaia && git checkout "$(GIT_BRANCH)" && git pull
|
||||
export PATH=$(GOPATH)/bin:$(PATH) && $(MAKE) -C $(GOPATH)/src/github.com/cosmos/gaia get_vendor_deps install
|
||||
@echo "*** Built gaia"
|
||||
|
||||
build-basecoind: git-branch gopath-setup
|
||||
@echo "*** Building basecoind from cosmos-sdk"
|
||||
go get -d -u github.com/cosmos/cosmos-sdk/examples/basecoin/cmd/basecoind
|
||||
cd $(GOPATH)/src/github.com/cosmos/cosmos-sdk && git checkout "$(GIT_BRANCH)" && git pull
|
||||
export PATH=$(GOPATH)/bin:$(PATH) && $(MAKE) -C $(GOPATH)/src/github.com/cosmos/cosmos-sdk get_tools get_vendor_deps build
|
||||
cp $(GOPATH)/src/github.com/cosmos/cosmos-sdk/build/basecoind $(GOPATH)/bin/basecoind
|
||||
@echo "*** Built basecoind from cosmos-sdk"
|
||||
|
||||
###
|
||||
# Prepare package files
|
||||
###
|
||||
|
||||
# set app_version
|
||||
version-%:
|
||||
@echo "Checking if binary exists"
|
||||
test -f $(GOPATH)/bin/$*
|
||||
@echo "BUILD_NUMBER is $(BUILD_NUMBER)"
|
||||
test -n "$(BUILD_NUMBER)"
|
||||
$(eval $*_version=$(shell $(GOPATH)/bin/$* version | head -1 | cut -d- -f1 | sed 's/^\(ethermint:\s*\|\)\(v\|\)//' | tr -d '\t ' ))
|
||||
|
||||
# set build_folder
|
||||
folder-%: version-%
|
||||
$(eval build_folder=BUILD/$*-$($*_version)-$(BUILD_NUMBER))
|
||||
|
||||
# clean up folder structure for package files
|
||||
prepare-files = rm -rf $(build_folder) && mkdir -p $(build_folder) && cp -r ./$(1)/* $(build_folder) && mkdir -p $(build_folder)/usr/bin && cp $(GOPATH)/bin/$(1) $(build_folder)/usr/bin
|
||||
|
||||
##
|
||||
## Package customizations for the different applications
|
||||
##
|
||||
|
||||
prepare-tendermint =
|
||||
prepare-ethermint = mkdir -p $(build_folder)/etc/ethermint && \
|
||||
cp $(GOPATH)/src/github.com/tendermint/ethermint/setup/genesis.json $(build_folder)/etc/ethermint/genesis.json && \
|
||||
cp -r $(GOPATH)/src/github.com/tendermint/ethermint/setup/keystore $(build_folder)/etc/ethermint
|
||||
prepare-gaia =
|
||||
prepare-basecoind = cp $(GOPATH)/bin/basecoind $(build_folder)/usr/bin
|
||||
|
||||
###
|
||||
# Package the binary for CentOS/RedHat (RPM) and Debian/Ubuntu (DEB)
|
||||
###
|
||||
|
||||
# Depends on rpmbuild, sorry, this can only be built on CentOS/RedHat machines.
|
||||
package-rpm-%: folder-%
|
||||
@echo "*** Packaging RPM $* version $($*_version)"
|
||||
|
||||
$(call prepare-files,$*)
|
||||
$(call prepare-$*)
|
||||
|
||||
rm -rf $(build_folder)/DEBIAN
|
||||
mkdir -p $(build_folder)/usr/share/licenses/$*
|
||||
cp ./LICENSE $(build_folder)/usr/share/licenses/$*/LICENSE
|
||||
chmod -Rf a+rX,u+w,g-w,o-w $(build_folder)
|
||||
|
||||
mkdir -p {SPECS,tmp}
|
||||
|
||||
./generate-spec $* spectemplates SPECS
|
||||
sed -i "s/@VERSION@/$($*_version)/" SPECS/$*.spec
|
||||
sed -i "s/@BUILD_NUMBER@/$(BUILD_NUMBER)/" SPECS/$*.spec
|
||||
sed -i "s/@PACKAGE_NAME@/$*/" SPECS/$*.spec
|
||||
|
||||
rpmbuild -bb SPECS/$*.spec --define "_topdir `pwd`" --define "_tmppath `pwd`/tmp"
|
||||
./sign RPMS/x86_64/$*-$($*_version)-$(BUILD_NUMBER).x86_64.rpm "$(gpg_key)" "`which gpg`"
|
||||
rpm -Kv RPMS/x86_64/$*-$($*_version)-$(BUILD_NUMBER).x86_64.rpm || echo "rpm returns non-zero exist for some reason. ($?)"
|
||||
@echo "*** Packaged RPM $* version $($*_version)"
|
||||
|
||||
package-deb-%: folder-%
|
||||
@echo "*** Packaging DEB $* version $($*_version)-$(BUILD_NUMBER)"
|
||||
|
||||
$(call prepare-files,$*)
|
||||
$(call prepare-$*)
|
||||
|
||||
mkdir -p $(build_folder)/usr/share/doc/$*
|
||||
cp $(build_folder)/DEBIAN/copyright $(build_folder)/usr/share/doc/$*
|
||||
chmod -Rf a+rX,u+w,g-w,o-w $(build_folder)
|
||||
|
||||
sed -i "s/@VERSION@/$($*_version)-$(BUILD_NUMBER)/" $(build_folder)/DEBIAN/changelog
|
||||
sed -i "s/@STABILITY@/stable/" $(build_folder)/DEBIAN/changelog
|
||||
sed -i "s/@DATETIMESTAMP@/`date +%a,\ %d\ %b\ %Y\ %T\ %z`/" $(build_folder)/DEBIAN/changelog
|
||||
sed -i "s/@VERSION@/$($*_version)-$(BUILD_NUMBER)/" $(build_folder)/DEBIAN/control
|
||||
|
||||
gzip -c $(build_folder)/DEBIAN/changelog > $(build_folder)/usr/share/doc/$*/changelog.Debian.gz
|
||||
gzip -c $(build_folder)/DEBIAN/changelog > $(build_folder)/usr/share/doc/$*/changelog.Debian.amd64.gz
|
||||
sed -i "s/@INSTALLEDSIZE@/`du -ks $(build_folder) | cut -f 1`/" $(build_folder)/DEBIAN/control
|
||||
|
||||
cd $(build_folder) && tar --owner=root --group=root -cvJf ../../tmp/data.tar.xz --exclude DEBIAN *
|
||||
cd $(build_folder)/DEBIAN && tar --owner=root --group=root -cvzf ../../../tmp/control.tar.gz *
|
||||
echo "2.0" > tmp/debian-binary
|
||||
|
||||
cp ./_gpg tmp/
|
||||
cd tmp && sed -i "s/@DATETIMESTAMP@/`date +%a\ %b\ %d\ %T\ %Y`/" _gpg
|
||||
cd tmp && sed -i "s/@BINMD5@/`md5sum debian-binary | cut -d\ -f1`/" _gpg
|
||||
cd tmp && sed -i "s/@BINSHA1@/`sha1sum debian-binary | cut -d\ -f1`/" _gpg
|
||||
cd tmp && sed -i "s/@BINSIZE@/`stat -c %s debian-binary | cut -d\ -f1`/" _gpg
|
||||
cd tmp && sed -i "s/@CONMD5@/`md5sum control.tar.gz | cut -d\ -f1`/" _gpg
|
||||
cd tmp && sed -i "s/@CONSHA1@/`sha1sum control.tar.gz | cut -d\ -f1`/" _gpg
|
||||
cd tmp && sed -i "s/@CONSIZE@/`stat -c %s control.tar.gz | cut -d\ -f1`/" _gpg
|
||||
cd tmp && sed -i "s/@DATMD5@/`md5sum data.tar.xz | cut -d\ -f1`/" _gpg
|
||||
cd tmp && sed -i "s/@DATSHA1@/`sha1sum data.tar.xz | cut -d\ -f1`/" _gpg
|
||||
cd tmp && sed -i "s/@DATSIZE@/`stat -c %s data.tar.xz | cut -d\ -f1`/" _gpg
|
||||
gpg --batch --passphrase "$(GPG_PASSPHRASE)" --clearsign tmp/_gpg
|
||||
mv tmp/_gpg.asc tmp/_gpgbuilder
|
||||
ar r tmp/$*-$($*_version)-$(BUILD_NUMBER)_amd64.deb tmp/debian-binary tmp/control.tar.gz tmp/data.tar.xz tmp/_gpgbuilder
|
||||
mv tmp/$*-$($*_version)-$(BUILD_NUMBER)_amd64.deb RPMS/
|
||||
rm tmp/debian-binary tmp/control.tar.gz tmp/data.tar.xz tmp/_gpgbuilder tmp/_gpg
|
||||
@echo "*** Packaged DEB $* version $($*_version)-$(BUILD_NUMBER)"
|
||||
|
||||
install-rpm-%: version-%
|
||||
#Make sure your host has the IAM role to read/write the S3 bucket OR that you set up ~/.boto
|
||||
@echo "*** Uploading $*-$($*_version)-$(BUILD_NUMBER).x86_64.rpm to AWS $(DEVOPS_PATH)CentOS repository"
|
||||
aws s3 sync s3://tendermint-packages/$(DEVOPS_PATH)centos/ tmp/s3/ --delete
|
||||
mkdir -p tmp/s3/7/os/x86_64/Packages
|
||||
cp RPMS/x86_64/$*-$($*_version)-$(BUILD_NUMBER).x86_64.rpm tmp/s3/7/os/x86_64/Packages
|
||||
cp ./RPM-GPG-KEY-Tendermint tmp/s3/7/os/x86_64/
|
||||
cp ./tendermint.repo tmp/s3/7/os/x86_64/
|
||||
rm -f tmp/s3/7/os/x86_64/repodata/*.bz2 tmp/s3/7/os/x86_64/repodata/*.gz tmp/s3/7/os/x86_64/repodata/repomd.xml.asc
|
||||
createrepo tmp/s3/7/os/x86_64/Packages -u https://tendermint-packages.interblock.io/$(DEVOPS_PATH)centos/7/os/x86_64/Packages -o tmp/s3/7/os/x86_64 --update -S --repo Tendermint --content tendermint --content basecoind --content ethermint
|
||||
gpg --batch --passphrase "$(GPG_PASSPHRASE)" --detach-sign -a tmp/s3/7/os/x86_64/repodata/repomd.xml
|
||||
aws s3 sync tmp/s3/ s3://tendermint-packages/$(DEVOPS_PATH)centos/ --delete --acl public-read
|
||||
@echo "*** Uploaded $* to AWS $(DEVOPS_PATH)CentOS repository"
|
||||
|
||||
install-deb-%: version-%
|
||||
@echo "*** Uploading $*-$($*_version)-$(BUILD_NUMBER)_amd64.deb to AWS $(DEVOPS_PATH)Debian repository"
|
||||
@echo "Testing if $*-$($*_version)-$(BUILD_NUMBER)_amd64.deb is already uploaded"
|
||||
test ! -f tmp/debian-s3/pool/$*-$($*_version)-$(BUILD_NUMBER)_amd64.deb
|
||||
aws s3 sync s3://tendermint-packages/$(DEVOPS_PATH)debian/ tmp/debian-s3/ --delete
|
||||
@echo "Testing if $*-$($*_version)-$(BUILD_NUMBER)_amd64.deb is already uploaded"
|
||||
test ! -f tmp/debian-s3/pool/$*-$($*_version)-$(BUILD_NUMBER)_amd64.deb
|
||||
cp ./tendermint.list tmp/debian-s3/
|
||||
mkdir -p tmp/debian-s3/pool tmp/debian-s3/dists/stable/main/binary-amd64
|
||||
cp RPMS/$*-$($*_version)-$(BUILD_NUMBER)_amd64.deb tmp/debian-s3/pool
|
||||
cp ./Release_amd64 tmp/debian-s3/dists/stable/main/binary-amd64/Release
|
||||
|
||||
#Packages / Packages.gz
|
||||
|
||||
echo > tmp/Package
|
||||
echo "Filename: pool/$*-$($*_version)-$(BUILD_NUMBER)_amd64.deb" >> tmp/Package
|
||||
echo "MD5sum: `md5sum RPMS/$*-$($*_version)-$(BUILD_NUMBER)_amd64.deb | cut -d\ -f 1`" >> tmp/Package
|
||||
echo "SHA1: `sha1sum RPMS/$*-$($*_version)-$(BUILD_NUMBER)_amd64.deb | cut -d\ -f 1`" >> tmp/Package
|
||||
echo "SHA256: `sha256sum RPMS/$*-$($*_version)-$(BUILD_NUMBER)_amd64.deb | cut -d\ -f 1`" >> tmp/Package
|
||||
echo "Size: `stat -c %s RPMS/$*-$($*_version)-$(BUILD_NUMBER)_amd64.deb | cut -d\ -f 1`" >> tmp/Package
|
||||
cat BUILD/$*-$($*_version)-$(BUILD_NUMBER)/DEBIAN/control >> tmp/Package
|
||||
|
||||
cat tmp/Package >> tmp/debian-s3/dists/stable/main/binary-amd64/Packages
|
||||
rm -f tmp/debian-s3/dists/stable/main/binary-amd64/Packages.gz
|
||||
gzip -c tmp/debian-s3/dists/stable/main/binary-amd64/Packages > tmp/debian-s3/dists/stable/main/binary-amd64/Packages.gz
|
||||
rm -f tmp/Package
|
||||
|
||||
#main / Release / InRelease / Release.gpg
|
||||
|
||||
cp ./Release tmp/debian-s3/dists/stable/main/Release
|
||||
rm -f tmp/debian-s3/dists/stable/main/InRelease
|
||||
rm -f tmp/debian-s3/dists/stable/main/Release.gpg
|
||||
|
||||
echo "MD5Sum:" >> tmp/debian-s3/dists/stable/main/Release
|
||||
cd tmp/debian-s3/dists/stable/main && for f in `find . -type f | sed 's/^.\///'` ; do test "$$f" == "Release" && continue ; echo -n " " ; md5sum $$f | sed "s/ / `stat -c %s $$f` /" ; done >> Release
|
||||
echo "SHA1:" >> tmp/debian-s3/dists/stable/main/Release
|
||||
cd tmp/debian-s3/dists/stable/main && for f in `find . -type f | sed 's/^.\///'` ; do test "$$f" == "Release" && continue ; echo -n " " ; sha1sum $$f | sed "s/ / `stat -c %s $$f` /" ; done >> Release
|
||||
echo "SHA256:" >> tmp/debian-s3/dists/stable/main/Release
|
||||
cd tmp/debian-s3/dists/stable/main && for f in `find . -type f | sed 's/^.\///'` ; do test "$$f" == "Release" && continue ; echo -n " " ; sha256sum $$f | sed "s/ / `stat -c %s $$f` /" ; done >> Release
|
||||
|
||||
gpg --batch --passphrase "$(GPG_PASSPHRASE)" --digest-algo SHA256 -b -a tmp/debian-s3/dists/stable/main/Release
|
||||
mv tmp/debian-s3/dists/stable/main/Release.asc tmp/debian-s3/dists/stable/main/Release.gpg
|
||||
gpg --batch --passphrase "$(GPG_PASSPHRASE)" --digest-algo SHA512 --clearsign tmp/debian-s3/dists/stable/main/Release
|
||||
mv tmp/debian-s3/dists/stable/main/Release.asc tmp/debian-s3/dists/stable/main/InRelease
|
||||
|
||||
#stable / Release / InRelease / Release.gpg
|
||||
|
||||
cp ./Release tmp/debian-s3/dists/stable/Release
|
||||
rm -f tmp/debian-s3/dists/stable/InRelease
|
||||
rm -f tmp/debian-s3/dists/stable/Release.gpg
|
||||
|
||||
echo "MD5Sum:" >> tmp/debian-s3/dists/stable/Release
|
||||
cd tmp/debian-s3/dists/stable && for f in `find . -type f | sed 's/^.\///'` ; do test "$$f" == "Release" && continue ; echo -n " " ; md5sum $$f | sed "s/ / `stat -c %s $$f` /" ; done >> Release
|
||||
echo "SHA1:" >> tmp/debian-s3/dists/stable/Release
|
||||
cd tmp/debian-s3/dists/stable && for f in `find . -type f | sed 's/^.\///'` ; do test "$$f" == "Release" && continue ; echo -n " " ; sha1sum $$f | sed "s/ / `stat -c %s $$f` /" ; done >> Release
|
||||
echo "SHA256:" >> tmp/debian-s3/dists/stable/Release
|
||||
cd tmp/debian-s3/dists/stable && for f in `find . -type f | sed 's/^.\///'` ; do test "$$f" == "Release" && continue ; echo -n " " ; sha256sum $$f | sed "s/ / `stat -c %s $$f` /" ; done >> Release
|
||||
|
||||
gpg --batch --passphrase "$(GPG_PASSPHRASE)" --digest-algo SHA256 -b -a tmp/debian-s3/dists/stable/Release
|
||||
mv tmp/debian-s3/dists/stable/Release.asc tmp/debian-s3/dists/stable/Release.gpg
|
||||
gpg --batch --passphrase "$(GPG_PASSPHRASE)" --digest-algo SHA512 --clearsign tmp/debian-s3/dists/stable/Release
|
||||
mv tmp/debian-s3/dists/stable/Release.asc tmp/debian-s3/dists/stable/InRelease
|
||||
|
||||
aws s3 sync tmp/debian-s3/ s3://tendermint-packages/$(DEVOPS_PATH)debian/ --delete --acl public-read
|
||||
@echo "*** Uploaded $*-$($*_version)-$(BUILD_NUMBER)_amd64.deb to AWS $(DEVOPS_PATH)Debian repository"
|
||||
|
||||
mostlyclean:
|
||||
rm -rf {BUILDROOT,SOURCES,SPECS,SRPMS,tmp}
|
||||
|
||||
clean: mostlyclean
|
||||
rm -rf {BUILD,RPMS}
|
||||
|
||||
distclean: clean
|
||||
rm -rf $(GOPATH)/src/github.com/tendermint/tendermint
|
||||
rm -rf $(GOPATH)/src/github.com/cosmos/cosmos-sdk
|
||||
rm -rf $(GOPATH)/src/github.com/tendermint/ethermint
|
||||
rm -rf $(GOPATH)/bin/tendermint
|
||||
rm -rf $(GOPATH)/bin/basecoind
|
||||
rm -rf $(GOPATH)/bin/ethermint
|
||||
rm -rf $(GOPATH)/bin/gaia
|
||||
|
||||
.PHONY : clean
|
||||
|
19
tools/build/RPM-GPG-KEY-Tendermint
Normal file
19
tools/build/RPM-GPG-KEY-Tendermint
Normal file
@@ -0,0 +1,19 @@
|
||||
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||
Version: GnuPG v2.0.22 (GNU/Linux)
|
||||
|
||||
mQENBFk97ngBCADaiPQFKJI7zWYdUKqC490DzY9g9LatsWoJErK5LuMXwEnF5i+a
|
||||
UkygueukA4C5U7L71l5EeOB9rtb6AbkF4IEZsmmp93APec/3Vfbac9xvK4dBdiht
|
||||
F8SrazPdHeR6AKcZH8ZpG/+mdONvGb/gEgtxVjaeIJFpCbjKLlKEXazh2zamhhth
|
||||
q+Nn/17QmI3KBiaGqQK5w4kGZ4mZPy6fXMQhW5dDMq9f4anlGIAYi9O53dVxsx2S
|
||||
5d+NHuGer5Ps0u6WMJi/e+UT2EGwzP6ygOxkIjyhMFuVftabOtSSrRHHetw8UAaI
|
||||
N/RPn2gSbQtOQ7unzHDXp3/o6/r2nDEErPyJABEBAAG0LkdyZWcgU3phYm8gKFRl
|
||||
bmRlcm1pbnQpIDxncmVnQHBoaWxvc29iZWFyLmNvbT6JATkEEwECACMFAlk97ngC
|
||||
GwMHCwkIBwMCAQYVCAIJCgsEFgIDAQIeAQIXgAAKCRDIkIHIISLL6bX/CACXTKmO
|
||||
u5XgvJICH0pHNeVS5/4Om1Rsg1xNmEkGFBP8N2fqn576exbOLgWLSyNHTEyrJNoc
|
||||
iTeUtod2qqbVGwRgWm1zeiP8NBYiQ9SUbqskIqcPavJNGWIxsCB0p/odoZah8xSj
|
||||
tGrkoyoxrc+7z2JgKYK8SVSkJXQkzuc5/ZlY85ci5gPKQhlo5YDqGo+4U9n/Ieo5
|
||||
nkF8LBalFC2j7A7sQNroEicpulpGhIq3jyUHtadX01z3pNzuX+wfHX9futoet0YS
|
||||
tG2007WoPGV0whGnoKxmk0JhwzhscC2XNtJl1GZcwqOOlPU9eGtZuPKj/HBAlRtz
|
||||
4xTOAcklpg8soqRA
|
||||
=jNDW
|
||||
-----END PGP PUBLIC KEY BLOCK-----
|
7
tools/build/Release
Normal file
7
tools/build/Release
Normal file
@@ -0,0 +1,7 @@
|
||||
Origin: Tendermint
|
||||
Label: Tendermint
|
||||
Suite: stable
|
||||
Date: Fri, 16 Jun 2017 19:44:00 UTC
|
||||
Architectures: amd64
|
||||
Components: main
|
||||
Description: Tendermint repository
|
5
tools/build/Release_amd64
Normal file
5
tools/build/Release_amd64
Normal file
@@ -0,0 +1,5 @@
|
||||
Archive: stable
|
||||
Component: main
|
||||
Origin: Tendermint
|
||||
Label: Tendermint
|
||||
Architecture: amd64
|
8
tools/build/_gpg
Normal file
8
tools/build/_gpg
Normal file
@@ -0,0 +1,8 @@
|
||||
Version: 4
|
||||
Signer:
|
||||
Date: @DATETIMESTAMP@
|
||||
Role: builder
|
||||
Files:
|
||||
@BINMD5@ @BINSHA1@ @BINSIZE@ debian-binary
|
||||
@CONMD5@ @CONSHA1@ @CONSIZE@ control.tar.gz
|
||||
@DATMD5@ @DATSHA1@ @DATSIZE@ data.tar.xz
|
6
tools/build/basecoind/DEBIAN/changelog
Normal file
6
tools/build/basecoind/DEBIAN/changelog
Normal file
@@ -0,0 +1,6 @@
|
||||
basecoind (@VERSION@) @STABILITY@; urgency=medium
|
||||
|
||||
* Automatic build. See https://github.com/cosmos/cosmos-sdk for more information.
|
||||
|
||||
-- Greg Szabo <greg@philosobear.com> @DATETIMESTAMP@
|
||||
|
1
tools/build/basecoind/DEBIAN/compat
Normal file
1
tools/build/basecoind/DEBIAN/compat
Normal file
@@ -0,0 +1 @@
|
||||
9
|
14
tools/build/basecoind/DEBIAN/control
Normal file
14
tools/build/basecoind/DEBIAN/control
Normal file
@@ -0,0 +1,14 @@
|
||||
Source: basecoind
|
||||
Section: net
|
||||
Priority: optional
|
||||
Maintainer: Greg Szabo <greg@philosobear.com>
|
||||
Build-Depends: debhelper (>=9)
|
||||
Standards-Version: 3.9.6
|
||||
Homepage: https://tendermint.com
|
||||
Package: basecoind
|
||||
Architecture: amd64
|
||||
Version: @VERSION@
|
||||
Installed-Size: @INSTALLEDSIZE@
|
||||
Description: basecoind is a Proof-of-Stake cryptocurrency and framework
|
||||
Basecoind is an ABCI application designed to be used with the Tendermint consensus engine to form a Proof-of-Stake cryptocurrency. It also provides a general purpose framework for extending the feature-set of the cryptocurrency by implementing plugins.
|
||||
|
21
tools/build/basecoind/DEBIAN/copyright
Normal file
21
tools/build/basecoind/DEBIAN/copyright
Normal file
@@ -0,0 +1,21 @@
|
||||
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
|
||||
Upstream-Name: basecoind
|
||||
Source: https://github.com/cosmos/cosmos-sdk
|
||||
|
||||
Files: *
|
||||
Copyright: 2017 All In Bits, Inc.
|
||||
License: Apache-2.0
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
.
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
.
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
.
|
||||
On Debian systems, the full text of the Apache License 2.0 can be found
|
||||
in the file `/usr/share/common-licenses/Apache-2.0'.
|
41
tools/build/basecoind/DEBIAN/postinst
Normal file
41
tools/build/basecoind/DEBIAN/postinst
Normal file
@@ -0,0 +1,41 @@
|
||||
#!/bin/sh
|
||||
# postinst script for basecoind
|
||||
#
|
||||
|
||||
set -e
|
||||
|
||||
# summary of how this script can be called:
|
||||
# * <postinst> `configure' <most-recently-configured-version>
|
||||
# * <old-postinst> `abort-upgrade' <new version>
|
||||
# * <conflictor's-postinst> `abort-remove' `in-favour' <package>
|
||||
# <new-version>
|
||||
# * <postinst> `abort-remove'
|
||||
# * <deconfigured's-postinst> `abort-deconfigure' `in-favour'
|
||||
# <failed-install-package> <version> `removing'
|
||||
# <conflicting-package> <version>
|
||||
# for details, see https://www.debian.org/doc/debian-policy/ or
|
||||
# the debian-policy package
|
||||
|
||||
|
||||
case "$1" in
|
||||
configure)
|
||||
chown basecoind.basecoind /etc/basecoind
|
||||
sudo -Hu basecoind basecoind node init --home /etc/basecoind 2B24DEE2364762300168DF19B6C18BCE2D399EA2
|
||||
systemctl daemon-reload
|
||||
;;
|
||||
|
||||
abort-upgrade|abort-remove|abort-deconfigure)
|
||||
;;
|
||||
|
||||
*)
|
||||
echo "postinst called with unknown argument \`$1'" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
# dh_installdeb will replace this with shell code automatically
|
||||
# generated by other debhelper scripts.
|
||||
|
||||
#DEBHELPER#
|
||||
|
||||
exit 0
|
41
tools/build/basecoind/DEBIAN/postrm
Normal file
41
tools/build/basecoind/DEBIAN/postrm
Normal file
@@ -0,0 +1,41 @@
|
||||
#!/bin/sh
|
||||
# postrm script for basecoin
|
||||
#
|
||||
|
||||
set -e
|
||||
|
||||
# summary of how this script can be called:
|
||||
# * <postrm> `remove'
|
||||
# * <postrm> `purge'
|
||||
# * <old-postrm> `upgrade' <new-version>
|
||||
# * <new-postrm> `failed-upgrade' <old-version>
|
||||
# * <new-postrm> `abort-install'
|
||||
# * <new-postrm> `abort-install' <old-version>
|
||||
# * <new-postrm> `abort-upgrade' <old-version>
|
||||
# * <disappearer's-postrm> `disappear' <overwriter>
|
||||
# <overwriter-version>
|
||||
# for details, see https://www.debian.org/doc/debian-policy/ or
|
||||
# the debian-policy package
|
||||
|
||||
|
||||
case "$1" in
|
||||
upgrade|failed-upgrade|abort-upgrade)
|
||||
systemctl daemon-reload
|
||||
;;
|
||||
|
||||
purge|remove|abort-install|disappear)
|
||||
systemctl daemon-reload
|
||||
;;
|
||||
|
||||
*)
|
||||
echo "postrm called with unknown argument \`$1'" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
# dh_installdeb will replace this with shell code automatically
|
||||
# generated by other debhelper scripts.
|
||||
|
||||
#DEBHELPER#
|
||||
|
||||
exit 0
|
38
tools/build/basecoind/DEBIAN/preinst
Normal file
38
tools/build/basecoind/DEBIAN/preinst
Normal file
@@ -0,0 +1,38 @@
|
||||
#!/bin/sh
|
||||
# preinst script for basecoind
|
||||
#
|
||||
|
||||
set -e
|
||||
|
||||
# summary of how this script can be called:
|
||||
# * <new-preinst> `install'
|
||||
# * <new-preinst> `install' <old-version>
|
||||
# * <new-preinst> `upgrade' <old-version>
|
||||
# * <old-preinst> `abort-upgrade' <new-version>
|
||||
# for details, see https://www.debian.org/doc/debian-policy/ or
|
||||
# the debian-policy package
|
||||
|
||||
|
||||
case "$1" in
|
||||
install|upgrade)
|
||||
if ! grep -q '^basecoind:' /etc/passwd ; then
|
||||
useradd -k /dev/null -r -m -b /etc basecoind
|
||||
chmod 755 /etc/basecoind
|
||||
fi
|
||||
;;
|
||||
|
||||
abort-upgrade)
|
||||
;;
|
||||
|
||||
*)
|
||||
echo "preinst called with unknown argument \`$1'" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
# dh_installdeb will replace this with shell code automatically
|
||||
# generated by other debhelper scripts.
|
||||
|
||||
#DEBHELPER#
|
||||
|
||||
exit 0
|
38
tools/build/basecoind/DEBIAN/prerm
Normal file
38
tools/build/basecoind/DEBIAN/prerm
Normal file
@@ -0,0 +1,38 @@
|
||||
#!/bin/sh
|
||||
# prerm script for basecoin
|
||||
#
|
||||
|
||||
set -e
|
||||
|
||||
# summary of how this script can be called:
|
||||
# * <prerm> `remove'
|
||||
# * <old-prerm> `upgrade' <new-version>
|
||||
# * <new-prerm> `failed-upgrade' <old-version>
|
||||
# * <conflictor's-prerm> `remove' `in-favour' <package> <new-version>
|
||||
# * <deconfigured's-prerm> `deconfigure' `in-favour'
|
||||
# <package-being-installed> <version> `removing'
|
||||
# <conflicting-package> <version>
|
||||
# for details, see https://www.debian.org/doc/debian-policy/ or
|
||||
# the debian-policy package
|
||||
|
||||
|
||||
case "$1" in
|
||||
remove|upgrade|deconfigure)
|
||||
systemctl stop basecoind 2> /dev/null || :
|
||||
;;
|
||||
|
||||
failed-upgrade)
|
||||
;;
|
||||
|
||||
*)
|
||||
echo "prerm called with unknown argument \`$1'" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
# dh_installdeb will replace this with shell code automatically
|
||||
# generated by other debhelper scripts.
|
||||
|
||||
#DEBHELPER#
|
||||
|
||||
exit 0
|
@@ -0,0 +1,2 @@
|
||||
disable basecoind.service
|
||||
|
18
tools/build/basecoind/etc/systemd/system/basecoind.service
Normal file
18
tools/build/basecoind/etc/systemd/system/basecoind.service
Normal file
@@ -0,0 +1,18 @@
|
||||
[Unit]
|
||||
Description=Basecoind
|
||||
Requires=network-online.target
|
||||
After=network-online.target
|
||||
|
||||
[Service]
|
||||
Environment="BCHOME=/etc/basecoind"
|
||||
Restart=on-failure
|
||||
User=basecoind
|
||||
Group=basecoind
|
||||
PermissionsStartOnly=true
|
||||
ExecStart=/usr/bin/basecoind start
|
||||
ExecReload=/bin/kill -HUP $MAINPID
|
||||
KillSignal=SIGTERM
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
|
12
tools/build/basecoind/usr/share/basecoind/key.json
Normal file
12
tools/build/basecoind/usr/share/basecoind/key.json
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"address": "1B1BE55F969F54064628A63B9559E7C21C925165",
|
||||
"priv_key": {
|
||||
"type": "ed25519",
|
||||
"data": "C70D6934B4F55F1B7BC33B56B9CA8A2061384AFC19E91E44B40C4BBA182953D1619D3678599971ED29C7529DDD4DA537B97129893598A17C82E3AC9A8BA95279"
|
||||
},
|
||||
"pub_key": {
|
||||
"type": "ed25519",
|
||||
"data": "619D3678599971ED29C7529DDD4DA537B97129893598A17C82E3AC9A8BA95279"
|
||||
}
|
||||
}
|
||||
|
12
tools/build/basecoind/usr/share/basecoind/key2.json
Normal file
12
tools/build/basecoind/usr/share/basecoind/key2.json
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"address": "1DA7C74F9C219229FD54CC9F7386D5A3839F0090",
|
||||
"priv_key": {
|
||||
"type": "ed25519",
|
||||
"data": "34BAE9E65CE8245FAD035A0E3EED9401BDE8785FFB3199ACCF8F5B5DDF7486A8352195DA90CB0B90C24295B90AEBA25A5A71BC61BAB2FE2387241D439698B7B8"
|
||||
},
|
||||
"pub_key": {
|
||||
"type": "ed25519",
|
||||
"data": "352195DA90CB0B90C24295B90AEBA25A5A71BC61BAB2FE2387241D439698B7B8"
|
||||
}
|
||||
}
|
||||
|
6
tools/build/ethermint/DEBIAN/changelog
Normal file
6
tools/build/ethermint/DEBIAN/changelog
Normal file
@@ -0,0 +1,6 @@
|
||||
ethermint (@VERSION@) @STABILITY@; urgency=medium
|
||||
|
||||
* Automatic build. See https://github.com/tendermint/tendermint for more information.
|
||||
|
||||
-- Greg Szabo <greg@philosobear.com> @DATETIMESTAMP@
|
||||
|
1
tools/build/ethermint/DEBIAN/compat
Normal file
1
tools/build/ethermint/DEBIAN/compat
Normal file
@@ -0,0 +1 @@
|
||||
9
|
15
tools/build/ethermint/DEBIAN/control
Normal file
15
tools/build/ethermint/DEBIAN/control
Normal file
@@ -0,0 +1,15 @@
|
||||
Source: ethermint
|
||||
Section: net
|
||||
Priority: optional
|
||||
Maintainer: Greg Szabo <greg@philosobear.com>
|
||||
Build-Depends: debhelper (>=9)
|
||||
Depends: tendermint (>=0.11.0)
|
||||
Standards-Version: 3.9.6
|
||||
Homepage: https://tendermint.com
|
||||
Package: ethermint
|
||||
Architecture: amd64
|
||||
Version: @VERSION@
|
||||
Installed-Size: @INSTALLEDSIZE@
|
||||
Description: ethermint enables ethereum as an ABCI application on tendermint and the COSMOS hub
|
||||
Ethermint enables ethereum to run as an ABCI application on tendermint and the COSMOS hub. This application allows you to get all the benefits of ethereum without having to run your own miners.
|
||||
|
21
tools/build/ethermint/DEBIAN/copyright
Normal file
21
tools/build/ethermint/DEBIAN/copyright
Normal file
@@ -0,0 +1,21 @@
|
||||
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
|
||||
Upstream-Name: ethermint
|
||||
Source: https://github.com/tendermint/ethermint
|
||||
|
||||
Files: *
|
||||
Copyright: 2017 All In Bits, Inc.
|
||||
License: Apache-2.0
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
.
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
.
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
.
|
||||
On Debian systems, the full text of the Apache License 2.0 can be found
|
||||
in the file `/usr/share/common-licenses/Apache-2.0'.
|
46
tools/build/ethermint/DEBIAN/postinst
Normal file
46
tools/build/ethermint/DEBIAN/postinst
Normal file
@@ -0,0 +1,46 @@
|
||||
#!/bin/sh
|
||||
# postinst script for ethermint
|
||||
#
|
||||
|
||||
set -e
|
||||
|
||||
# summary of how this script can be called:
|
||||
# * <postinst> `configure' <most-recently-configured-version>
|
||||
# * <old-postinst> `abort-upgrade' <new version>
|
||||
# * <conflictor's-postinst> `abort-remove' `in-favour' <package>
|
||||
# <new-version>
|
||||
# * <postinst> `abort-remove'
|
||||
# * <deconfigured's-postinst> `abort-deconfigure' `in-favour'
|
||||
# <failed-install-package> <version> `removing'
|
||||
# <conflicting-package> <version>
|
||||
# for details, see https://www.debian.org/doc/debian-policy/ or
|
||||
# the debian-policy package
|
||||
|
||||
|
||||
case "$1" in
|
||||
configure)
|
||||
chown ethermint.ethermint /etc/ethermint
|
||||
chown ethermint.ethermint /etc/ethermint/genesis.json
|
||||
chown ethermint.ethermint /etc/ethermint/keystore
|
||||
chown ethermint.ethermint /etc/ethermint/keystore/UTC--2016-10-21T22-30-03.071787745Z--7eff122b94897ea5b0e2a9abf47b86337fafebdc
|
||||
|
||||
sudo -Hu ethermint /usr/bin/ethermint --datadir /etc/ethermint init /etc/ethermint/genesis.json
|
||||
sudo -Hu ethermint tendermint init --home /etc/ethermint
|
||||
systemctl daemon-reload
|
||||
;;
|
||||
|
||||
abort-upgrade|abort-remove|abort-deconfigure)
|
||||
;;
|
||||
|
||||
*)
|
||||
echo "postinst called with unknown argument \`$1'" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
# dh_installdeb will replace this with shell code automatically
|
||||
# generated by other debhelper scripts.
|
||||
|
||||
#DEBHELPER#
|
||||
|
||||
exit 0
|
41
tools/build/ethermint/DEBIAN/postrm
Normal file
41
tools/build/ethermint/DEBIAN/postrm
Normal file
@@ -0,0 +1,41 @@
|
||||
#!/bin/sh
|
||||
# postrm script for ethermint
|
||||
#
|
||||
|
||||
set -e
|
||||
|
||||
# summary of how this script can be called:
|
||||
# * <postrm> `remove'
|
||||
# * <postrm> `purge'
|
||||
# * <old-postrm> `upgrade' <new-version>
|
||||
# * <new-postrm> `failed-upgrade' <old-version>
|
||||
# * <new-postrm> `abort-install'
|
||||
# * <new-postrm> `abort-install' <old-version>
|
||||
# * <new-postrm> `abort-upgrade' <old-version>
|
||||
# * <disappearer's-postrm> `disappear' <overwriter>
|
||||
# <overwriter-version>
|
||||
# for details, see https://www.debian.org/doc/debian-policy/ or
|
||||
# the debian-policy package
|
||||
|
||||
|
||||
case "$1" in
|
||||
upgrade|failed-upgrade|abort-upgrade)
|
||||
systemctl daemon-reload
|
||||
;;
|
||||
|
||||
purge|remove|abort-install|disappear)
|
||||
systemctl daemon-reload
|
||||
;;
|
||||
|
||||
*)
|
||||
echo "postrm called with unknown argument \`$1'" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
# dh_installdeb will replace this with shell code automatically
|
||||
# generated by other debhelper scripts.
|
||||
|
||||
#DEBHELPER#
|
||||
|
||||
exit 0
|
38
tools/build/ethermint/DEBIAN/preinst
Normal file
38
tools/build/ethermint/DEBIAN/preinst
Normal file
@@ -0,0 +1,38 @@
|
||||
#!/bin/sh
|
||||
# preinst script for ethermint
|
||||
#
|
||||
|
||||
set -e
|
||||
|
||||
# summary of how this script can be called:
|
||||
# * <new-preinst> `install'
|
||||
# * <new-preinst> `install' <old-version>
|
||||
# * <new-preinst> `upgrade' <old-version>
|
||||
# * <old-preinst> `abort-upgrade' <new-version>
|
||||
# for details, see https://www.debian.org/doc/debian-policy/ or
|
||||
# the debian-policy package
|
||||
|
||||
|
||||
case "$1" in
|
||||
install|upgrade)
|
||||
if ! grep -q '^ethermint:' /etc/passwd ; then
|
||||
useradd -k /dev/null -r -m -b /etc ethermint
|
||||
chmod 755 /etc/ethermint
|
||||
fi
|
||||
;;
|
||||
|
||||
abort-upgrade)
|
||||
;;
|
||||
|
||||
*)
|
||||
echo "preinst called with unknown argument \`$1'" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
# dh_installdeb will replace this with shell code automatically
|
||||
# generated by other debhelper scripts.
|
||||
|
||||
#DEBHELPER#
|
||||
|
||||
exit 0
|
38
tools/build/ethermint/DEBIAN/prerm
Normal file
38
tools/build/ethermint/DEBIAN/prerm
Normal file
@@ -0,0 +1,38 @@
|
||||
#!/bin/sh
|
||||
# prerm script for ethermint
|
||||
#
|
||||
|
||||
set -e
|
||||
|
||||
# summary of how this script can be called:
|
||||
# * <prerm> `remove'
|
||||
# * <old-prerm> `upgrade' <new-version>
|
||||
# * <new-prerm> `failed-upgrade' <old-version>
|
||||
# * <conflictor's-prerm> `remove' `in-favour' <package> <new-version>
|
||||
# * <deconfigured's-prerm> `deconfigure' `in-favour'
|
||||
# <package-being-installed> <version> `removing'
|
||||
# <conflicting-package> <version>
|
||||
# for details, see https://www.debian.org/doc/debian-policy/ or
|
||||
# the debian-policy package
|
||||
|
||||
|
||||
case "$1" in
|
||||
remove|upgrade|deconfigure)
|
||||
systemctl stop ethermint 2> /dev/null || :
|
||||
;;
|
||||
|
||||
failed-upgrade)
|
||||
;;
|
||||
|
||||
*)
|
||||
echo "prerm called with unknown argument \`$1'" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
# dh_installdeb will replace this with shell code automatically
|
||||
# generated by other debhelper scripts.
|
||||
|
||||
#DEBHELPER#
|
||||
|
||||
exit 0
|
@@ -0,0 +1,2 @@
|
||||
disable ethermint.service
|
||||
|
17
tools/build/ethermint/etc/systemd/system/ethermint.service
Normal file
17
tools/build/ethermint/etc/systemd/system/ethermint.service
Normal file
@@ -0,0 +1,17 @@
|
||||
[Unit]
|
||||
Description=Ethermint
|
||||
Requires=network-online.target
|
||||
After=network-online.target
|
||||
|
||||
[Service]
|
||||
Restart=on-failure
|
||||
User=ethermint
|
||||
Group=ethermint
|
||||
PermissionsStartOnly=true
|
||||
ExecStart=/usr/bin/ethermint --datadir /etc/ethermint
|
||||
ExecReload=/bin/kill -HUP $MAINPID
|
||||
KillSignal=SIGTERM
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
|
6
tools/build/gaia/DEBIAN/changelog
Normal file
6
tools/build/gaia/DEBIAN/changelog
Normal file
@@ -0,0 +1,6 @@
|
||||
gaia (@VERSION@) @STABILITY@; urgency=medium
|
||||
|
||||
* Automatic build. See https://github.com/tendermint/basecoin for more information.
|
||||
|
||||
-- Greg Szabo <greg@philosobear.com> @DATETIMESTAMP@
|
||||
|
1
tools/build/gaia/DEBIAN/compat
Normal file
1
tools/build/gaia/DEBIAN/compat
Normal file
@@ -0,0 +1 @@
|
||||
9
|
14
tools/build/gaia/DEBIAN/control
Normal file
14
tools/build/gaia/DEBIAN/control
Normal file
@@ -0,0 +1,14 @@
|
||||
Source: gaia
|
||||
Section: net
|
||||
Priority: optional
|
||||
Maintainer: Greg Szabo <greg@philosobear.com>
|
||||
Build-Depends: debhelper (>=9)
|
||||
Standards-Version: 3.9.6
|
||||
Homepage: https://cosmos.network
|
||||
Package: gaia
|
||||
Architecture: amd64
|
||||
Version: @VERSION@
|
||||
Installed-Size: @INSTALLEDSIZE@
|
||||
Description: gaia - Tendermint Cosmos delegation game chain
|
||||
Gaia description comes later.
|
||||
|
21
tools/build/gaia/DEBIAN/copyright
Normal file
21
tools/build/gaia/DEBIAN/copyright
Normal file
@@ -0,0 +1,21 @@
|
||||
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
|
||||
Upstream-Name: gaia
|
||||
Source: https://github.com/cosmos/gaia
|
||||
|
||||
Files: *
|
||||
Copyright: 2017 All In Bits, Inc.
|
||||
License: Apache-2.0
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
.
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
.
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
.
|
||||
On Debian systems, the full text of the Apache License 2.0 can be found
|
||||
in the file `/usr/share/common-licenses/Apache-2.0'.
|
41
tools/build/gaia/DEBIAN/postinst
Normal file
41
tools/build/gaia/DEBIAN/postinst
Normal file
@@ -0,0 +1,41 @@
|
||||
#!/bin/sh
|
||||
# postinst script for gaia
|
||||
#
|
||||
|
||||
set -e
|
||||
|
||||
# summary of how this script can be called:
|
||||
# * <postinst> `configure' <most-recently-configured-version>
|
||||
# * <old-postinst> `abort-upgrade' <new version>
|
||||
# * <conflictor's-postinst> `abort-remove' `in-favour' <package>
|
||||
# <new-version>
|
||||
# * <postinst> `abort-remove'
|
||||
# * <deconfigured's-postinst> `abort-deconfigure' `in-favour'
|
||||
# <failed-install-package> <version> `removing'
|
||||
# <conflicting-package> <version>
|
||||
# for details, see https://www.debian.org/doc/debian-policy/ or
|
||||
# the debian-policy package
|
||||
|
||||
|
||||
case "$1" in
|
||||
configure)
|
||||
chown gaia.gaia /etc/gaia
|
||||
sudo -Hu gaia gaia node init --home /etc/gaia 2B24DEE2364762300168DF19B6C18BCE2D399EA2
|
||||
systemctl daemon-reload
|
||||
;;
|
||||
|
||||
abort-upgrade|abort-remove|abort-deconfigure)
|
||||
;;
|
||||
|
||||
*)
|
||||
echo "postinst called with unknown argument \`$1'" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
# dh_installdeb will replace this with shell code automatically
|
||||
# generated by other debhelper scripts.
|
||||
|
||||
#DEBHELPER#
|
||||
|
||||
exit 0
|
41
tools/build/gaia/DEBIAN/postrm
Normal file
41
tools/build/gaia/DEBIAN/postrm
Normal file
@@ -0,0 +1,41 @@
|
||||
#!/bin/sh
|
||||
# postrm script for gaia
|
||||
#
|
||||
|
||||
set -e
|
||||
|
||||
# summary of how this script can be called:
|
||||
# * <postrm> `remove'
|
||||
# * <postrm> `purge'
|
||||
# * <old-postrm> `upgrade' <new-version>
|
||||
# * <new-postrm> `failed-upgrade' <old-version>
|
||||
# * <new-postrm> `abort-install'
|
||||
# * <new-postrm> `abort-install' <old-version>
|
||||
# * <new-postrm> `abort-upgrade' <old-version>
|
||||
# * <disappearer's-postrm> `disappear' <overwriter>
|
||||
# <overwriter-version>
|
||||
# for details, see https://www.debian.org/doc/debian-policy/ or
|
||||
# the debian-policy package
|
||||
|
||||
|
||||
case "$1" in
|
||||
upgrade|failed-upgrade|abort-upgrade)
|
||||
systemctl daemon-reload
|
||||
;;
|
||||
|
||||
purge|remove|abort-install|disappear)
|
||||
systemctl daemon-reload
|
||||
;;
|
||||
|
||||
*)
|
||||
echo "postrm called with unknown argument \`$1'" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
# dh_installdeb will replace this with shell code automatically
|
||||
# generated by other debhelper scripts.
|
||||
|
||||
#DEBHELPER#
|
||||
|
||||
exit 0
|
38
tools/build/gaia/DEBIAN/preinst
Normal file
38
tools/build/gaia/DEBIAN/preinst
Normal file
@@ -0,0 +1,38 @@
|
||||
#!/bin/sh
|
||||
# preinst script for gaia
|
||||
#
|
||||
|
||||
set -e
|
||||
|
||||
# summary of how this script can be called:
|
||||
# * <new-preinst> `install'
|
||||
# * <new-preinst> `install' <old-version>
|
||||
# * <new-preinst> `upgrade' <old-version>
|
||||
# * <old-preinst> `abort-upgrade' <new-version>
|
||||
# for details, see https://www.debian.org/doc/debian-policy/ or
|
||||
# the debian-policy package
|
||||
|
||||
|
||||
case "$1" in
|
||||
install|upgrade)
|
||||
if ! grep -q '^gaia:' /etc/passwd ; then
|
||||
useradd -k /dev/null -r -m -b /etc gaia
|
||||
chmod 755 /etc/gaia
|
||||
fi
|
||||
;;
|
||||
|
||||
abort-upgrade)
|
||||
;;
|
||||
|
||||
*)
|
||||
echo "preinst called with unknown argument \`$1'" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
# dh_installdeb will replace this with shell code automatically
|
||||
# generated by other debhelper scripts.
|
||||
|
||||
#DEBHELPER#
|
||||
|
||||
exit 0
|
38
tools/build/gaia/DEBIAN/prerm
Normal file
38
tools/build/gaia/DEBIAN/prerm
Normal file
@@ -0,0 +1,38 @@
|
||||
#!/bin/sh
|
||||
# prerm script for gaia
|
||||
#
|
||||
|
||||
set -e
|
||||
|
||||
# summary of how this script can be called:
|
||||
# * <prerm> `remove'
|
||||
# * <old-prerm> `upgrade' <new-version>
|
||||
# * <new-prerm> `failed-upgrade' <old-version>
|
||||
# * <conflictor's-prerm> `remove' `in-favour' <package> <new-version>
|
||||
# * <deconfigured's-prerm> `deconfigure' `in-favour'
|
||||
# <package-being-installed> <version> `removing'
|
||||
# <conflicting-package> <version>
|
||||
# for details, see https://www.debian.org/doc/debian-policy/ or
|
||||
# the debian-policy package
|
||||
|
||||
|
||||
case "$1" in
|
||||
remove|upgrade|deconfigure)
|
||||
systemctl stop gaia 2> /dev/null || :
|
||||
;;
|
||||
|
||||
failed-upgrade)
|
||||
;;
|
||||
|
||||
*)
|
||||
echo "prerm called with unknown argument \`$1'" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
# dh_installdeb will replace this with shell code automatically
|
||||
# generated by other debhelper scripts.
|
||||
|
||||
#DEBHELPER#
|
||||
|
||||
exit 0
|
@@ -0,0 +1,2 @@
|
||||
disable gaia.service
|
||||
|
17
tools/build/gaia/etc/systemd/system/gaia.service
Normal file
17
tools/build/gaia/etc/systemd/system/gaia.service
Normal file
@@ -0,0 +1,17 @@
|
||||
[Unit]
|
||||
Description=Gaia
|
||||
Requires=network-online.target
|
||||
After=network-online.target
|
||||
|
||||
[Service]
|
||||
Restart=on-failure
|
||||
User=gaia
|
||||
Group=gaia
|
||||
PermissionsStartOnly=true
|
||||
ExecStart=/usr/bin/gaia node start --home=/etc/gaia
|
||||
ExecReload=/bin/kill -HUP $MAINPID
|
||||
KillSignal=SIGTERM
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
|
12
tools/build/gaia/usr/share/gaia/key.json
Normal file
12
tools/build/gaia/usr/share/gaia/key.json
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"address": "1B1BE55F969F54064628A63B9559E7C21C925165",
|
||||
"priv_key": {
|
||||
"type": "ed25519",
|
||||
"data": "C70D6934B4F55F1B7BC33B56B9CA8A2061384AFC19E91E44B40C4BBA182953D1619D3678599971ED29C7529DDD4DA537B97129893598A17C82E3AC9A8BA95279"
|
||||
},
|
||||
"pub_key": {
|
||||
"type": "ed25519",
|
||||
"data": "619D3678599971ED29C7529DDD4DA537B97129893598A17C82E3AC9A8BA95279"
|
||||
}
|
||||
}
|
||||
|
12
tools/build/gaia/usr/share/gaia/key2.json
Normal file
12
tools/build/gaia/usr/share/gaia/key2.json
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"address": "1DA7C74F9C219229FD54CC9F7386D5A3839F0090",
|
||||
"priv_key": {
|
||||
"type": "ed25519",
|
||||
"data": "34BAE9E65CE8245FAD035A0E3EED9401BDE8785FFB3199ACCF8F5B5DDF7486A8352195DA90CB0B90C24295B90AEBA25A5A71BC61BAB2FE2387241D439698B7B8"
|
||||
},
|
||||
"pub_key": {
|
||||
"type": "ed25519",
|
||||
"data": "352195DA90CB0B90C24295B90AEBA25A5A71BC61BAB2FE2387241D439698B7B8"
|
||||
}
|
||||
}
|
||||
|
36
tools/build/generate-spec
Executable file
36
tools/build/generate-spec
Executable file
@@ -0,0 +1,36 @@
|
||||
#!/bin/bash
|
||||
|
||||
if [ $# -ne 3 ]; then
|
||||
echo "Usage: $0 <application> <template_source_dir> <SPEC_dir>"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
app=$1
|
||||
src=$2
|
||||
dst=$3
|
||||
|
||||
# Find spectemplate
|
||||
if [ ! -f "$src/$app.spec" ]; then
|
||||
if [ ! -f "$src/app-template.spec" ]; then
|
||||
echo "Source template not found."
|
||||
exit 1
|
||||
else
|
||||
srcfile="$src/app-template.spec"
|
||||
fi
|
||||
else
|
||||
srcfile="$src/$app.spec"
|
||||
fi
|
||||
|
||||
# Copy spectemplate to SPECS
|
||||
cp "$srcfile" "$dst/$app.spec"
|
||||
|
||||
# Apply any variables defined in .data
|
||||
if [ -f "$src/$app.data" ]; then
|
||||
srcdata="$src/$app.data"
|
||||
source "$srcdata"
|
||||
for var in `grep -v -e ^# -e ^\s*$ "$srcdata" | grep = | sed 's/\s*=.*$//'`
|
||||
do
|
||||
sed -i "s\\@${var}@\\${!var}\\g" "$dst/$app.spec"
|
||||
done
|
||||
fi
|
||||
|
26
tools/build/sign
Executable file
26
tools/build/sign
Executable file
@@ -0,0 +1,26 @@
|
||||
#!/usr/bin/expect -f
|
||||
set timeout 3
|
||||
set PACKAGE [lindex $argv 0]
|
||||
set GPG_NAME [lindex $argv 1]
|
||||
set GPG_PATH [lindex $argv 2]
|
||||
set GPG_PASSPHRASE $env(GPG_PASSPHRASE)
|
||||
|
||||
if {[llength $argv] == 0} {
|
||||
send_user "Usage: ./sign <rpm_package> <gpg_key> <gpg_binary>\n"
|
||||
exit 1
|
||||
}
|
||||
|
||||
send_user "\nSigning $PACKAGE\n"
|
||||
spawn rpmsign --resign $PACKAGE --define "_signature gpg" --define "_gpg_name $GPG_NAME" --define "_gpgbin $GPG_PATH"
|
||||
expect {
|
||||
timeout { send_user "\nTimeout signing $PACKAGE\n"; exit 1 }
|
||||
"Enter pass phrase:"
|
||||
}
|
||||
send "$GPG_PASSPHRASE\r"
|
||||
expect {
|
||||
timeout { send_user "\nTimeout signing $PACKAGE\n"; exit 1 }
|
||||
"Pass phrase is good."
|
||||
}
|
||||
interact
|
||||
sleep 3
|
||||
|
55
tools/build/spectemplates/app-template.spec
Normal file
55
tools/build/spectemplates/app-template.spec
Normal file
@@ -0,0 +1,55 @@
|
||||
Version: @VERSION@
|
||||
Release: @BUILD_NUMBER@
|
||||
|
||||
%define __spec_install_post %{nil}
|
||||
%define debug_package %{nil}
|
||||
%define __os_install_post %{nil}
|
||||
|
||||
Name: @PACKAGE_NAME@
|
||||
Summary: @PACKAGE_SUMMARY@
|
||||
License: Apache 2.0
|
||||
URL: @PACKAGE_URL@
|
||||
Packager: Greg Szabo
|
||||
@PACKAGE_ADDITIONAL_HEADER@
|
||||
|
||||
%description
|
||||
@PACKAGE_DESCRIPTION@
|
||||
|
||||
%pre
|
||||
if ! %{__grep} -q '^%{name}:' /etc/passwd ; then
|
||||
useradd -r -b %{_sysconfdir} %{name}
|
||||
mkdir -p %{_sysconfdir}/%{name}
|
||||
chmod 755 %{_sysconfdir}/%{name}
|
||||
chown %{name}.%{name} %{_sysconfdir}/%{name}
|
||||
fi
|
||||
|
||||
%prep
|
||||
# Nothing to do here. - It is done in the Makefile.
|
||||
|
||||
%build
|
||||
# Nothing to do here.
|
||||
|
||||
%install
|
||||
cd %{name}-%{version}-%{release}
|
||||
%{__cp} -a * %{buildroot}
|
||||
|
||||
%post
|
||||
sudo -Hu %{name} %{name} node init --home %{_sysconfdir}/%{name} 2B24DEE2364762300168DF19B6C18BCE2D399EA2
|
||||
systemctl daemon-reload
|
||||
|
||||
%preun
|
||||
systemctl stop %{name} 2> /dev/null || :
|
||||
|
||||
%postun
|
||||
systemctl daemon-reload
|
||||
|
||||
%files
|
||||
%ghost %attr(0755, %{name}, %{name}) %dir %{_sysconfdir}/%{name}
|
||||
%{_bindir}/*
|
||||
%{_sysconfdir}/systemd/system/*
|
||||
%{_sysconfdir}/systemd/system-preset/*
|
||||
%dir %{_datadir}/%{name}
|
||||
%{_datadir}/%{name}/*
|
||||
%dir %{_defaultlicensedir}/%{name}
|
||||
%doc %{_defaultlicensedir}/%{name}/LICENSE
|
||||
|
5
tools/build/spectemplates/basecoind.data
Normal file
5
tools/build/spectemplates/basecoind.data
Normal file
@@ -0,0 +1,5 @@
|
||||
PACKAGE_SUMMARY="basecoind is a Proof-of-Stake cryptocurrency and framework"
|
||||
PACKAGE_URL="https://cosmos.network/"
|
||||
PACKAGE_ADDITIONAL_HEADER="Provides: basecoind"
|
||||
PACKAGE_DESCRIPTION="Basecoind is an ABCI application designed to be used with the Tendermint consensus engine to form a Proof-of-Stake cryptocurrency. It also provides a general purpose framework for extending the feature-set of the cryptocurrency by implementing plugins."
|
||||
|
5
tools/build/spectemplates/ethermint.data
Normal file
5
tools/build/spectemplates/ethermint.data
Normal file
@@ -0,0 +1,5 @@
|
||||
PACKAGE_SUMMARY="ethermint enables ethereum as an ABCI application on tendermint and the COSMOS hub"
|
||||
PACKAGE_URL="https://tendermint.com/"
|
||||
PACKAGE_ADDITIONAL_HEADER="Provides: ethermint"
|
||||
PACKAGE_DESCRIPTION="Ethermint enables ethereum to run as an ABCI application on tendermint and the COSMOS hub. This application allows you to get all the benefits of ethereum without having to run your own miners."
|
||||
|
60
tools/build/spectemplates/ethermint.spec
Normal file
60
tools/build/spectemplates/ethermint.spec
Normal file
@@ -0,0 +1,60 @@
|
||||
Version: @VERSION@
|
||||
Release: @BUILD_NUMBER@
|
||||
|
||||
%define __spec_install_post %{nil}
|
||||
%define debug_package %{nil}
|
||||
%define __os_install_post %{nil}
|
||||
|
||||
Name: @PACKAGE_NAME@
|
||||
Summary: @PACKAGE_SUMMARY@
|
||||
License: Apache 2.0
|
||||
URL: @PACKAGE_URL@
|
||||
Packager: Greg Szabo
|
||||
Requires: tendermint >= 0.11.0
|
||||
@PACKAGE_ADDITIONAL_HEADER@
|
||||
|
||||
%description
|
||||
@PACKAGE_DESCRIPTION@
|
||||
|
||||
%pre
|
||||
if ! %{__grep} -q '^%{name}:' /etc/passwd ; then
|
||||
useradd -r -b %{_sysconfdir} %{name}
|
||||
mkdir -p %{_sysconfdir}/%{name}
|
||||
chmod 755 %{_sysconfdir}/%{name}
|
||||
chown %{name}.%{name} %{_sysconfdir}/%{name}
|
||||
fi
|
||||
|
||||
%prep
|
||||
# Nothing to do here. - It is done in the Makefile.
|
||||
|
||||
%build
|
||||
# Nothing to do here.
|
||||
|
||||
%install
|
||||
cd %{name}-%{version}-%{release}
|
||||
%{__cp} -a * %{buildroot}
|
||||
|
||||
%post
|
||||
sudo -Hu %{name} tendermint init --home %{_sysconfdir}/%{name}
|
||||
sudo -Hu %{name} %{name} --datadir %{_sysconfdir}/%{name} init %{_sysconfdir}/%{name}/genesis.json
|
||||
|
||||
systemctl daemon-reload
|
||||
|
||||
%preun
|
||||
systemctl stop %{name} 2> /dev/null || :
|
||||
systemctl stop %{name}-service 2> /dev/null || :
|
||||
|
||||
%postun
|
||||
systemctl daemon-reload
|
||||
|
||||
%files
|
||||
%attr(0755, %{name}, %{name}) %dir %{_sysconfdir}/%{name}
|
||||
%config(noreplace) %attr(0644, %{name}, %{name}) %{_sysconfdir}/%{name}/genesis.json
|
||||
%attr(0755, %{name}, %{name}) %dir %{_sysconfdir}/%{name}/keystore
|
||||
%attr(0644, %{name}, %{name}) %{_sysconfdir}/%{name}/keystore/*
|
||||
%{_bindir}/*
|
||||
%{_sysconfdir}/systemd/system/*
|
||||
%{_sysconfdir}/systemd/system-preset/*
|
||||
%dir %{_defaultlicensedir}/%{name}
|
||||
%doc %{_defaultlicensedir}/%{name}/LICENSE
|
||||
|
5
tools/build/spectemplates/gaia.data
Normal file
5
tools/build/spectemplates/gaia.data
Normal file
@@ -0,0 +1,5 @@
|
||||
PACKAGE_SUMMARY="gaia - Tendermint Cosmos delegation game chain"
|
||||
PACKAGE_URL="https://cosmos.network/"
|
||||
PACKAGE_ADDITIONAL_HEADER=""
|
||||
PACKAGE_DESCRIPTION="Gaia description comes later."
|
||||
|
31
tools/build/spectemplates/tendermint.spec
Normal file
31
tools/build/spectemplates/tendermint.spec
Normal file
@@ -0,0 +1,31 @@
|
||||
Version: @VERSION@
|
||||
Release: @BUILD_NUMBER@
|
||||
|
||||
%define __spec_install_post %{nil}
|
||||
%define debug_package %{nil}
|
||||
%define __os_install_post %{nil}
|
||||
|
||||
Name: tendermint
|
||||
Summary: securely and consistently replicate an application on many machines
|
||||
License: Apache 2.0
|
||||
URL: https://tendermint.com/
|
||||
Packager: Greg Szabo
|
||||
|
||||
%description
|
||||
Tendermint is software for securely and consistently replicating an application on many machines. By securely, we mean that Tendermint works even if up to 1/3 of machines fail in arbitrary ways. By consistently, we mean that every non-faulty machine sees the same transaction log and computes the same state.
|
||||
|
||||
%prep
|
||||
# Nothing to do here. - It is done in the Makefile.
|
||||
|
||||
%build
|
||||
# Nothing to do here.
|
||||
|
||||
%install
|
||||
cd %{name}-%{version}-%{release}
|
||||
%{__cp} -a * %{buildroot}
|
||||
|
||||
%files
|
||||
%{_bindir}/tendermint
|
||||
%dir %{_defaultlicensedir}/%{name}
|
||||
%doc %{_defaultlicensedir}/%{name}/LICENSE
|
||||
|
1
tools/build/tendermint.list
Normal file
1
tools/build/tendermint.list
Normal file
@@ -0,0 +1 @@
|
||||
deb http://tendermint-packages.s3-website-us-west-1.amazonaws.com/debian stable main
|
12
tools/build/tendermint.repo
Normal file
12
tools/build/tendermint.repo
Normal file
@@ -0,0 +1,12 @@
|
||||
#This is the .repo file for the Tendermint CentOS repositories.
|
||||
#Although it has only been tested under CentOS 7, it should work under Fedora and RedHat 7 too.
|
||||
#Currently only 64-bit packages are built.
|
||||
|
||||
[tendermint]
|
||||
name=Tendermint stable releases repository
|
||||
baseurl=https://do9rmxapsag1v.cloudfront.net/centos/7/os/x86_64
|
||||
gpgcheck=1
|
||||
gpgkey=https://do9rmxapsag1v.cloudfront.net/centos/7/os/x86_64/RPM-GPG-KEY-Tendermint
|
||||
enabled=1
|
||||
#sslverify = 1
|
||||
|
6
tools/build/tendermint/DEBIAN/changelog
Normal file
6
tools/build/tendermint/DEBIAN/changelog
Normal file
@@ -0,0 +1,6 @@
|
||||
tendermint (@VERSION@) @STABILITY@; urgency=medium
|
||||
|
||||
* Automatic build. See https://github.com/tendermint/tendermint for more information.
|
||||
|
||||
-- Greg Szabo <greg@philosobear.com> @DATETIMESTAMP@
|
||||
|
1
tools/build/tendermint/DEBIAN/compat
Normal file
1
tools/build/tendermint/DEBIAN/compat
Normal file
@@ -0,0 +1 @@
|
||||
9
|
14
tools/build/tendermint/DEBIAN/control
Normal file
14
tools/build/tendermint/DEBIAN/control
Normal file
@@ -0,0 +1,14 @@
|
||||
Source: tendermint
|
||||
Section: net
|
||||
Priority: optional
|
||||
Maintainer: Greg Szabo <greg@philosobear.com>
|
||||
Build-Depends: debhelper (>=9)
|
||||
Standards-Version: 3.9.6
|
||||
Homepage: https://tendermint.com
|
||||
Package: tendermint
|
||||
Architecture: amd64
|
||||
Version: @VERSION@
|
||||
Installed-Size: @INSTALLEDSIZE@
|
||||
Description: securely and consistently replicate an application on many machines
|
||||
Tendermint is software for securely and consistently replicating an application on many machines. By securely, we mean that Tendermint works even if up to 1/3 of machines fail in arbitrary ways. By consistently, we mean that every non-faulty machine sees the same transaction log and computes the same state.
|
||||
|
21
tools/build/tendermint/DEBIAN/copyright
Normal file
21
tools/build/tendermint/DEBIAN/copyright
Normal file
@@ -0,0 +1,21 @@
|
||||
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
|
||||
Upstream-Name: tendermint
|
||||
Source: https://github.com/tendermint/tendermint
|
||||
|
||||
Files: *
|
||||
Copyright: 2017 All In Bits, Inc.
|
||||
License: Apache-2.0
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
.
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
.
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
.
|
||||
On Debian systems, the full text of the Apache License 2.0 can be found
|
||||
in the file `/usr/share/common-licenses/Apache-2.0'.
|
192
tools/mintnet-kubernetes/LICENSE
Normal file
192
tools/mintnet-kubernetes/LICENSE
Normal file
@@ -0,0 +1,192 @@
|
||||
Copyright (C) 2017 Tendermint
|
||||
|
||||
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
https://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
https://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
290
tools/mintnet-kubernetes/README.rst
Normal file
290
tools/mintnet-kubernetes/README.rst
Normal file
@@ -0,0 +1,290 @@
|
||||
Using Kubernetes
|
||||
================
|
||||
|
||||
.. figure:: assets/t_plus_k.png
|
||||
:alt: Tendermint plus Kubernetes
|
||||
|
||||
Tendermint plus Kubernetes
|
||||
|
||||
This should primarily be used for testing purposes or for
|
||||
tightly-defined chains operated by a single stakeholder (see `the
|
||||
security precautions <#security>`__). If your desire is to launch an
|
||||
application with many stakeholders, consider using our set of Ansible
|
||||
scripts.
|
||||
|
||||
Quick Start
|
||||
-----------
|
||||
|
||||
For either platform, see the `requirements <https://github.com/kubernetes/minikube#requirements>`__
|
||||
|
||||
MacOS
|
||||
^^^^^
|
||||
|
||||
::
|
||||
|
||||
curl -LO https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/darwin/amd64/kubectl && chmod +x kubectl && sudo mv kubectl /usr/local/bin/kubectl
|
||||
curl -Lo minikube https://storage.googleapis.com/minikube/releases/v0.18.0/minikube-darwin-amd64 && chmod +x minikube && sudo mv minikube /usr/local/bin/
|
||||
minikube start
|
||||
|
||||
git clone https://github.com/tendermint/tools.git && cd tools/mintnet-kubernetes/examples/basecoin && make create
|
||||
|
||||
Linux
|
||||
^^^^^
|
||||
|
||||
::
|
||||
|
||||
curl -LO https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/linux/amd64/kubectl && chmod +x kubectl && sudo mv kubectl /usr/local/bin/kubectl
|
||||
curl -Lo minikube https://storage.googleapis.com/minikube/releases/v0.18.0/minikube-linux-amd64 && chmod +x minikube && sudo mv minikube /usr/local/bin/
|
||||
minikube start
|
||||
|
||||
git clone https://github.com/tendermint/tools.git && cd tools/mintnet-kubernetes/examples/basecoin && make create
|
||||
|
||||
Verify it worked
|
||||
~~~~~~~~~~~~~~~~
|
||||
|
||||
**Using a shell:**
|
||||
|
||||
First wait until all the pods are ``Running``:
|
||||
|
||||
``kubectl get pods -w -o wide -L tm``
|
||||
|
||||
then query the Tendermint app logs from the first pod:
|
||||
|
||||
``kubectl logs -c tm -f tm-0``
|
||||
|
||||
finally, use our `Rest API <../specification/rpc.html>`__ to fetch the status of the second pod's Tendermint app.
|
||||
|
||||
Note we are using ``kubectl exec`` because pods are not exposed (and should not be) to the
|
||||
outer network:
|
||||
|
||||
``kubectl exec -c tm tm-0 -- curl -s http://tm-1.basecoin:26657/status | json_pp``
|
||||
|
||||
**Using the dashboard:**
|
||||
|
||||
::
|
||||
|
||||
minikube dashboard
|
||||
|
||||
Clean up
|
||||
~~~~~~~~
|
||||
|
||||
::
|
||||
|
||||
make destroy
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
Setup a Kubernetes cluster
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
- locally using `Minikube <https://github.com/kubernetes/minikube>`__
|
||||
- on GCE with a single click in the web UI
|
||||
- on AWS using `Kubernetes
|
||||
Operations <https://github.com/kubernetes/kops/blob/master/docs/aws.md>`__
|
||||
- on Linux machines (Digital Ocean) using
|
||||
`kubeadm <https://kubernetes.io/docs/getting-started-guides/kubeadm/>`__
|
||||
- on AWS, Azure, GCE or bare metal using `Kargo
|
||||
(Ansible) <https://kubernetes.io/docs/getting-started-guides/kargo/>`__
|
||||
|
||||
Please refer to `the official
|
||||
documentation <https://kubernetes.io/docs/getting-started-guides/>`__
|
||||
for overview and comparison of different options.
|
||||
|
||||
Kubernetes on Digital Ocean
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Available options:
|
||||
|
||||
- `kubeadm (alpha) <https://kubernetes.io/docs/getting-started-guides/kubeadm/>`__
|
||||
- `kargo <https://kubernetes.io/docs/getting-started-guides/kargo/>`__
|
||||
- `rancher <http://rancher.com/>`__
|
||||
- `terraform <https://github.com/hermanjunge/kubernetes-digitalocean-terraform>`__
|
||||
|
||||
As you can see, there is no single tool for creating a cluster on DO.
|
||||
Therefore, choose the one you know and comfortable working with. If you know
|
||||
and used `terraform <https://www.terraform.io/>`__ before, then choose it. If you
|
||||
know Ansible, then pick kargo. If none of these seem familiar to you, go with
|
||||
``kubeadm``. Rancher is a beautiful UI for deploying and managing containers in
|
||||
production.
|
||||
|
||||
Kubernetes on Google Cloud Engine
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Review the `Official Documentation <https://kubernetes.io/docs/getting-started-guides/gce/>`__ for Kubernetes on Google Compute
|
||||
Engine.
|
||||
|
||||
**Create a cluster**
|
||||
|
||||
The recommended way is to use `Google Container
|
||||
Engine <https://cloud.google.com/container-engine/>`__. You should be able
|
||||
to create a fully fledged cluster with just a few clicks.
|
||||
|
||||
**Connect to it**
|
||||
|
||||
Install ``gcloud`` as a part of `Google Cloud SDK <https://cloud.google.com/sdk/>`__.
|
||||
|
||||
Make sure you have credentials for GCloud by running ``gcloud auth login``.
|
||||
|
||||
In order to make API calls against GCE, you must also run ``gcloud auth
|
||||
application-default login``.
|
||||
|
||||
Press ``Connect``:
|
||||
|
||||
.. figure:: assets/gce1.png
|
||||
|
||||
and execute the first command in your shell. Then start a proxy by
|
||||
executing ``kubectl` proxy``.
|
||||
|
||||
.. figure:: assets/gce2.png
|
||||
|
||||
Now you should be able to run ``kubectl`` command to create resources, get
|
||||
resource info, logs, etc.
|
||||
|
||||
**Make sure you have Kubernetes >= 1.5, because you will be using
|
||||
StatefulSets, which is a beta feature in 1.5.**
|
||||
|
||||
Create a configuration file
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Download a template:
|
||||
|
||||
::
|
||||
|
||||
curl -Lo app.yaml https://github.com/tendermint/tools/raw/master/mintnet-kubernetes/app.template.yaml
|
||||
|
||||
Open ``app.yaml`` in your favorite editor and configure your app
|
||||
container (navigate to ``- name: app``). Kubernetes DSL (Domain Specific
|
||||
Language) is very simple, so it should be easy. You will need to set
|
||||
Docker image, command and/or run arguments. Replace variables prefixed
|
||||
with ``YOUR_APP`` with corresponding values. Set genesis time to now and
|
||||
preferable chain ID in ConfigMap.
|
||||
|
||||
Please note if you are changing ``replicas`` number, do not forget to
|
||||
update ``validators`` set in ConfigMap. You will be able to scale the
|
||||
cluster up or down later, but new pods (nodes) won't become validators
|
||||
automatically.
|
||||
|
||||
Deploy your application
|
||||
^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
::
|
||||
|
||||
kubectl create -f ./app.yaml
|
||||
|
||||
Observe your cluster
|
||||
^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
`web UI <https://github.com/kubernetes/dashboard>`__
|
||||
|
||||
The easiest way to access Dashboard is to use ``kubectl``. Run the following
|
||||
command in your desktop environment:
|
||||
|
||||
::
|
||||
|
||||
kubectl proxy
|
||||
|
||||
``kubectl`` will handle authentication with apiserver and make Dashboard
|
||||
available at http://localhost:8001/ui
|
||||
|
||||
**shell**
|
||||
|
||||
List all the pods:
|
||||
|
||||
::
|
||||
|
||||
kubectl get pods -o wide -L tm
|
||||
|
||||
StatefulSet details:
|
||||
|
||||
::
|
||||
|
||||
kubectl describe statefulsets tm
|
||||
|
||||
First pod details:
|
||||
|
||||
::
|
||||
|
||||
kubectl describe pod tm-0
|
||||
|
||||
Tendermint app logs from the first pod:
|
||||
|
||||
::
|
||||
|
||||
kubectl logs tm-0 -c tm -f
|
||||
|
||||
App logs from the first pod:
|
||||
|
||||
::
|
||||
|
||||
kubectl logs tm-0 -c app -f
|
||||
|
||||
Status of the second pod's Tendermint app:
|
||||
|
||||
::
|
||||
|
||||
kubectl exec -c tm tm-0 -- curl -s http://tm-1.<YOUR_APP_NAME>:26657/status | json_pp
|
||||
|
||||
Security
|
||||
--------
|
||||
|
||||
Due to the nature of Kubernetes, where you typically have a single
|
||||
master, the master could be a SPOF (Single Point Of Failure). Therefore,
|
||||
you need to make sure only authorized people can access it. And these
|
||||
people themselves had taken basic measures in order not to get hacked.
|
||||
|
||||
These are the best practices:
|
||||
|
||||
- all access to the master is over TLS
|
||||
- access to the API Server is X.509 certificate or token based
|
||||
- etcd is not exposed directly to the cluster
|
||||
- ensure that images are free of vulnerabilities
|
||||
(`1 <https://github.com/coreos/clair>`__)
|
||||
- ensure that only authorized images are used in your environment
|
||||
- disable direct access to Kubernetes nodes (no SSH)
|
||||
- define resource quota
|
||||
|
||||
Resources:
|
||||
|
||||
- https://kubernetes.io/docs/admin/accessing-the-api/
|
||||
- http://blog.kubernetes.io/2016/08/security-best-practices-kubernetes-deployment.html
|
||||
- https://blog.openshift.com/securing-kubernetes/
|
||||
|
||||
Fault tolerance
|
||||
---------------
|
||||
|
||||
Having a single master (API server) is a bad thing also because if
|
||||
something happens to it, you risk being left without an access to the
|
||||
application.
|
||||
|
||||
To avoid that you can `run Kubernetes in multiple
|
||||
zones <https://kubernetes.io/docs/admin/multiple-zones/>`__, each zone
|
||||
running an `API
|
||||
server <https://kubernetes.io/docs/admin/high-availability/>`__ and load
|
||||
balance requests between them. Do not forget to make sure only one
|
||||
instance of scheduler and controller-manager are running at once.
|
||||
|
||||
Running in multiple zones is a lightweight version of a broader `Cluster
|
||||
Federation feature <https://kubernetes.io/docs/admin/federation/>`__.
|
||||
Federated deployments could span across multiple regions (not zones). We
|
||||
haven't tried this feature yet, so any feedback is highly appreciated!
|
||||
Especially, related to additional latency and cost of exchanging data
|
||||
between the regions.
|
||||
|
||||
Resources:
|
||||
|
||||
- https://kubernetes.io/docs/admin/high-availability/
|
||||
|
||||
Starting process
|
||||
----------------
|
||||
|
||||
.. figure:: assets/statefulset.png
|
||||
:alt: StatefulSet
|
||||
|
||||
StatefulSet
|
||||
|
||||
Init containers (``tm-gen-validator``) are run before all other
|
||||
containers, creating public-private key pair for each pod. Every ``tm``
|
||||
container then asks other pods for their public keys, which are served
|
||||
with nginx (``pub-key`` container). When ``tm`` container have all the
|
||||
keys, it forms a genesis file and starts the Tendermint process.
|
265
tools/mintnet-kubernetes/app.template.yaml
Normal file
265
tools/mintnet-kubernetes/app.template.yaml
Normal file
@@ -0,0 +1,265 @@
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
annotations:
|
||||
service.alpha.kubernetes.io/tolerate-unready-endpoints: "true"
|
||||
name: YOUR_APP_NAME
|
||||
labels:
|
||||
app: YOUR_APP_NAME
|
||||
spec:
|
||||
ports:
|
||||
- port: 26656
|
||||
name: p2p
|
||||
- port: 26657
|
||||
name: rpc
|
||||
clusterIP: None
|
||||
selector:
|
||||
app: tm
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: tm-config
|
||||
data:
|
||||
seeds: "tm-0,tm-1,tm-2,tm-3"
|
||||
validators: "tm-0,tm-1,tm-2,tm-3"
|
||||
validator.power: "10"
|
||||
genesis.json: |-
|
||||
{
|
||||
"genesis_time": "2017-01-02T10:10:10.164Z",
|
||||
"chain_id": "chain-B5XXm5",
|
||||
"validators": [],
|
||||
"app_hash": ""
|
||||
}
|
||||
pub_key_nginx.conf: |-
|
||||
server {
|
||||
listen 80 default_server;
|
||||
listen [::]:80 default_server ipv6only=on;
|
||||
location /pub_key.json { root /usr/share/nginx/; }
|
||||
}
|
||||
---
|
||||
apiVersion: policy/v1beta1
|
||||
kind: PodDisruptionBudget
|
||||
metadata:
|
||||
name: tm-budget
|
||||
spec:
|
||||
selector:
|
||||
matchLabels:
|
||||
app: tm
|
||||
minAvailable: 2
|
||||
---
|
||||
apiVersion: apps/v1beta1
|
||||
kind: StatefulSet
|
||||
metadata:
|
||||
name: tm
|
||||
spec:
|
||||
serviceName: YOUR_APP_NAME
|
||||
replicas: 4
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: tm
|
||||
version: v1
|
||||
annotations:
|
||||
pod.beta.kubernetes.io/init-containers: '[{
|
||||
"name": "tm-gen-validator",
|
||||
"image": "tendermint/tendermint:0.10.0",
|
||||
"imagePullPolicy": "IfNotPresent",
|
||||
"command": ["bash", "-c", "
|
||||
set -ex\n
|
||||
if [ ! -f /tendermint/priv_validator.json ]; then\n
|
||||
tendermint gen_validator > /tendermint/priv_validator.json\n
|
||||
# pub_key.json will be served by pub-key container\n
|
||||
cat /tendermint/priv_validator.json | jq \".pub_key\" > /tendermint/pub_key.json\n
|
||||
fi\n
|
||||
"],
|
||||
"volumeMounts": [
|
||||
{"name": "tmdir", "mountPath": "/tendermint"}
|
||||
]
|
||||
}]'
|
||||
spec:
|
||||
containers:
|
||||
- name: tm
|
||||
imagePullPolicy: IfNotPresent
|
||||
image: tendermint/tendermint:0.10.0
|
||||
resources:
|
||||
requests:
|
||||
cpu: 50m
|
||||
memory: 128Mi
|
||||
limits:
|
||||
cpu: 100m
|
||||
memory: 256Mi
|
||||
ports:
|
||||
- containerPort: 26656
|
||||
name: p2p
|
||||
- containerPort: 26657
|
||||
name: rpc
|
||||
env:
|
||||
- name: SEEDS
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
name: tm-config
|
||||
key: seeds
|
||||
- name: VALIDATOR_POWER
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
name: tm-config
|
||||
key: validator.power
|
||||
- name: VALIDATORS
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
name: tm-config
|
||||
key: validators
|
||||
- name: TMHOME
|
||||
value: /tendermint
|
||||
command:
|
||||
- bash
|
||||
- "-c"
|
||||
- |
|
||||
set -ex
|
||||
|
||||
# copy template
|
||||
cp /etc/tendermint/genesis.json /tendermint/genesis.json
|
||||
|
||||
# fill genesis file with validators
|
||||
IFS=',' read -ra VALS_ARR <<< "$VALIDATORS"
|
||||
fqdn_suffix=$(hostname -f | sed 's#[^.]*\.\(\)#\1#')
|
||||
for v in "${VALS_ARR[@]}"; do
|
||||
# wait until validator generates priv/pub key pair
|
||||
set +e
|
||||
|
||||
curl -s --fail "http://$v.$fqdn_suffix/pub_key.json" > /dev/null
|
||||
ERR=$?
|
||||
while [ "$ERR" != 0 ]; do
|
||||
sleep 5
|
||||
curl -s --fail "http://$v.$fqdn_suffix/pub_key.json" > /dev/null
|
||||
ERR=$?
|
||||
done
|
||||
set -e
|
||||
|
||||
# add validator to genesis file along with its pub_key
|
||||
curl -s "http://$v.$fqdn_suffix/pub_key.json" | jq ". as \$k | {pub_key: \$k, amount: $VALIDATOR_POWER, name: \"$v\"}" > pub_validator.json
|
||||
cat /tendermint/genesis.json | jq ".validators |= .+ [$(cat pub_validator.json)]" > tmpgenesis && mv tmpgenesis /tendermint/genesis.json
|
||||
rm pub_validator.json
|
||||
done
|
||||
|
||||
# construct seeds
|
||||
IFS=',' read -ra SEEDS_ARR <<< "$SEEDS"
|
||||
seeds=()
|
||||
for s in "${SEEDS_ARR[@]}"; do
|
||||
seeds+=("$s.$fqdn_suffix:26656")
|
||||
done
|
||||
seeds=$(IFS=','; echo "${seeds[*]}")
|
||||
|
||||
tendermint node --p2p.seeds="$seeds" --moniker="`hostname`" --proxy_app="unix:///socks/app.sock"
|
||||
volumeMounts:
|
||||
- name: tmdir
|
||||
mountPath: /tendermint
|
||||
- mountPath: /etc/tendermint/genesis.json
|
||||
name: configdir
|
||||
subPath: genesis.json
|
||||
- name: socksdir
|
||||
mountPath: /socks
|
||||
|
||||
- name: app
|
||||
imagePullPolicy: IfNotPresent
|
||||
image: YOUR_APP_IMAGE
|
||||
args: ["--addr=\"unix:///socks/app.sock\""]
|
||||
volumeMounts:
|
||||
- name: socksdir
|
||||
mountPath: /socks
|
||||
|
||||
######## OR ########
|
||||
#
|
||||
# - name: app
|
||||
# imagePullPolicy: IfNotPresent
|
||||
# image: golang:1.7.5
|
||||
# resources:
|
||||
# requests:
|
||||
# cpu: YOUR_APP_CPU_REQ
|
||||
# memory: YOUR_APP_MEM_REQ
|
||||
# limits:
|
||||
# cpu: YOUR_APP_CPU_LIMIT
|
||||
# memory: YOUR_APP_MEM_LIMIT
|
||||
# command:
|
||||
# - bash
|
||||
# - "-c"
|
||||
# - |
|
||||
# set -ex
|
||||
|
||||
# go get -d YOUR_APP_PACKAGE
|
||||
# cd $GOPATH/YOUR_APP_PACKAGE
|
||||
# make install
|
||||
#
|
||||
# rm -f /socks/app.sock # remove old socket
|
||||
|
||||
# YOUR_APP_EXEC --addr="unix:///socks/app.sock"
|
||||
# volumeMounts:
|
||||
# - name: socksdir
|
||||
# mountPath: /socks
|
||||
|
||||
######## OPTIONALLY ########
|
||||
#
|
||||
# - name: data
|
||||
# imagePullPolicy: IfNotPresent
|
||||
# image: golang:1.7.5
|
||||
# command:
|
||||
# - bash
|
||||
# - "-c"
|
||||
# - |
|
||||
# set -ex
|
||||
# go get github.com/tendermint/merkleeyes/cmd/merkleeyes
|
||||
# rm -f /socks/data.sock # remove old socket
|
||||
# merkleeyes server --address="unix:///socks/data.sock"
|
||||
# volumeMounts:
|
||||
# - name: socksdir
|
||||
# mountPath: /socks
|
||||
|
||||
- name: pub-key
|
||||
imagePullPolicy: IfNotPresent
|
||||
image: nginx:1.11.9
|
||||
resources:
|
||||
requests:
|
||||
cpu: 10m
|
||||
memory: 12Mi
|
||||
limits:
|
||||
cpu: 20m
|
||||
memory: 24Mi
|
||||
ports:
|
||||
- containerPort: 80
|
||||
name: pub-key
|
||||
command:
|
||||
- bash
|
||||
- "-c"
|
||||
- |
|
||||
set -ex
|
||||
# fixes 403 Permission Denied (open() "/tendermint/pub_key.json" failed (13: Permission denied))
|
||||
# => we cannot serve from /tendermint, so we copy the file
|
||||
mkdir -p /usr/share/nginx
|
||||
cp /tendermint/pub_key.json /usr/share/nginx/pub_key.json
|
||||
nginx -g "daemon off;"
|
||||
volumeMounts:
|
||||
- name: tmdir
|
||||
mountPath: /tendermint
|
||||
- mountPath: /etc/nginx/conf.d/pub_key.conf
|
||||
name: configdir
|
||||
subPath: pub_key_nginx.conf
|
||||
|
||||
volumes:
|
||||
- name: configdir
|
||||
configMap:
|
||||
name: tm-config
|
||||
- name: socksdir
|
||||
emptyDir: {}
|
||||
|
||||
volumeClaimTemplates:
|
||||
- metadata:
|
||||
name: tmdir
|
||||
annotations:
|
||||
volume.alpha.kubernetes.io/storage-class: anything
|
||||
spec:
|
||||
accessModes: ["ReadWriteOnce"]
|
||||
resources:
|
||||
requests:
|
||||
storage: 2Gi
|
BIN
tools/mintnet-kubernetes/assets/gce1.png
Normal file
BIN
tools/mintnet-kubernetes/assets/gce1.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 13 KiB |
BIN
tools/mintnet-kubernetes/assets/gce2.png
Normal file
BIN
tools/mintnet-kubernetes/assets/gce2.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 30 KiB |
BIN
tools/mintnet-kubernetes/assets/statefulset.png
Normal file
BIN
tools/mintnet-kubernetes/assets/statefulset.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 17 KiB |
BIN
tools/mintnet-kubernetes/assets/t_plus_k.png
Normal file
BIN
tools/mintnet-kubernetes/assets/t_plus_k.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 18 KiB |
10
tools/mintnet-kubernetes/examples/basecoin/Makefile
Normal file
10
tools/mintnet-kubernetes/examples/basecoin/Makefile
Normal file
@@ -0,0 +1,10 @@
|
||||
create:
|
||||
@echo "==> Creating deployment"
|
||||
@kubectl create -f app.yaml
|
||||
|
||||
destroy:
|
||||
@echo "==> Destroying deployment"
|
||||
@kubectl delete -f app.yaml
|
||||
@kubectl delete pvc -l app=tm
|
||||
|
||||
.PHONY: create destroy
|
42
tools/mintnet-kubernetes/examples/basecoin/README.md
Normal file
42
tools/mintnet-kubernetes/examples/basecoin/README.md
Normal file
@@ -0,0 +1,42 @@
|
||||
# Basecoin example
|
||||
|
||||
This is an example of using [basecoin](https://github.com/tendermint/basecoin).
|
||||
|
||||
## Usage
|
||||
|
||||
```
|
||||
make create
|
||||
```
|
||||
|
||||
### Check account balance and send a transaction
|
||||
|
||||
1. wait until all the pods are `Running`.
|
||||
|
||||
```
|
||||
kubectl get pods -w -o wide -L tm
|
||||
```
|
||||
|
||||
2. wait until app starts.
|
||||
|
||||
```
|
||||
kubectl logs -c app -f tm-0
|
||||
```
|
||||
|
||||
3. get account's address of the second pod
|
||||
|
||||
```
|
||||
ADDR=`kubectl exec -c app tm-1 -- cat /app/key.json | jq ".address" | tr -d "\""`
|
||||
```
|
||||
|
||||
4. send 5 coins to it from the first pod
|
||||
|
||||
```
|
||||
kubectl exec -c app tm-0 -- basecoin tx send --to "0x$ADDR" --amount 5mycoin --from /app/key.json --chain_id chain-tTH4mi
|
||||
```
|
||||
|
||||
|
||||
## Clean up
|
||||
|
||||
```
|
||||
make destroy
|
||||
```
|
334
tools/mintnet-kubernetes/examples/basecoin/app.yaml
Normal file
334
tools/mintnet-kubernetes/examples/basecoin/app.yaml
Normal file
@@ -0,0 +1,334 @@
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
annotations:
|
||||
service.alpha.kubernetes.io/tolerate-unready-endpoints: "true"
|
||||
name: basecoin
|
||||
labels:
|
||||
app: basecoin
|
||||
spec:
|
||||
ports:
|
||||
- port: 26656
|
||||
name: p2p
|
||||
- port: 26657
|
||||
name: rpc
|
||||
clusterIP: None
|
||||
selector:
|
||||
app: tm
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: tm-config
|
||||
data:
|
||||
seeds: "tm-0,tm-1,tm-2,tm-3"
|
||||
validators: "tm-0,tm-1,tm-2,tm-3"
|
||||
validator.power: "10"
|
||||
genesis.json: |-
|
||||
{
|
||||
"genesis_time": "2016-02-05T06:02:31.526Z",
|
||||
"chain_id": "chain-tTH4mi",
|
||||
"validators": [],
|
||||
"app_hash": ""
|
||||
}
|
||||
pub_key_nginx.conf: |-
|
||||
server {
|
||||
listen 80 default_server;
|
||||
listen [::]:80 default_server ipv6only=on;
|
||||
location /pub_key.json { root /usr/share/nginx/; }
|
||||
location /app_pub_key.json { root /usr/share/nginx/; }
|
||||
}
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: app-config
|
||||
data:
|
||||
genesis.json: |-
|
||||
{
|
||||
"chain_id": "chain-tTH4mi",
|
||||
"app_options": {
|
||||
"accounts": [
|
||||
{
|
||||
"pub_key": "tm-0",
|
||||
"coins": [
|
||||
{
|
||||
"denom": "mycoin",
|
||||
"amount": 1000000000
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"pub_key": "tm-1",
|
||||
"coins": [
|
||||
{
|
||||
"denom": "mycoin",
|
||||
"amount": 1000000000
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"pub_key": "tm-2",
|
||||
"coins": [
|
||||
{
|
||||
"denom": "mycoin",
|
||||
"amount": 1000000000
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"pub_key": "tm-3",
|
||||
"coins": [
|
||||
{
|
||||
"denom": "mycoin",
|
||||
"amount": 1000000000
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
---
|
||||
apiVersion: policy/v1beta1
|
||||
kind: PodDisruptionBudget
|
||||
metadata:
|
||||
name: tm-budget
|
||||
spec:
|
||||
selector:
|
||||
matchLabels:
|
||||
app: tm
|
||||
minAvailable: 2
|
||||
---
|
||||
apiVersion: apps/v1beta1
|
||||
kind: StatefulSet
|
||||
metadata:
|
||||
name: tm
|
||||
spec:
|
||||
serviceName: basecoin
|
||||
replicas: 4
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: tm
|
||||
annotations:
|
||||
pod.beta.kubernetes.io/init-containers: '[{
|
||||
"name": "tm-gen-validator",
|
||||
"image": "tendermint/tendermint:0.10.0",
|
||||
"imagePullPolicy": "IfNotPresent",
|
||||
"command": ["bash", "-c", "
|
||||
set -ex\n
|
||||
if [ ! -f /tendermint/priv_validator.json ]; then\n
|
||||
tendermint gen_validator > /tendermint/priv_validator.json\n
|
||||
# pub_key.json will be served by pub-key container\n
|
||||
cat /tendermint/priv_validator.json | jq \".pub_key\" > /tendermint/pub_key.json\n
|
||||
fi\n
|
||||
"],
|
||||
"volumeMounts": [
|
||||
{"name": "tmdir", "mountPath": "/tendermint"}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "app-gen-key",
|
||||
"image": "tendermint/basecoin:0.5.1",
|
||||
"imagePullPolicy": "IfNotPresent",
|
||||
"command": ["bash", "-c", "
|
||||
set -ex\n
|
||||
if [ ! -f /app/key.json ]; then\n
|
||||
basecoin key new > /app/key.json\n
|
||||
# pub_key.json will be served by app-pub-key container\n
|
||||
cat /app/key.json | jq \".pub_key\" > /app/pub_key.json\n
|
||||
fi\n
|
||||
"],
|
||||
"volumeMounts": [
|
||||
{"name": "appdir", "mountPath": "/app"}
|
||||
]
|
||||
}]'
|
||||
spec:
|
||||
containers:
|
||||
- name: tm
|
||||
imagePullPolicy: IfNotPresent
|
||||
image: tendermint/tendermint:0.10.0
|
||||
ports:
|
||||
- containerPort: 26656
|
||||
name: p2p
|
||||
- containerPort: 26657
|
||||
name: rpc
|
||||
env:
|
||||
- name: SEEDS
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
name: tm-config
|
||||
key: seeds
|
||||
- name: VALIDATOR_POWER
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
name: tm-config
|
||||
key: validator.power
|
||||
- name: VALIDATORS
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
name: tm-config
|
||||
key: validators
|
||||
- name: TMHOME
|
||||
value: /tendermint
|
||||
command:
|
||||
- bash
|
||||
- "-c"
|
||||
- |
|
||||
set -ex
|
||||
|
||||
# copy template
|
||||
cp /etc/tendermint/genesis.json /tendermint/genesis.json
|
||||
|
||||
# fill genesis file with validators
|
||||
IFS=',' read -ra VALS_ARR <<< "$VALIDATORS"
|
||||
fqdn_suffix=$(hostname -f | sed 's#[^.]*\.\(\)#\1#')
|
||||
for v in "${VALS_ARR[@]}"; do
|
||||
# wait until validator generates priv/pub key pair
|
||||
set +e
|
||||
|
||||
curl -s --fail "http://$v.$fqdn_suffix/pub_key.json" > /dev/null
|
||||
ERR=$?
|
||||
while [ "$ERR" != 0 ]; do
|
||||
sleep 5
|
||||
curl -s --fail "http://$v.$fqdn_suffix/pub_key.json" > /dev/null
|
||||
ERR=$?
|
||||
done
|
||||
set -e
|
||||
|
||||
# add validator to genesis file along with its pub_key
|
||||
curl -s "http://$v.$fqdn_suffix/pub_key.json" | jq ". as \$k | {pub_key: \$k, amount: $VALIDATOR_POWER, name: \"$v\"}" > pub_validator.json
|
||||
cat /tendermint/genesis.json | jq ".validators |= .+ [$(cat pub_validator.json)]" > tmpgenesis && mv tmpgenesis /tendermint/genesis.json
|
||||
rm pub_validator.json
|
||||
done
|
||||
|
||||
# construct seeds
|
||||
IFS=',' read -ra SEEDS_ARR <<< "$SEEDS"
|
||||
seeds=()
|
||||
for s in "${SEEDS_ARR[@]}"; do
|
||||
seeds+=("$s.$fqdn_suffix:26656")
|
||||
done
|
||||
seeds=$(IFS=','; echo "${seeds[*]}")
|
||||
|
||||
tendermint node --p2p.seeds="$seeds" --moniker="`hostname`" --proxy_app="unix:///socks/app.sock"
|
||||
volumeMounts:
|
||||
- name: tmdir
|
||||
mountPath: /tendermint
|
||||
- mountPath: /etc/tendermint/genesis.json
|
||||
name: tmconfigdir
|
||||
subPath: genesis.json
|
||||
- name: socksdir
|
||||
mountPath: /socks
|
||||
|
||||
- name: app
|
||||
imagePullPolicy: IfNotPresent
|
||||
image: tendermint/basecoin:0.5.1
|
||||
env:
|
||||
- name: BCHOME
|
||||
value: /app
|
||||
workingDir: /app
|
||||
command:
|
||||
- bash
|
||||
- "-c"
|
||||
- |
|
||||
set -ex
|
||||
|
||||
# replace "tm-N" with public keys in genesis file
|
||||
cp /etc/app/genesis.json genesis.json
|
||||
fqdn_suffix=$(hostname -f | sed 's#[^.]*\.\(\)#\1#')
|
||||
# for every "base/account"
|
||||
i=0
|
||||
length=$(cat genesis.json | jq ".app_options.accounts | length")
|
||||
while [[ $i -lt $length ]]; do
|
||||
# extract pod name ("tm-0")
|
||||
pod=$(cat genesis.json | jq -r ".app_options.accounts[$i].pub_key")
|
||||
|
||||
# wait until pod starts to serve its pub_key
|
||||
set +e
|
||||
|
||||
curl -s --fail "http://$pod.$fqdn_suffix/app_pub_key.json" > /dev/null
|
||||
ERR=$?
|
||||
while [ "$ERR" != 0 ]; do
|
||||
sleep 5
|
||||
curl -s --fail "http://$pod.$fqdn_suffix/app_pub_key.json" > /dev/null
|
||||
ERR=$?
|
||||
done
|
||||
set -e
|
||||
|
||||
# get its pub_key
|
||||
curl -s "http://$pod.$fqdn_suffix/app_pub_key.json" | jq "." > k.json
|
||||
|
||||
# replace pod name with it ("tm-0" => "{"type": ..., "data": ...}")
|
||||
cat genesis.json | jq ".app_options.accounts[$i].pub_key = $(cat k.json | jq '.')" > tmpgenesis && mv tmpgenesis genesis.json
|
||||
rm -f k.json
|
||||
|
||||
i=$((i+1))
|
||||
done
|
||||
|
||||
rm -f /socks/app.sock # remove old socket
|
||||
|
||||
basecoin start --address="unix:///socks/app.sock" --without-tendermint
|
||||
volumeMounts:
|
||||
- name: appdir
|
||||
mountPath: /app
|
||||
- mountPath: /etc/app/genesis.json
|
||||
name: appconfigdir
|
||||
subPath: genesis.json
|
||||
- name: socksdir
|
||||
mountPath: /socks
|
||||
|
||||
- name: pub-key
|
||||
imagePullPolicy: IfNotPresent
|
||||
image: nginx:latest
|
||||
ports:
|
||||
- containerPort: 80
|
||||
command:
|
||||
- bash
|
||||
- "-c"
|
||||
- |
|
||||
set -ex
|
||||
# fixes 403 Permission Denied (open() "/tendermint/pub_key.json" failed (13: Permission denied))
|
||||
# => we cannot serve from /tendermint, so we copy the file
|
||||
mkdir -p /usr/share/nginx
|
||||
cp /tendermint/pub_key.json /usr/share/nginx/pub_key.json
|
||||
cp /app/pub_key.json /usr/share/nginx/app_pub_key.json
|
||||
nginx -g "daemon off;"
|
||||
volumeMounts:
|
||||
- name: tmdir
|
||||
mountPath: /tendermint
|
||||
- name: appdir
|
||||
mountPath: /app
|
||||
- mountPath: /etc/nginx/conf.d/pub_key.conf
|
||||
name: tmconfigdir
|
||||
subPath: pub_key_nginx.conf
|
||||
|
||||
volumes:
|
||||
- name: tmconfigdir
|
||||
configMap:
|
||||
name: tm-config
|
||||
- name: appconfigdir
|
||||
configMap:
|
||||
name: app-config
|
||||
- name: socksdir
|
||||
emptyDir: {}
|
||||
|
||||
volumeClaimTemplates:
|
||||
- metadata:
|
||||
name: tmdir
|
||||
annotations:
|
||||
volume.alpha.kubernetes.io/storage-class: anything
|
||||
spec:
|
||||
accessModes: [ "ReadWriteOnce" ]
|
||||
resources:
|
||||
requests:
|
||||
storage: 2Gi
|
||||
- metadata:
|
||||
name: appdir
|
||||
annotations:
|
||||
volume.alpha.kubernetes.io/storage-class: anything
|
||||
spec:
|
||||
accessModes: [ "ReadWriteOnce" ]
|
||||
resources:
|
||||
requests:
|
||||
storage: 12Mi
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user