test(etcdraft): add unit test for etcdraft package
This commit is contained in:
parent
ccb315510d
commit
8f361682ce
19
go.sum
19
go.sum
|
@ -122,6 +122,7 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
|
|||
github.com/davidlazar/go-crypto v0.0.0-20170701192655-dcfb0a7ac018/go.mod h1:rQYf4tfk5sSwFsnDg3qYaBxSjsD9S8+59vW0dKUgme4=
|
||||
github.com/davidlazar/go-crypto v0.0.0-20190912175916-7055855a373f h1:BOaYiTvg8p9vBUXpklC22XSK/mifLF7lG9jtmYYi3Tc=
|
||||
github.com/davidlazar/go-crypto v0.0.0-20190912175916-7055855a373f/go.mod h1:rQYf4tfk5sSwFsnDg3qYaBxSjsD9S8+59vW0dKUgme4=
|
||||
github.com/deckarep/golang-set v0.0.0-20180603214616-504e848d77ea h1:j4317fAZh7X6GqbFowYdYdI0L9bwxL07jyPZIdepyZ0=
|
||||
github.com/deckarep/golang-set v0.0.0-20180603214616-504e848d77ea/go.mod h1:93vsz/8Wt4joVM7c2AVqh+YRMiUSc14yDtF28KmMOgQ=
|
||||
github.com/dgraph-io/badger v1.5.5-0.20190226225317-8115aed38f8f/go.mod h1:VZxzAIRPHRVNRKRo6AXrX9BJegn6il06VMTZVJYCIjQ=
|
||||
github.com/dgraph-io/badger v1.6.0-rc1/go.mod h1:zwt7syl517jmP8s94KqSxTlM6IMsdhYy6psNgSztDR4=
|
||||
|
@ -142,6 +143,7 @@ github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21 h1:YEetp8
|
|||
github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU=
|
||||
github.com/eapache/queue v1.1.0 h1:YOEu7KNc61ntiQlcEeUIoDTJ2o8mQznoNvUhiigpIqc=
|
||||
github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
|
||||
github.com/edsrzf/mmap-go v0.0.0-20160512033002-935e0e8a636c h1:JHHhtb9XWJrGNMcrVP6vyzO4dusgi/HnceHTgxSejUM=
|
||||
github.com/edsrzf/mmap-go v0.0.0-20160512033002-935e0e8a636c/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M=
|
||||
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||
|
@ -152,6 +154,7 @@ github.com/fastly/go-utils v0.0.0-20180712184237-d95a45783239/go.mod h1:Gdwt2ce0
|
|||
github.com/fatih/color v1.3.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||
github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys=
|
||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||
github.com/fjl/memsize v0.0.0-20180418122429-ca190fb6ffbc h1:jtW8jbpkO4YirRSyepBOH8E+2HEw6/hKkBvFPwhUN8c=
|
||||
github.com/fjl/memsize v0.0.0-20180418122429-ca190fb6ffbc/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0=
|
||||
github.com/flynn/noise v0.0.0-20180327030543-2492fe189ae6 h1:u/UEqS66A5ckRmS4yNpjmVH56sVtS/RfclBAYocb4as=
|
||||
github.com/flynn/noise v0.0.0-20180327030543-2492fe189ae6/go.mod h1:1i71OnUq3iUe1ma7Lr6yG6/rjvM3emb6yoL7xLFzcVQ=
|
||||
|
@ -163,6 +166,7 @@ github.com/frankban/quicktest v1.10.0/go.mod h1:ui7WezCLWMWxVWr1GETZY3smRy0G4KWq
|
|||
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/garyburd/redigo v1.6.0/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY=
|
||||
github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff h1:tY80oXqGNY4FhTFhk+o9oFHGINQ/+vhlm8HFzi6znCI=
|
||||
github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww=
|
||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
github.com/go-check/check v0.0.0-20180628173108-788fd7840127/go.mod h1:9ES+weclKsC9YodN5RgxqK/VD9HM9JsCSh7rNhMZE98=
|
||||
|
@ -279,6 +283,7 @@ github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2p
|
|||
github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
|
||||
github.com/hokaccha/go-prettyjson v0.0.0-20190818114111-108c894c2c0e h1:0aewS5NTyxftZHSnFaJmWE5oCCrj4DyEXkAiMa1iZJM=
|
||||
github.com/hokaccha/go-prettyjson v0.0.0-20190818114111-108c894c2c0e/go.mod h1:pFlLw2CfqZiIBOx6BuCeRLCrfxBJipTY0nIOF/VbGcI=
|
||||
github.com/holiman/uint256 v1.1.1 h1:4JywC80b+/hSfljFlEBLHrrh+CIONLDz9NuFl0af4Mw=
|
||||
github.com/holiman/uint256 v1.1.1/go.mod h1:y4ga/t+u+Xwd7CpDgZESaRcWy0I7XMlTMA25ApIH5Jw=
|
||||
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
|
@ -369,6 +374,7 @@ github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfV
|
|||
github.com/julienschmidt/httprouter v1.1.1-0.20170430222011-975b5c4c7c21/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
||||
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
||||
github.com/kami-zh/go-capturer v0.0.0-20171211120116-e492ea43421d/go.mod h1:P2viExyCEfeWGU259JnaQ34Inuec4R38JCyBx2edgD0=
|
||||
github.com/karalabe/usb v0.0.0-20190919080040-51dc0efba356 h1:I/yrLt2WilKxlQKCM52clh5rGzTKpVctGT1lH4Dc8Jw=
|
||||
github.com/karalabe/usb v0.0.0-20190919080040-51dc0efba356/go.mod h1:Od972xHfMJowv7NGVDiWVxk2zxnWgjLlJzE+F4F7AGU=
|
||||
github.com/karrick/godirwalk v1.10.12/go.mod h1:RoGL9dQei4vP9ilrpETWE8CLOZ1kiN0LhBygSwrAsHA=
|
||||
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
|
||||
|
@ -598,13 +604,14 @@ github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hd
|
|||
github.com/mattn/go-isatty v0.0.10 h1:qxFzApOv4WsAL965uUPIsXzAKCZxN2p9UqdhFS4ZW10=
|
||||
github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84=
|
||||
github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
||||
github.com/mattn/go-runewidth v0.0.4 h1:2BvfKmzob6Bmd4YsL0zygOqfdFnK7GR4QL06Do4/p7Y=
|
||||
github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||
github.com/meshplus/bitxhub-core v0.1.0-rc1.0.20210126064930-8245c5b45956 h1:f1CXhJSLo/JuTXLjv5PRtvLvzq7mxzD58Aet27k5QlU=
|
||||
github.com/meshplus/bitxhub-core v0.1.0-rc1.0.20210126064930-8245c5b45956/go.mod h1:MHf0waxqnW4Qwfpq66jqvJP+FritN5OTs/8wlQcNlJY=
|
||||
github.com/meshplus/bitxhub-core v0.1.0-rc1.0.20210112105719-497a79914e4e h1:gQf9QgAiiLrCInvcBBGvOU/6D8x6+kaJwHGXUlV8RTA=
|
||||
github.com/meshplus/bitxhub-core v0.1.0-rc1.0.20210112105719-497a79914e4e/go.mod h1:MHf0waxqnW4Qwfpq66jqvJP+FritN5OTs/8wlQcNlJY=
|
||||
github.com/meshplus/bitxhub-core v0.1.0-rc1.0.20210126064930-8245c5b45956 h1:f1CXhJSLo/JuTXLjv5PRtvLvzq7mxzD58Aet27k5QlU=
|
||||
github.com/meshplus/bitxhub-core v0.1.0-rc1.0.20210126064930-8245c5b45956/go.mod h1:MHf0waxqnW4Qwfpq66jqvJP+FritN5OTs/8wlQcNlJY=
|
||||
github.com/meshplus/bitxhub-kit v1.0.0-rc1/go.mod h1:ra/AhOkPvpElI+wXrB9G6DjdcrdxFU3vMwA5MYKr9D0=
|
||||
github.com/meshplus/bitxhub-kit v1.0.0/go.mod h1:7cWyhXWZfrQ3+EaxkRoXfuiG3Y5R9DXYJomeZKkETW8=
|
||||
github.com/meshplus/bitxhub-kit v1.1.1 h1:vkPO88oA3+Kpc0N8lIgfj/U52KBuI+633hPbMYt1xm8=
|
||||
|
@ -708,6 +715,7 @@ github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLA
|
|||
github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4=
|
||||
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
|
||||
github.com/olekukonko/tablewriter v0.0.1/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
|
||||
github.com/olekukonko/tablewriter v0.0.2-0.20190409134802-7e037d187b0c h1:1RHs3tNxjXGHeul8z2t6H2N2TlAqpKe5yryJztRx4Jk=
|
||||
github.com/olekukonko/tablewriter v0.0.2-0.20190409134802-7e037d187b0c/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
|
||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
|
@ -731,9 +739,11 @@ github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFSt
|
|||
github.com/orcaman/concurrent-map v0.0.0-20190826125027-8c72a8bb44f6 h1:lNCW6THrCKBiJBpz8kbVGjC7MgdCGKwuvBgc7LoD6sw=
|
||||
github.com/orcaman/concurrent-map v0.0.0-20190826125027-8c72a8bb44f6/go.mod h1:Lu3tH6HLW3feq74c2GC+jIMS/K2CFcDWnWD9XkenwhI=
|
||||
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
|
||||
github.com/pborman/uuid v0.0.0-20170112150404-1b00554d8222 h1:goeTyGkArOZIVOMA0dQbyuPWGNQJZGPwPu/QS9GlpnA=
|
||||
github.com/pborman/uuid v0.0.0-20170112150404-1b00554d8222/go.mod h1:VyrYX9gd7irzKovcSS6BIIEwPRkP2Wm2m9ufcdFSJ34=
|
||||
github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc=
|
||||
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
||||
github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7 h1:oYW+YCJ1pachXTQmzR3rNLYGGz4g/UgFcjb28p/viDM=
|
||||
github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7/go.mod h1:CRroGNssyjTd/qIG2FyxByd2S8JEAZXBl4qUrZf8GS0=
|
||||
github.com/pierrec/lz4 v2.4.1+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
|
||||
github.com/pierrec/lz4 v2.5.2+incompatible h1:WCjObylUIOlKy/+7Abdn34TLIkXiA4UWUMhxq9m9ZXI=
|
||||
|
@ -777,6 +787,7 @@ github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0 h1:MkV+77GLUNo
|
|||
github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
|
||||
github.com/rifflock/lfshook v0.0.0-20180920164130-b9218ef580f5 h1:mZHayPoR0lNmnHyvtYjDeq0zlVHn9K/ZXoy17ylucdo=
|
||||
github.com/rifflock/lfshook v0.0.0-20180920164130-b9218ef580f5/go.mod h1:GEXHk5HgEKCvEIIrSpFI3ozzG5xOKA2DVlEX/gGnewM=
|
||||
github.com/rjeczalik/notify v0.9.1 h1:CLCKso/QK1snAlnhNR/CNvNiFU2saUtjV0bx3EwNeCE=
|
||||
github.com/rjeczalik/notify v0.9.1/go.mod h1:rKwnCoCGeuQnwBtTSPL9Dad03Vh2n40ePRrjvIXnJho=
|
||||
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
|
||||
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
|
||||
|
@ -834,6 +845,7 @@ github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DM
|
|||
github.com/spf13/viper v1.7.1 h1:pM5oEahlgWv/WnHXpgbKz7iLIxRf65tye2Ci+XFK5sk=
|
||||
github.com/spf13/viper v1.7.1/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg=
|
||||
github.com/src-d/envconfig v1.0.0/go.mod h1:Q9YQZ7BKITldTBnoxsE5gOeB5y66RyPXeue/R4aaNBc=
|
||||
github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4 h1:Gb2Tyox57NRNuZ2d3rmvB3pcmbu7O1RS3m8WRx7ilrg=
|
||||
github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4/go.mod h1:RZLeN1LMWmRsyYjvAu+I6Dm9QmlDaIIt+Y+4Kd7Tp+Q=
|
||||
github.com/steakknife/bloomfilter v0.0.0-20180922174646-6819c0d2a570 h1:gIlAHnH1vJb5vwEjIp5kBj/eu99p/bl0Ay2goiPe5xE=
|
||||
github.com/steakknife/bloomfilter v0.0.0-20180922174646-6819c0d2a570/go.mod h1:8OR4w3TdeIHIh1g6EMY5p0gVNOovcWC+1vpc7naMuAw=
|
||||
|
@ -871,6 +883,7 @@ github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhV
|
|||
github.com/tjfoc/gmsm v1.3.0/go.mod h1:HaUcFuY0auTiaHB9MHFGCPx5IaLhTUd2atbCFBQXn9w=
|
||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5 h1:LnC5Kc/wtumK+WB441p7ynQJzVuNRJiqddSIE3IlSEQ=
|
||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||
github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef h1:wHSqTBrZW24CsNJDfeh9Ex6Pm0Rcpc7qrgKBiL44vF4=
|
||||
github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef/go.mod h1:sJ5fKU0s6JVwZjjcUEX2zFOnvq0ASQ2K9Zr6cf67kNs=
|
||||
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
|
||||
github.com/urfave/cli v1.22.1 h1:+mkCCcOFKPnCmVYVcURKps1Xe+3zP90gSYGNfRkjoIY=
|
||||
|
@ -891,6 +904,7 @@ github.com/willf/bitset v1.1.11 h1:N7Z7E9UvjW+sGsEl7k/SJrvY2reP1A07MrGuCjIOjRE=
|
|||
github.com/willf/bitset v1.1.11/go.mod h1:83CECat5yLh5zVOf4P1ErAgKA5UDvKtgyUABdr3+MjI=
|
||||
github.com/willf/bloom v2.0.3+incompatible h1:QDacWdqcAUI1MPOwIQZRy9kOR7yxfyEmxX8Wdm2/JPA=
|
||||
github.com/willf/bloom v2.0.3+incompatible/go.mod h1:MmAltL9pDMNTrvUkxdg0k0q5I0suxmuwp3KbyrZLOZ8=
|
||||
github.com/wsddn/go-ecdh v0.0.0-20161211032359-48726bab9208 h1:1cngl9mPEoITZG8s8cVcUy5CeIBYhEESkOB7m6Gmkrk=
|
||||
github.com/wsddn/go-ecdh v0.0.0-20161211032359-48726bab9208/go.mod h1:IotVbo4F+mw0EzQ08zFqg7pK3FebNXpaMsRy2RT+Ees=
|
||||
github.com/x-cray/logrus-prefixed-formatter v0.5.2/go.mod h1:2duySbKsL6M18s5GU7VPsoEPHyzalCE06qoARUCeBBE=
|
||||
github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c/go.mod h1:lB8K/P019DLNhemzwFU4jHLhdvlE6uDZjXFejJXr49I=
|
||||
|
@ -1141,6 +1155,7 @@ gopkg.in/src-d/go-cli.v0 v0.0.0-20181105080154-d492247bbc0d/go.mod h1:z+K8VcOYVY
|
|||
gopkg.in/src-d/go-log.v1 v1.0.1/go.mod h1:GN34hKP0g305ysm2/hctJ0Y8nWP3zxXXJ8GFabTyABE=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||
gopkg.in/urfave/cli.v1 v1.20.0 h1:NdAVW6RYxDif9DhDHaAortIu956m2c0v+09AZBPTbE0=
|
||||
gopkg.in/urfave/cli.v1 v1.20.0/go.mod h1:vuBzUtMdQeixQj8LVd+/98pzhxNGQoyuPBlsXHOQNO0=
|
||||
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
|
||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
|
|
|
@ -40,7 +40,7 @@ type Node struct {
|
|||
batchTimerMgr *BatchTimer
|
||||
|
||||
proposeC chan *raftproto.RequestBatch // proposed ready, input channel
|
||||
confChangeC <-chan raftpb.ConfChange // proposed cluster config changes
|
||||
confChangeC chan raftpb.ConfChange // proposed cluster config changes
|
||||
commitC chan *pb.CommitEvent // the hash commit channel
|
||||
errorC chan<- error // errors from raft session
|
||||
tickTimeout time.Duration // tick timeout
|
||||
|
@ -361,7 +361,7 @@ func (n *Node) run() {
|
|||
// 1: Write HardState, Entries, and Snapshot to persistent storage if they
|
||||
// are not empty.
|
||||
if err := n.raftStorage.Store(rd.Entries, rd.HardState, rd.Snapshot); err != nil {
|
||||
n.logger.Errorf("failed to persist etcd/raft data: %s", err)
|
||||
n.logger.Errorf("Failed to persist etcd/raft data: %s", err)
|
||||
}
|
||||
|
||||
if !raft.IsEmptySnap(rd.Snapshot) {
|
||||
|
|
|
@ -5,32 +5,22 @@ import (
|
|||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/coreos/etcd/raft/raftpb"
|
||||
"github.com/golang/mock/gomock"
|
||||
crypto2 "github.com/libp2p/go-libp2p-core/crypto"
|
||||
"github.com/libp2p/go-libp2p-core/peer"
|
||||
"github.com/meshplus/bitxhub-kit/crypto"
|
||||
"github.com/meshplus/bitxhub-kit/crypto/asym"
|
||||
"github.com/meshplus/bitxhub-kit/crypto/asym/ecdsa"
|
||||
"github.com/meshplus/bitxhub-kit/log"
|
||||
"github.com/meshplus/bitxhub-kit/types"
|
||||
"github.com/meshplus/bitxhub-model/pb"
|
||||
"github.com/meshplus/bitxhub/internal/ledger/mock_ledger"
|
||||
"github.com/meshplus/bitxhub/internal/model/events"
|
||||
"github.com/meshplus/bitxhub/internal/repo"
|
||||
"github.com/meshplus/bitxhub/pkg/order"
|
||||
"github.com/meshplus/bitxhub/pkg/peermgr"
|
||||
"github.com/meshplus/bitxhub/pkg/peermgr/mock_peermgr"
|
||||
libp2pcert "github.com/meshplus/go-libp2p-cert"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
const to = "0x3f9d18f7c3a6e5e4c0b877fe3e688ab08840b997"
|
||||
|
||||
func TestNode_Start(t *testing.T) {
|
||||
repoRoot, err := ioutil.TempDir("", "node")
|
||||
assert.Nil(t, err)
|
||||
|
@ -200,159 +190,53 @@ func TestMulti_Node_Start_Without_Cert_Verification(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func listen(t *testing.T, order order.Order, swarm *peermgr.Swarm) {
|
||||
orderMsgCh := make(chan events.OrderMessageEvent)
|
||||
sub := swarm.SubscribeOrderMessage(orderMsgCh)
|
||||
defer sub.Unsubscribe()
|
||||
for {
|
||||
select {
|
||||
case ev := <-orderMsgCh:
|
||||
err := order.Step(ev.Data)
|
||||
require.Nil(t, err)
|
||||
}
|
||||
func TestReportState(t *testing.T) {
|
||||
ast := assert.New(t)
|
||||
defer os.RemoveAll("./testdata/storage")
|
||||
node := mockRaftNode(t)
|
||||
err := node.Start()
|
||||
ast.Nil(err)
|
||||
blockHash := &types.Hash{
|
||||
RawHash: [types.HashLength]byte{0},
|
||||
}
|
||||
|
||||
txHashList := make([]*types.Hash, 0)
|
||||
txHash := &types.Hash{
|
||||
RawHash: [types.HashLength]byte{0},
|
||||
}
|
||||
txHashList = append(txHashList, txHash)
|
||||
node.blockAppliedIndex.Store(uint64(10), uint64(10))
|
||||
node.ReportState(uint64(10), blockHash, txHashList)
|
||||
appliedIndex, ok := node.blockAppliedIndex.Load(uint64(10))
|
||||
ast.Equal(true, ok)
|
||||
ast.Equal(uint64(10), appliedIndex.(uint64))
|
||||
nonce := node.GetPendingNonceByAccount("account1")
|
||||
ast.Equal(uint64(1), nonce)
|
||||
err = node.DelNode(uint64(1))
|
||||
}
|
||||
|
||||
func generateTx() *pb.Transaction {
|
||||
privKey, _ := asym.GenerateKeyPair(crypto.Secp256k1)
|
||||
|
||||
from, _ := privKey.PublicKey().Address()
|
||||
|
||||
tx := &pb.Transaction{
|
||||
From: from,
|
||||
To: types.NewAddressByStr(to),
|
||||
Timestamp: time.Now().UnixNano(),
|
||||
Nonce: 1,
|
||||
}
|
||||
_ = tx.Sign(privKey)
|
||||
tx.TransactionHash = tx.Hash()
|
||||
return tx
|
||||
func TestGetPendingNonceByAccount(t *testing.T) {
|
||||
ast := assert.New(t)
|
||||
defer os.RemoveAll("./testdata/storage")
|
||||
node := mockRaftNode(t)
|
||||
err := node.Start()
|
||||
ast.Nil(err)
|
||||
nonce := node.GetPendingNonceByAccount("account1")
|
||||
ast.Equal(uint64(1), nonce)
|
||||
err = node.DelNode(uint64(1))
|
||||
}
|
||||
|
||||
func peers(id uint64, addrs []string, ids []string) []*repo.NetworkNodes {
|
||||
m := make([]*repo.NetworkNodes, 0, len(addrs))
|
||||
for i, addr := range addrs {
|
||||
m = append(m, &repo.NetworkNodes{
|
||||
ID: uint64(i + 1),
|
||||
Account: "",
|
||||
Pid: ids[i],
|
||||
Hosts: []string{addr},
|
||||
})
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
func genKeysAndConfig(t *testing.T, peerCnt int) ([]crypto2.PrivKey, []crypto.PrivateKey, []string, []string) {
|
||||
var nodeKeys []crypto2.PrivKey
|
||||
var privKeys []crypto.PrivateKey
|
||||
var peers []string
|
||||
var ids []string
|
||||
|
||||
port := 5001
|
||||
|
||||
for i := 0; i < peerCnt; i++ {
|
||||
key, err := asym.GenerateKeyPair(crypto.ECDSA_P256)
|
||||
require.Nil(t, err)
|
||||
|
||||
libp2pKey, err := convertToLibp2pPrivKey(key)
|
||||
require.Nil(t, err)
|
||||
nodeKeys = append(nodeKeys, libp2pKey)
|
||||
id, err := peer.IDFromPublicKey(libp2pKey.GetPublic())
|
||||
require.Nil(t, err)
|
||||
|
||||
peer := fmt.Sprintf("/ip4/127.0.0.1/tcp/%d/p2p/", port)
|
||||
peers = append(peers, peer)
|
||||
ids = append(ids, id.String())
|
||||
port++
|
||||
|
||||
privKey, err := asym.GenerateKeyPair(crypto.Secp256k1)
|
||||
require.Nil(t, err)
|
||||
|
||||
privKeys = append(privKeys, privKey)
|
||||
}
|
||||
|
||||
return nodeKeys, privKeys, peers, ids
|
||||
}
|
||||
|
||||
func convertToLibp2pPrivKey(privateKey crypto.PrivateKey) (crypto2.PrivKey, error) {
|
||||
ecdsaPrivKey, ok := privateKey.(*ecdsa.PrivateKey)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("convert to libp2p private key: not ecdsa private key")
|
||||
}
|
||||
|
||||
libp2pPrivKey, _, err := crypto2.ECDSAKeyPairFromKey(ecdsaPrivKey.K)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return libp2pPrivKey, nil
|
||||
}
|
||||
|
||||
func newSwarms(t *testing.T, peerCnt int, certVerify bool) ([]*peermgr.Swarm, map[uint64]*pb.VpInfo) {
|
||||
var swarms []*peermgr.Swarm
|
||||
nodes := make(map[uint64]*pb.VpInfo)
|
||||
nodeKeys, privKeys, addrs, ids := genKeysAndConfig(t, peerCnt)
|
||||
mockCtl := gomock.NewController(t)
|
||||
mockLedger := mock_ledger.NewMockLedger(mockCtl)
|
||||
|
||||
agencyData, err := ioutil.ReadFile("testdata/agency.cert")
|
||||
require.Nil(t, err)
|
||||
|
||||
nodeData, err := ioutil.ReadFile("testdata/node.cert")
|
||||
require.Nil(t, err)
|
||||
|
||||
caData, err := ioutil.ReadFile("testdata/ca.cert")
|
||||
require.Nil(t, err)
|
||||
|
||||
cert, err := libp2pcert.ParseCert(caData)
|
||||
require.Nil(t, err)
|
||||
|
||||
for i := 0; i < peerCnt; i++ {
|
||||
ID := i + 1
|
||||
repo := &repo.Repo{
|
||||
Key: &repo.Key{},
|
||||
NetworkConfig: &repo.NetworkConfig{
|
||||
N: uint64(peerCnt),
|
||||
ID: uint64(ID),
|
||||
},
|
||||
Certs: &libp2pcert.Certs{
|
||||
NodeCertData: nodeData,
|
||||
AgencyCertData: agencyData,
|
||||
CACert: cert,
|
||||
},
|
||||
Config: &repo.Config{
|
||||
Ping: repo.Ping{
|
||||
Duration: 2 * time.Second,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
if certVerify {
|
||||
repo.Config.Cert.Verify = true
|
||||
} else {
|
||||
repo.Config.Cert.Verify = false
|
||||
}
|
||||
|
||||
idx := strings.LastIndex(addrs[i], "/p2p/")
|
||||
local := addrs[i][:idx]
|
||||
repo.NetworkConfig.LocalAddr = local
|
||||
repo.Key.Libp2pPrivKey = nodeKeys[i]
|
||||
repo.Key.PrivKey = privKeys[i]
|
||||
repo.NetworkConfig.Nodes = peers(uint64(i), addrs, ids)
|
||||
|
||||
address, err := privKeys[i].PublicKey().Address()
|
||||
require.Nil(t, err)
|
||||
vpInfo := &pb.VpInfo{
|
||||
Id: uint64(ID),
|
||||
Account: address.String(),
|
||||
}
|
||||
nodes[uint64(ID)] = vpInfo
|
||||
swarm, err := peermgr.New(repo, log.NewWithModule("p2p"), mockLedger)
|
||||
require.Nil(t, err)
|
||||
err = swarm.Start()
|
||||
require.Nil(t, err)
|
||||
swarms = append(swarms, swarm)
|
||||
}
|
||||
return swarms, nodes
|
||||
func TestRun(t *testing.T) {
|
||||
ast := assert.New(t)
|
||||
defer os.RemoveAll("./testdata/storage")
|
||||
node := mockRaftNode(t)
|
||||
node.checkInterval = 200 * time.Millisecond
|
||||
err := node.Start()
|
||||
ast.Nil(err)
|
||||
// test confChangeC
|
||||
node.confChangeC <- raftpb.ConfChange{ID: uint64(2)}
|
||||
// test rebroadcastTicker
|
||||
txs := make([]*pb.Transaction, 0)
|
||||
txs = append(txs, constructTx(1))
|
||||
node.mempool.ProcessTransactions(txs, false, true)
|
||||
time.Sleep(250 * time.Millisecond)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,280 @@
|
|||
package etcdraft
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/coreos/etcd/raft"
|
||||
"github.com/coreos/etcd/raft/raftpb"
|
||||
"github.com/golang/mock/gomock"
|
||||
crypto2 "github.com/libp2p/go-libp2p-core/crypto"
|
||||
"github.com/libp2p/go-libp2p-core/peer"
|
||||
"github.com/meshplus/bitxhub-kit/crypto"
|
||||
"github.com/meshplus/bitxhub-kit/crypto/asym"
|
||||
"github.com/meshplus/bitxhub-kit/crypto/asym/ecdsa"
|
||||
"github.com/meshplus/bitxhub-kit/log"
|
||||
"github.com/meshplus/bitxhub-kit/types"
|
||||
"github.com/meshplus/bitxhub-model/pb"
|
||||
"github.com/meshplus/bitxhub/internal/ledger/mock_ledger"
|
||||
"github.com/meshplus/bitxhub/internal/model/events"
|
||||
"github.com/meshplus/bitxhub/internal/repo"
|
||||
"github.com/meshplus/bitxhub/pkg/order"
|
||||
raftproto "github.com/meshplus/bitxhub/pkg/order/etcdraft/proto"
|
||||
"github.com/meshplus/bitxhub/pkg/order/mempool"
|
||||
"github.com/meshplus/bitxhub/pkg/peermgr"
|
||||
libp2pcert "github.com/meshplus/go-libp2p-cert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
const to = "0x3f9d18f7c3a6e5e4c0b877fe3e688ab08840b997"
|
||||
|
||||
func constructTx(nonce uint64) *pb.Transaction {
|
||||
privK, _ := asym.GenerateKeyPair(crypto.Secp256k1)
|
||||
pubKey := privK.PublicKey()
|
||||
addr, _ := pubKey.Address()
|
||||
tx := &pb.Transaction{Nonce: nonce}
|
||||
tx.Timestamp = time.Now().UnixNano()
|
||||
tx.From = addr
|
||||
sig, _ := privK.Sign(tx.SignHash().Bytes())
|
||||
tx.Signature = sig
|
||||
tx.TransactionHash = tx.Hash()
|
||||
tx.Nonce = nonce
|
||||
return tx
|
||||
}
|
||||
|
||||
func mockRaftNode(t *testing.T) *Node {
|
||||
logger := log.NewWithModule("consensus")
|
||||
batchTimerMgr := NewTimer(500*time.Millisecond, logger)
|
||||
txCache := mempool.NewTxCache(25*time.Millisecond, uint64(2), logger)
|
||||
walDir := filepath.Join("./testdata/storage", "wal")
|
||||
snapDir := filepath.Join("./testdata/storage", "snap")
|
||||
dbDir := filepath.Join("./testdata/storage", "state")
|
||||
raftStorage, dbStorage, _ := CreateStorage(logger, walDir, snapDir, dbDir, raft.NewMemoryStorage())
|
||||
repoRoot := "./testdata/"
|
||||
raftConfig, _ := generateRaftConfig(repoRoot)
|
||||
peerCnt := 4
|
||||
swarms, _ := newSwarms(t, peerCnt, false)
|
||||
mempoolConf := &mempool.Config{
|
||||
ID: uint64(1),
|
||||
ChainHeight: uint64(1),
|
||||
Logger: logger,
|
||||
BatchSize: raftConfig.RAFT.MempoolConfig.BatchSize,
|
||||
PoolSize: raftConfig.RAFT.MempoolConfig.PoolSize,
|
||||
TxSliceSize: raftConfig.RAFT.MempoolConfig.TxSliceSize,
|
||||
TxSliceTimeout: raftConfig.RAFT.MempoolConfig.TxSliceTimeout,
|
||||
}
|
||||
mempoolInst := mempool.NewMempool(mempoolConf)
|
||||
node := &Node{
|
||||
id: uint64(1),
|
||||
lastExec: uint64(1),
|
||||
repoRoot: repoRoot,
|
||||
logger: logger,
|
||||
confChangeC: make(chan raftpb.ConfChange),
|
||||
commitC: make(chan *pb.CommitEvent, 1024),
|
||||
errorC: make(chan<- error),
|
||||
msgC: make(chan []byte),
|
||||
stateC: make(chan *mempool.ChainState),
|
||||
proposeC: make(chan *raftproto.RequestBatch),
|
||||
txCache: txCache,
|
||||
batchTimerMgr: batchTimerMgr,
|
||||
storage: dbStorage,
|
||||
raftStorage: raftStorage,
|
||||
mempool: mempoolInst,
|
||||
tickTimeout: 500 * time.Millisecond,
|
||||
checkInterval: 3 * time.Minute,
|
||||
ctx: context.Background(),
|
||||
peerMgr: swarms[0],
|
||||
getChainMetaFunc: getChainMetaFunc,
|
||||
}
|
||||
node.syncer = &mockSync{}
|
||||
return node
|
||||
}
|
||||
|
||||
type mockSync struct{}
|
||||
|
||||
// SyncCFTBlocks fetches the block list from other node, and just fetches but not verifies the block
|
||||
func (sync *mockSync) SyncCFTBlocks(begin, end uint64, blockCh chan *pb.Block) error {
|
||||
for i := begin; i <= end; i++ {
|
||||
blockHeight := i
|
||||
header := &pb.BlockHeader{Number: blockHeight}
|
||||
blockHash := &types.Hash{
|
||||
RawHash: [types.HashLength]byte{0},
|
||||
}
|
||||
blockCh <- &pb.Block{BlockHeader: header, BlockHash: blockHash}
|
||||
}
|
||||
blockCh <- nil
|
||||
return nil
|
||||
}
|
||||
|
||||
// SyncBFTBlocks fetches the block list from quorum nodes, and verifies all the block
|
||||
func (sync *mockSync) SyncBFTBlocks(begin, end uint64, metaHash *types.Hash, blockCh chan *pb.Block) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func getChainMetaFunc() *pb.ChainMeta {
|
||||
blockHash := &types.Hash{
|
||||
RawHash: [types.HashLength]byte{1},
|
||||
}
|
||||
return &pb.ChainMeta{
|
||||
Height: uint64(1),
|
||||
BlockHash: blockHash,
|
||||
}
|
||||
}
|
||||
func listen(t *testing.T, order order.Order, swarm *peermgr.Swarm) {
|
||||
orderMsgCh := make(chan events.OrderMessageEvent)
|
||||
sub := swarm.SubscribeOrderMessage(orderMsgCh)
|
||||
defer sub.Unsubscribe()
|
||||
for {
|
||||
select {
|
||||
case ev := <-orderMsgCh:
|
||||
err := order.Step(ev.Data)
|
||||
require.Nil(t, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func generateTx() *pb.Transaction {
|
||||
privKey, _ := asym.GenerateKeyPair(crypto.Secp256k1)
|
||||
from, _ := privKey.PublicKey().Address()
|
||||
tx := &pb.Transaction{
|
||||
From: from,
|
||||
To: types.NewAddressByStr(to),
|
||||
Timestamp: time.Now().UnixNano(),
|
||||
Nonce: 1,
|
||||
}
|
||||
_ = tx.Sign(privKey)
|
||||
tx.TransactionHash = tx.Hash()
|
||||
return tx
|
||||
}
|
||||
|
||||
func peers(id uint64, addrs []string, ids []string) []*repo.NetworkNodes {
|
||||
m := make([]*repo.NetworkNodes, 0, len(addrs))
|
||||
for i, addr := range addrs {
|
||||
m = append(m, &repo.NetworkNodes{
|
||||
ID: uint64(i + 1),
|
||||
Account: "",
|
||||
Pid: ids[i],
|
||||
Hosts: []string{addr},
|
||||
})
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
func genKeysAndConfig(t *testing.T, peerCnt int) ([]crypto2.PrivKey, []crypto.PrivateKey, []string, []string) {
|
||||
var nodeKeys []crypto2.PrivKey
|
||||
var privKeys []crypto.PrivateKey
|
||||
var peers []string
|
||||
var ids []string
|
||||
|
||||
port := 5001
|
||||
|
||||
for i := 0; i < peerCnt; i++ {
|
||||
key, err := asym.GenerateKeyPair(crypto.ECDSA_P256)
|
||||
require.Nil(t, err)
|
||||
|
||||
libp2pKey, err := convertToLibp2pPrivKey(key)
|
||||
require.Nil(t, err)
|
||||
nodeKeys = append(nodeKeys, libp2pKey)
|
||||
id, err := peer.IDFromPublicKey(libp2pKey.GetPublic())
|
||||
require.Nil(t, err)
|
||||
|
||||
peer := fmt.Sprintf("/ip4/127.0.0.1/tcp/%d/p2p/", port)
|
||||
peers = append(peers, peer)
|
||||
ids = append(ids, id.String())
|
||||
port++
|
||||
|
||||
privKey, err := asym.GenerateKeyPair(crypto.Secp256k1)
|
||||
require.Nil(t, err)
|
||||
|
||||
privKeys = append(privKeys, privKey)
|
||||
}
|
||||
|
||||
return nodeKeys, privKeys, peers, ids
|
||||
}
|
||||
|
||||
func convertToLibp2pPrivKey(privateKey crypto.PrivateKey) (crypto2.PrivKey, error) {
|
||||
ecdsaPrivKey, ok := privateKey.(*ecdsa.PrivateKey)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("convert to libp2p private key: not ecdsa private key")
|
||||
}
|
||||
|
||||
libp2pPrivKey, _, err := crypto2.ECDSAKeyPairFromKey(ecdsaPrivKey.K)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return libp2pPrivKey, nil
|
||||
}
|
||||
|
||||
func newSwarms(t *testing.T, peerCnt int, certVerify bool) ([]*peermgr.Swarm, map[uint64]*pb.VpInfo) {
|
||||
var swarms []*peermgr.Swarm
|
||||
nodes := make(map[uint64]*pb.VpInfo)
|
||||
nodeKeys, privKeys, addrs, ids := genKeysAndConfig(t, peerCnt)
|
||||
mockCtl := gomock.NewController(t)
|
||||
mockLedger := mock_ledger.NewMockLedger(mockCtl)
|
||||
|
||||
agencyData, err := ioutil.ReadFile("testdata/agency.cert")
|
||||
require.Nil(t, err)
|
||||
|
||||
nodeData, err := ioutil.ReadFile("testdata/node.cert")
|
||||
require.Nil(t, err)
|
||||
|
||||
caData, err := ioutil.ReadFile("testdata/ca.cert")
|
||||
require.Nil(t, err)
|
||||
|
||||
cert, err := libp2pcert.ParseCert(caData)
|
||||
require.Nil(t, err)
|
||||
|
||||
for i := 0; i < peerCnt; i++ {
|
||||
ID := i + 1
|
||||
repo := &repo.Repo{
|
||||
Key: &repo.Key{},
|
||||
NetworkConfig: &repo.NetworkConfig{
|
||||
N: uint64(peerCnt),
|
||||
ID: uint64(ID),
|
||||
},
|
||||
Certs: &libp2pcert.Certs{
|
||||
NodeCertData: nodeData,
|
||||
AgencyCertData: agencyData,
|
||||
CACert: cert,
|
||||
},
|
||||
Config: &repo.Config{
|
||||
Ping: repo.Ping{
|
||||
Duration: 2 * time.Second,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
if certVerify {
|
||||
repo.Config.Cert.Verify = true
|
||||
} else {
|
||||
repo.Config.Cert.Verify = false
|
||||
}
|
||||
|
||||
idx := strings.LastIndex(addrs[i], "/p2p/")
|
||||
local := addrs[i][:idx]
|
||||
repo.NetworkConfig.LocalAddr = local
|
||||
repo.Key.Libp2pPrivKey = nodeKeys[i]
|
||||
repo.Key.PrivKey = privKeys[i]
|
||||
repo.NetworkConfig.Nodes = peers(uint64(i), addrs, ids)
|
||||
|
||||
address, err := privKeys[i].PublicKey().Address()
|
||||
require.Nil(t, err)
|
||||
vpInfo := &pb.VpInfo{
|
||||
Id: uint64(ID),
|
||||
Account: address.String(),
|
||||
}
|
||||
nodes[uint64(ID)] = vpInfo
|
||||
swarm, err := peermgr.New(repo, log.NewWithModule("p2p"), mockLedger)
|
||||
require.Nil(t, err)
|
||||
err = swarm.Start()
|
||||
require.Nil(t, err)
|
||||
swarms = append(swarms, swarm)
|
||||
}
|
||||
return swarms, nodes
|
||||
}
|
|
@ -2,7 +2,6 @@ package etcdraft
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
|
@ -83,8 +82,7 @@ func CreateStorage(
|
|||
}
|
||||
} else {
|
||||
// snapshot found
|
||||
lg.Debugf("Loaded snapshot at Term %d and Index %d, Nodes: %+v",
|
||||
snapshot.Metadata.Term, snapshot.Metadata.Index, snapshot.Metadata.ConfState.Nodes)
|
||||
lg.Debugf("Loaded snapshot at Term %d and Index %d, Nodes: %+v", snapshot.Metadata.Term, snapshot.Metadata.Index, snapshot.Metadata.ConfState.Nodes)
|
||||
}
|
||||
|
||||
w, st, ents, err := createOrReadWAL(lg, walDir, snapshot)
|
||||
|
@ -116,14 +114,14 @@ func CreateStorage(
|
|||
return nil, nil, errors.Errorf("Failed to new leveldb: %s", err)
|
||||
}
|
||||
return &RaftStorage{
|
||||
lg: lg,
|
||||
ram: ram,
|
||||
wal: w,
|
||||
snap: sn,
|
||||
walDir: walDir,
|
||||
snapDir: snapDir,
|
||||
db: db,
|
||||
snapshotIndex: ListSnapshots(lg, snapDir),
|
||||
lg: lg,
|
||||
ram: ram,
|
||||
wal: w,
|
||||
snap: sn,
|
||||
walDir: walDir,
|
||||
snapDir: snapDir,
|
||||
db: db,
|
||||
snapshotIndex: ListSnapshots(lg, snapDir),
|
||||
}, db, nil
|
||||
}
|
||||
|
||||
|
@ -157,17 +155,8 @@ func ListSnapshots(logger raft.Logger, snapDir string) []uint64 {
|
|||
s, err := snap.Read(fpath)
|
||||
if err != nil {
|
||||
logger.Errorf("Snapshot file %s is corrupted: %s", fpath, err)
|
||||
|
||||
broken := fpath + ".broken"
|
||||
if err = os.Rename(fpath, broken); err != nil {
|
||||
logger.Errorf("Failed to rename corrupted snapshot file %s to %s: %s", fpath, broken, err)
|
||||
} else {
|
||||
logger.Debugf("Renaming corrupted snapshot file %s to %s", fpath, broken)
|
||||
}
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
snapshots = append(snapshots, s.Metadata.Index)
|
||||
}
|
||||
|
||||
|
@ -189,10 +178,6 @@ func createOrReadWAL(lg raft.Logger, walDir string, snapshot *raftpb.Snapshot) (
|
|||
// TODO(jay_guo) add metadata to be persisted with wal once we need it.
|
||||
// use case could be data dump and restore on a new node.
|
||||
w, err := wal.Create(walDir, nil)
|
||||
if err == os.ErrExist {
|
||||
lg.Fatalf("programming error, we've just checked that WAL does not exist")
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return nil, st, nil, errors.Errorf("failed to initialize WAL: %s", err)
|
||||
}
|
||||
|
@ -212,46 +197,17 @@ func createOrReadWAL(lg raft.Logger, walDir string, snapshot *raftpb.Snapshot) (
|
|||
|
||||
lg.Debugf("Loading WAL at Term %d and Index %d", walsnap.Term, walsnap.Index)
|
||||
|
||||
var repaired bool
|
||||
for {
|
||||
if w, err = wal.Open(walDir, walsnap); err != nil {
|
||||
return nil, st, nil, errors.Errorf("failed to open WAL: %s", err)
|
||||
}
|
||||
if w, err = wal.Open(walDir, walsnap); err != nil {
|
||||
return nil, st, nil, errors.Errorf("failed to open WAL: %s", err)
|
||||
}
|
||||
|
||||
if _, st, ents, err = w.ReadAll(); err != nil {
|
||||
lg.Warningf("Failed to read WAL: %s", err)
|
||||
|
||||
if errc := w.Close(); errc != nil {
|
||||
return nil, st, nil, errors.Errorf("failed to close erroneous WAL: %s", errc)
|
||||
}
|
||||
|
||||
// only repair UnexpectedEOF and only repair once
|
||||
if repaired || err != io.ErrUnexpectedEOF {
|
||||
return nil, st, nil, errors.Errorf("failed to read WAL and cannot repair: %s", err)
|
||||
}
|
||||
|
||||
if !wal.Repair(walDir) {
|
||||
return nil, st, nil, errors.Errorf("failed to repair WAL: %s", err)
|
||||
}
|
||||
|
||||
repaired = true
|
||||
// next loop should be able to open WAL and return
|
||||
continue
|
||||
}
|
||||
|
||||
// successfully opened WAL and read all entries, break
|
||||
break
|
||||
if _, st, ents, err = w.ReadAll(); err != nil {
|
||||
return nil, st, nil, errors.Errorf("failed to read WAL: %s", err)
|
||||
}
|
||||
|
||||
return w, st, ents, nil
|
||||
}
|
||||
|
||||
// Snapshot returns the latest snapshot stored in memory
|
||||
func (rs *RaftStorage) Snapshot() raftpb.Snapshot {
|
||||
sn, _ := rs.ram.Snapshot() // Snapshot always returns nil error
|
||||
return sn
|
||||
}
|
||||
|
||||
// Store persists etcd/raft data
|
||||
func (rs *RaftStorage) Store(entries []raftpb.Entry, hardstate raftpb.HardState, snapshot raftpb.Snapshot) error {
|
||||
if err := rs.wal.Save(hardstate, entries); err != nil {
|
||||
|
@ -263,13 +219,8 @@ func (rs *RaftStorage) Store(entries []raftpb.Entry, hardstate raftpb.HardState,
|
|||
return err
|
||||
}
|
||||
|
||||
if err := rs.ram.ApplySnapshot(snapshot); err != nil {
|
||||
if err == raft.ErrSnapOutOfDate {
|
||||
rs.lg.Warningf("Attempted to apply out-of-date snapshot at Term %d and Index %d",
|
||||
snapshot.Metadata.Term, snapshot.Metadata.Index)
|
||||
} else {
|
||||
rs.lg.Fatalf("Unexpected programming error: %s", err)
|
||||
}
|
||||
if err := rs.ram.ApplySnapshot(snapshot); err != nil && err != raft.ErrSnapOutOfDate {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -325,12 +276,8 @@ func (rs *RaftStorage) TakeSnapshot(i uint64, cs raftpb.ConfState, data []byte)
|
|||
if i > rs.SnapshotCatchUpEntries {
|
||||
compacti := i - rs.SnapshotCatchUpEntries
|
||||
rs.lg.Debugf("Purging in-memory raft entries prior to %d", compacti)
|
||||
if err = rs.ram.Compact(compacti); err != nil {
|
||||
if err == raft.ErrCompacted {
|
||||
rs.lg.Warningf("Raft entries prior to %d are already purged", compacti)
|
||||
} else {
|
||||
rs.lg.Fatalf("Failed to purge raft entries: %s", err)
|
||||
}
|
||||
if err = rs.ram.Compact(compacti); err != nil && err != raft.ErrCompacted {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -395,10 +342,6 @@ func (rs *RaftStorage) purgeSnap() {
|
|||
var files []string
|
||||
for _, f := range snapFiles {
|
||||
if !strings.HasSuffix(f, ".snap") {
|
||||
if strings.HasPrefix(f, ".broken") {
|
||||
rs.lg.Warningf("Found broken snapshot file %s, it can be removed manually", f)
|
||||
}
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
|
@ -433,18 +376,6 @@ func (rs *RaftStorage) purge(files []string) {
|
|||
}
|
||||
}
|
||||
|
||||
// ApplySnapshot applies snapshot to local memory storage
|
||||
func (rs *RaftStorage) ApplySnapshot(snap raftpb.Snapshot) {
|
||||
if err := rs.ram.ApplySnapshot(snap); err != nil {
|
||||
if err == raft.ErrSnapOutOfDate {
|
||||
rs.lg.Warningf("Attempted to apply out-of-date snapshot at Term %d and Index %d",
|
||||
snap.Metadata.Term, snap.Metadata.Index)
|
||||
} else {
|
||||
rs.lg.Fatalf("Unexpected programming error: %s", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Close closes storage
|
||||
func (rs *RaftStorage) Close() error {
|
||||
if err := rs.wal.Close(); err != nil {
|
||||
|
|
|
@ -0,0 +1,111 @@
|
|||
package etcdraft
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/coreos/etcd/raft/raftpb"
|
||||
"github.com/meshplus/bitxhub-kit/types"
|
||||
"github.com/meshplus/bitxhub-model/pb"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestRecoverFromSnapshot(t *testing.T) {
|
||||
ast := assert.New(t)
|
||||
defer os.RemoveAll("./testdata/storage")
|
||||
node := mockRaftNode(t)
|
||||
err := node.Start()
|
||||
ast.Nil(err)
|
||||
snap := raftpb.Snapshot{Data: []byte("test"), Metadata: raftpb.SnapshotMetadata{Index: uint64(2), Term: uint64(1)}}
|
||||
err = node.raftStorage.snap.SaveSnap(snap)
|
||||
ast.Nil(err)
|
||||
node.recoverFromSnapshot()
|
||||
ast.NotEqual(uint64(2), node.appliedIndex, "wrong type data")
|
||||
ast.NotEqual(uint64(2), node.snapshotIndex, "wrong type data")
|
||||
|
||||
go func() {
|
||||
block := <-node.commitC
|
||||
ast.Equal(uint64(2), block.Block.BlockHeader.Number)
|
||||
}()
|
||||
blockHash := &types.Hash{
|
||||
RawHash: [types.HashLength]byte{2},
|
||||
}
|
||||
snapData := &pb.ChainMeta{Height: uint64(2), BlockHash: blockHash}
|
||||
snapDataBytes, _ := snapData.Marshal()
|
||||
snap.Data = snapDataBytes
|
||||
err = node.raftStorage.snap.SaveSnap(snap)
|
||||
ast.Nil(err)
|
||||
node.recoverFromSnapshot()
|
||||
ast.Equal(uint64(2), node.appliedIndex)
|
||||
ast.Equal(uint64(2), node.snapshotIndex)
|
||||
}
|
||||
|
||||
func TestTakeSnapshotAndGC(t *testing.T) {
|
||||
ast := assert.New(t)
|
||||
defer os.RemoveAll("./testdata/storage")
|
||||
node := mockRaftNode(t)
|
||||
err := node.Start()
|
||||
ast.Nil(err)
|
||||
entries := []raftpb.Entry{raftpb.Entry{Term: uint64(1), Index: uint64(1)}}
|
||||
node.raftStorage.ram.Append(entries)
|
||||
err = node.raftStorage.TakeSnapshot(uint64(1), node.confState, []byte("test"))
|
||||
ast.Nil(err)
|
||||
ast.Equal(1, len(node.raftStorage.snapshotIndex))
|
||||
|
||||
entries = []raftpb.Entry{raftpb.Entry{Term: uint64(1), Index: uint64(2)}}
|
||||
node.raftStorage.ram.Append(entries)
|
||||
err = node.raftStorage.TakeSnapshot(uint64(2), node.confState, []byte("test2"))
|
||||
|
||||
entries = []raftpb.Entry{raftpb.Entry{Term: uint64(1), Index: uint64(3)}}
|
||||
node.raftStorage.ram.Append(entries)
|
||||
err = node.raftStorage.TakeSnapshot(uint64(3), node.confState, []byte("test3"))
|
||||
|
||||
entries = []raftpb.Entry{raftpb.Entry{Term: uint64(1), Index: uint64(4)}}
|
||||
node.raftStorage.ram.Append(entries)
|
||||
err = node.raftStorage.TakeSnapshot(uint64(4), node.confState, []byte("test4"))
|
||||
ast.Equal(4, len(node.raftStorage.snapshotIndex))
|
||||
|
||||
entries = []raftpb.Entry{raftpb.Entry{Term: uint64(1), Index: uint64(5)}}
|
||||
node.raftStorage.ram.Append(entries)
|
||||
err = node.raftStorage.TakeSnapshot(uint64(5), node.confState, []byte("test5"))
|
||||
ast.Equal(5, len(node.raftStorage.snapshotIndex))
|
||||
|
||||
entries = []raftpb.Entry{raftpb.Entry{Term: uint64(1), Index: uint64(6)}}
|
||||
node.raftStorage.ram.Append(entries)
|
||||
err = node.raftStorage.TakeSnapshot(uint64(6), node.confState, []byte("test6"))
|
||||
ast.Equal(5, len(node.raftStorage.snapshotIndex), "gc Snap and wal 1")
|
||||
|
||||
err = node.raftStorage.Close()
|
||||
ast.Nil(err)
|
||||
}
|
||||
|
||||
func TestCreateOrReadWAL(t *testing.T) {
|
||||
ast := assert.New(t)
|
||||
defer os.RemoveAll("./testdata/storage")
|
||||
node := mockRaftNode(t)
|
||||
err := node.Start()
|
||||
ast.Nil(err)
|
||||
entries := []raftpb.Entry{raftpb.Entry{Term: uint64(1), Index: uint64(1)}}
|
||||
snap := raftpb.Snapshot{Data: []byte("test"), Metadata: raftpb.SnapshotMetadata{Index: uint64(2), Term: uint64(1)}}
|
||||
blockHash := &types.Hash{
|
||||
RawHash: [types.HashLength]byte{2},
|
||||
}
|
||||
snapData := &pb.ChainMeta{Height: uint64(2), BlockHash: blockHash}
|
||||
snapDataBytes, _ := snapData.Marshal()
|
||||
snap.Data = snapDataBytes
|
||||
hardstate := raftpb.HardState{Term: uint64(1), Commit: uint64(0)}
|
||||
err = node.raftStorage.Store(entries, hardstate, snap)
|
||||
ast.Nil(err)
|
||||
_, _, _, err = createOrReadWAL(node.logger, node.raftStorage.walDir, &snap)
|
||||
ast.NotNil(err, "requested entry index 1 is older than the existing snapshot 2")
|
||||
|
||||
entries = []raftpb.Entry{raftpb.Entry{Term: uint64(1), Index: uint64(4)}}
|
||||
snap.Metadata.Index = uint64(3)
|
||||
err = node.raftStorage.Store(entries, hardstate, snap)
|
||||
ast.Nil(err)
|
||||
_ = node.raftStorage.wal.Close()
|
||||
_, st, ents, err1 := createOrReadWAL(node.logger, node.raftStorage.walDir, &snap)
|
||||
ast.Nil(err1)
|
||||
ast.Equal(uint64(1), st.Term)
|
||||
ast.Equal(1, len(ents))
|
||||
}
|
|
@ -56,4 +56,4 @@ func (timer *BatchTimer) StopBatchTimer() {
|
|||
|
||||
func (timer *BatchTimer) BatchTimeoutEvent() chan bool {
|
||||
return timer.timeoutEventC
|
||||
}
|
||||
}
|
||||
|
|
|
@ -59,6 +59,8 @@ func TestGetPendingNonceByAccount(t *testing.T) {
|
|||
ast.Equal(uint64(3), nonce)
|
||||
nonce = mpi.GetPendingNonceByAccount(account2.String())
|
||||
ast.Equal(uint64(3), nonce, "not 4")
|
||||
ifFull := mpi.IsPoolFull()
|
||||
ast.Equal(false, ifFull)
|
||||
}
|
||||
|
||||
func TestCommitTransactions(t *testing.T) {
|
||||
|
|
Loading…
Reference in New Issue