mirror of https://github.com/poanetwork/gecko.git
commit
283824972d
7
go.mod
7
go.mod
|
@ -6,10 +6,10 @@ require (
|
||||||
github.com/AppsFlyer/go-sundheit v0.2.0
|
github.com/AppsFlyer/go-sundheit v0.2.0
|
||||||
github.com/allegro/bigcache v1.2.1 // indirect
|
github.com/allegro/bigcache v1.2.1 // indirect
|
||||||
github.com/aristanetworks/goarista v0.0.0-20200520141224-0f14e646773f // indirect
|
github.com/aristanetworks/goarista v0.0.0-20200520141224-0f14e646773f // indirect
|
||||||
github.com/ava-labs/coreth v0.2.5 // Added manually; don't delete
|
github.com/ava-labs/coreth v0.2.5 // indirect; Added manually; don't delete
|
||||||
github.com/ava-labs/go-ethereum v1.9.3 // indirect
|
github.com/ava-labs/go-ethereum v1.9.3 // indirect
|
||||||
github.com/deckarep/golang-set v1.7.1 // indirect
|
github.com/deckarep/golang-set v1.7.1 // indirect
|
||||||
github.com/decred/dcrd/dcrec/secp256k1 v1.0.3
|
github.com/decred/dcrd/dcrec/secp256k1 v1.0.3 // indirect
|
||||||
github.com/decred/dcrd/dcrec/secp256k1/v3 v3.0.0-20200526030155-0c6c7ca85d3b
|
github.com/decred/dcrd/dcrec/secp256k1/v3 v3.0.0-20200526030155-0c6c7ca85d3b
|
||||||
github.com/edsrzf/mmap-go v1.0.0 // indirect
|
github.com/edsrzf/mmap-go v1.0.0 // indirect
|
||||||
github.com/elastic/gosigar v0.10.5 // indirect
|
github.com/elastic/gosigar v0.10.5 // indirect
|
||||||
|
@ -29,12 +29,11 @@ require (
|
||||||
github.com/karalabe/usb v0.0.0-20191104083709-911d15fe12a9 // indirect
|
github.com/karalabe/usb v0.0.0-20191104083709-911d15fe12a9 // indirect
|
||||||
github.com/mattn/go-colorable v0.1.6 // indirect
|
github.com/mattn/go-colorable v0.1.6 // indirect
|
||||||
github.com/mitchellh/go-homedir v1.1.0
|
github.com/mitchellh/go-homedir v1.1.0
|
||||||
github.com/mr-tron/base58 v1.1.3
|
github.com/mr-tron/base58 v1.2.0
|
||||||
github.com/nbutton23/zxcvbn-go v0.0.0-20180912185939-ae427f1e4c1d
|
github.com/nbutton23/zxcvbn-go v0.0.0-20180912185939-ae427f1e4c1d
|
||||||
github.com/olekukonko/tablewriter v0.0.4 // indirect
|
github.com/olekukonko/tablewriter v0.0.4 // indirect
|
||||||
github.com/pborman/uuid v1.2.0 // indirect
|
github.com/pborman/uuid v1.2.0 // indirect
|
||||||
github.com/prometheus/client_golang v1.6.0
|
github.com/prometheus/client_golang v1.6.0
|
||||||
github.com/prometheus/common v0.9.1
|
|
||||||
github.com/prometheus/tsdb v0.10.0 // indirect
|
github.com/prometheus/tsdb v0.10.0 // indirect
|
||||||
github.com/rjeczalik/notify v0.9.2 // indirect
|
github.com/rjeczalik/notify v0.9.2 // indirect
|
||||||
github.com/rs/cors v1.7.0
|
github.com/rs/cors v1.7.0
|
||||||
|
|
12
go.sum
12
go.sum
|
@ -43,7 +43,9 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
|
||||||
github.com/deckarep/golang-set v1.7.1 h1:SCQV0S6gTtp6itiFrTqI+pfmJ4LN85S1YzhDf9rTHJQ=
|
github.com/deckarep/golang-set v1.7.1 h1:SCQV0S6gTtp6itiFrTqI+pfmJ4LN85S1YzhDf9rTHJQ=
|
||||||
github.com/deckarep/golang-set v1.7.1/go.mod h1:93vsz/8Wt4joVM7c2AVqh+YRMiUSc14yDtF28KmMOgQ=
|
github.com/deckarep/golang-set v1.7.1/go.mod h1:93vsz/8Wt4joVM7c2AVqh+YRMiUSc14yDtF28KmMOgQ=
|
||||||
github.com/decred/dcrd v1.3.0 h1:EEXm7BdiROfazDtuFsOu9mfotnyy00bgCuVwUqaszFo=
|
github.com/decred/dcrd v1.3.0 h1:EEXm7BdiROfazDtuFsOu9mfotnyy00bgCuVwUqaszFo=
|
||||||
|
github.com/decred/dcrd/chaincfg/chainhash v1.0.2 h1:rt5Vlq/jM3ZawwiacWjPa+smINyLRN07EO0cNBV6DGU=
|
||||||
github.com/decred/dcrd/chaincfg/chainhash v1.0.2/go.mod h1:BpbrGgrPTr3YJYRN3Bm+D9NuaFd+zGyNeIKgrhCXK60=
|
github.com/decred/dcrd/chaincfg/chainhash v1.0.2/go.mod h1:BpbrGgrPTr3YJYRN3Bm+D9NuaFd+zGyNeIKgrhCXK60=
|
||||||
|
github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK09Y2A4Xv7EE0=
|
||||||
github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc=
|
github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc=
|
||||||
github.com/decred/dcrd/dcrec v1.0.0 h1:W+z6Es+Rai3MXYVoPAxYr5U1DGis0Co33scJ6uH2J6o=
|
github.com/decred/dcrd/dcrec v1.0.0 h1:W+z6Es+Rai3MXYVoPAxYr5U1DGis0Co33scJ6uH2J6o=
|
||||||
github.com/decred/dcrd/dcrec/secp256k1 v1.0.3 h1:u4XpHqlscRolxPxt2YHrFBDVZYY1AK+KMV02H1r+HmU=
|
github.com/decred/dcrd/dcrec/secp256k1 v1.0.3 h1:u4XpHqlscRolxPxt2YHrFBDVZYY1AK+KMV02H1r+HmU=
|
||||||
|
@ -69,6 +71,7 @@ github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5/go.mod h1:VvhXpOYNQvB+
|
||||||
github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw=
|
github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw=
|
||||||
github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g=
|
github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g=
|
||||||
github.com/frankban/quicktest v1.7.2/go.mod h1:jaStnuzAqU1AJdCO0l53JDCJrVDKcS03DbaAcR7Ks/o=
|
github.com/frankban/quicktest v1.7.2/go.mod h1:jaStnuzAqU1AJdCO0l53JDCJrVDKcS03DbaAcR7Ks/o=
|
||||||
|
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/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/garyburd/redigo v1.6.0/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY=
|
||||||
github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 h1:f6D9Hr8xV8uYKlyuj8XIruxlh9WjVjdh1gIicAS7ays=
|
github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 h1:f6D9Hr8xV8uYKlyuj8XIruxlh9WjVjdh1gIicAS7ays=
|
||||||
|
@ -82,6 +85,7 @@ github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk=
|
||||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||||
|
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6 h1:ZgQEtGgCBiWRM39fZuwSd1LwSqqSW0hOdXCYYDX0R3I=
|
||||||
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
|
@ -103,6 +107,7 @@ github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEW
|
||||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||||
|
github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
|
||||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||||
github.com/google/uuid v1.0.0 h1:b4Gk+7WdP/d3HZH8EJsZpvV7EtDOgaZLtnaNGIu1adA=
|
github.com/google/uuid v1.0.0 h1:b4Gk+7WdP/d3HZH8EJsZpvV7EtDOgaZLtnaNGIu1adA=
|
||||||
|
@ -136,6 +141,7 @@ github.com/jackpal/gateway v1.0.6/go.mod h1:lTpwd4ACLXmpyiCTRtfiNyVnUmqT9RivzCDQ
|
||||||
github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus=
|
github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus=
|
||||||
github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc=
|
github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc=
|
||||||
github.com/jcmturner/gofork v1.0.0/go.mod h1:MK8+TM0La+2rjBD4jE12Kj1pCCxK7d2LK/UM3ncEo0o=
|
github.com/jcmturner/gofork v1.0.0/go.mod h1:MK8+TM0La+2rjBD4jE12Kj1pCCxK7d2LK/UM3ncEo0o=
|
||||||
|
github.com/jhump/protoreflect v1.6.0 h1:h5jfMVslIg6l29nsMs0D8Wj17RDVdNYti0vDN/PZZoE=
|
||||||
github.com/jhump/protoreflect v1.6.0/go.mod h1:eaTn3RZAmMBcV0fifFvlm6VHNz3wSkYyXYWUh7ymB74=
|
github.com/jhump/protoreflect v1.6.0/go.mod h1:eaTn3RZAmMBcV0fifFvlm6VHNz3wSkYyXYWUh7ymB74=
|
||||||
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||||
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||||
|
@ -149,8 +155,10 @@ github.com/klauspost/reedsolomon v1.9.3/go.mod h1:CwCi+NUr9pqSVktrkN+Ondf06rkhYZ
|
||||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||||
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
||||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||||
|
github.com/kr/pretty v0.2.0 h1:s5hAObm+yFO5uHYt5dYjxi2rXrsnmRpJx4OYvIWUaQs=
|
||||||
github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||||
|
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||||
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
|
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
|
||||||
github.com/mattn/go-colorable v0.1.6 h1:6Su7aK7lXmJ/U79bYtBjLNaha4Fs1Rg9plHpcH+vvnE=
|
github.com/mattn/go-colorable v0.1.6 h1:6Su7aK7lXmJ/U79bYtBjLNaha4Fs1Rg9plHpcH+vvnE=
|
||||||
|
@ -171,6 +179,8 @@ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lN
|
||||||
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||||
github.com/mr-tron/base58 v1.1.3 h1:v+sk57XuaCKGXpWtVBX8YJzO7hMGx4Aajh4TQbdEFdc=
|
github.com/mr-tron/base58 v1.1.3 h1:v+sk57XuaCKGXpWtVBX8YJzO7hMGx4Aajh4TQbdEFdc=
|
||||||
github.com/mr-tron/base58 v1.1.3/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc=
|
github.com/mr-tron/base58 v1.1.3/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc=
|
||||||
|
github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o=
|
||||||
|
github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc=
|
||||||
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||||
github.com/nbutton23/zxcvbn-go v0.0.0-20180912185939-ae427f1e4c1d h1:AREM5mwr4u1ORQBMvzfzBgpsctsbQikCVpvC+tX285E=
|
github.com/nbutton23/zxcvbn-go v0.0.0-20180912185939-ae427f1e4c1d h1:AREM5mwr4u1ORQBMvzfzBgpsctsbQikCVpvC+tX285E=
|
||||||
github.com/nbutton23/zxcvbn-go v0.0.0-20180912185939-ae427f1e4c1d/go.mod h1:o96djdrsSGy3AWPyBgZMAGfxZNfgntdJG+11KU4QvbU=
|
github.com/nbutton23/zxcvbn-go v0.0.0-20180912185939-ae427f1e4c1d/go.mod h1:o96djdrsSGy3AWPyBgZMAGfxZNfgntdJG+11KU4QvbU=
|
||||||
|
@ -321,6 +331,7 @@ golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3
|
||||||
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||||
golang.org/x/tools v0.0.0-20200221224223-e1da425f72fd/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
golang.org/x/tools v0.0.0-20200221224223-e1da425f72fd/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||||
|
@ -351,6 +362,7 @@ gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQ
|
||||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||||
gopkg.in/bsm/ratelimit.v1 v1.0.0-20160220154919-db14e161995a/go.mod h1:KF9sEfUPAXdG8Oev9e99iLGnl2uJMjc5B+4y3O7x610=
|
gopkg.in/bsm/ratelimit.v1 v1.0.0-20160220154919-db14e161995a/go.mod h1:KF9sEfUPAXdG8Oev9e99iLGnl2uJMjc5B+4y3O7x610=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
|
||||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
|
gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
|
||||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||||
|
|
14
main/main.go
14
main/main.go
|
@ -40,10 +40,6 @@ func main() {
|
||||||
defer log.StopOnPanic()
|
defer log.StopOnPanic()
|
||||||
defer Config.DB.Close()
|
defer Config.DB.Close()
|
||||||
|
|
||||||
if Config.StakingIP.IsZero() {
|
|
||||||
log.Warn("NAT traversal has failed. It will be able to connect to less nodes.")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Track if sybil control is enforced
|
// Track if sybil control is enforced
|
||||||
if !Config.EnableStaking && Config.EnableP2PTLS {
|
if !Config.EnableStaking && Config.EnableP2PTLS {
|
||||||
log.Warn("Staking is disabled. Sybil control is not enforced.")
|
log.Warn("Staking is disabled. Sybil control is not enforced.")
|
||||||
|
@ -68,12 +64,16 @@ func main() {
|
||||||
log.Debug("assertions are enabled. This may slow down execution")
|
log.Debug("assertions are enabled. This may slow down execution")
|
||||||
}
|
}
|
||||||
|
|
||||||
mapper := nat.NewDefaultMapper(log, Config.Nat, nat.TCP, "gecko")
|
mapper := nat.NewPortMapper(log, Config.Nat)
|
||||||
defer mapper.UnmapAllPorts()
|
defer mapper.UnmapAllPorts()
|
||||||
|
|
||||||
mapper.MapPort(Config.StakingIP.Port, Config.StakingIP.Port) // Open staking port
|
Config.StakingIP.Port = mapper.Map("TCP", Config.StakingLocalPort, "gecko-staking") // Open staking port
|
||||||
if Config.HTTPHost != "127.0.0.1" && Config.HTTPHost != "localhost" { // Open HTTP port iff HTTP server not listening on localhost
|
if Config.HTTPHost != "127.0.0.1" && Config.HTTPHost != "localhost" { // Open HTTP port iff HTTP server not listening on localhost
|
||||||
mapper.MapPort(Config.HTTPPort, Config.HTTPPort)
|
mapper.Map("TCP", Config.HTTPPort, "gecko-http")
|
||||||
|
}
|
||||||
|
|
||||||
|
if Config.StakingIP.IsZero() {
|
||||||
|
log.Warn("NAT traversal has failed. The node will be able to connect to less nodes.")
|
||||||
}
|
}
|
||||||
|
|
||||||
node := node.Node{}
|
node := node.Node{}
|
||||||
|
|
|
@ -284,12 +284,12 @@ func init() {
|
||||||
Config.DB = memdb.New()
|
Config.DB = memdb.New()
|
||||||
}
|
}
|
||||||
|
|
||||||
Config.Nat = nat.NewRouter()
|
Config.Nat = nat.GetRouter()
|
||||||
|
|
||||||
var ip net.IP
|
var ip net.IP
|
||||||
// If public IP is not specified, get it using shell command dig
|
// If public IP is not specified, get it using shell command dig
|
||||||
if *consensusIP == "" {
|
if *consensusIP == "" {
|
||||||
ip, err = Config.Nat.IP()
|
ip, err = Config.Nat.ExternalIP()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ip = net.IPv4zero // Couldn't get my IP...set to 0.0.0.0
|
ip = net.IPv4zero // Couldn't get my IP...set to 0.0.0.0
|
||||||
}
|
}
|
||||||
|
@ -306,6 +306,7 @@ func init() {
|
||||||
IP: ip,
|
IP: ip,
|
||||||
Port: uint16(*consensusPort),
|
Port: uint16(*consensusPort),
|
||||||
}
|
}
|
||||||
|
Config.StakingLocalPort = uint16(*consensusPort)
|
||||||
|
|
||||||
defaultBootstrapIPs, defaultBootstrapIDs := GetDefaultBootstraps(networkID, 5)
|
defaultBootstrapIPs, defaultBootstrapIDs := GetDefaultBootstraps(networkID, 5)
|
||||||
|
|
||||||
|
|
143
nat/mapper.go
143
nat/mapper.go
|
@ -1,143 +0,0 @@
|
||||||
// (c) 2019-2020, Ava Labs, Inc. All rights reserved.
|
|
||||||
// See the file LICENSE for licensing terms.
|
|
||||||
|
|
||||||
package nat
|
|
||||||
|
|
||||||
import (
|
|
||||||
"sync"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/ava-labs/gecko/utils/logging"
|
|
||||||
"github.com/ava-labs/gecko/utils/wrappers"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
defaultMappingTimeout = 30 * time.Minute
|
|
||||||
defaultMappingUpdateInterval = 3 * defaultMappingTimeout / 4
|
|
||||||
)
|
|
||||||
|
|
||||||
// Mapper maps port
|
|
||||||
type Mapper interface {
|
|
||||||
MapPort(newInternalPort, newExternalPort uint16) error
|
|
||||||
UnmapAllPorts() error
|
|
||||||
}
|
|
||||||
|
|
||||||
type mapper struct {
|
|
||||||
log logging.Logger
|
|
||||||
router Router
|
|
||||||
networkProtocol NetworkProtocol
|
|
||||||
mappingNames string
|
|
||||||
mappingTimeout time.Duration
|
|
||||||
mappingUpdateInterval time.Duration
|
|
||||||
|
|
||||||
closer chan struct{}
|
|
||||||
wg sync.WaitGroup
|
|
||||||
errLock sync.Mutex
|
|
||||||
errs wrappers.Errs
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewMapper returns a new mapper that can map ports on a router
|
|
||||||
func NewMapper(
|
|
||||||
log logging.Logger,
|
|
||||||
router Router,
|
|
||||||
networkProtocol NetworkProtocol,
|
|
||||||
mappingNames string,
|
|
||||||
mappingTimeout time.Duration,
|
|
||||||
mappingUpdateInterval time.Duration,
|
|
||||||
) Mapper {
|
|
||||||
return &mapper{
|
|
||||||
log: log,
|
|
||||||
router: router,
|
|
||||||
networkProtocol: networkProtocol,
|
|
||||||
mappingNames: mappingNames,
|
|
||||||
mappingTimeout: mappingTimeout,
|
|
||||||
mappingUpdateInterval: mappingUpdateInterval,
|
|
||||||
closer: make(chan struct{}),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewDefaultMapper returns a new mapper that can map ports on a router with
|
|
||||||
// default settings
|
|
||||||
func NewDefaultMapper(
|
|
||||||
log logging.Logger,
|
|
||||||
router Router,
|
|
||||||
networkProtocol NetworkProtocol,
|
|
||||||
mappingNames string,
|
|
||||||
) Mapper {
|
|
||||||
return NewMapper(
|
|
||||||
log,
|
|
||||||
router,
|
|
||||||
networkProtocol,
|
|
||||||
mappingNames,
|
|
||||||
defaultMappingTimeout, // uses the default value
|
|
||||||
defaultMappingUpdateInterval, // uses the default value
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// MapPort maps a local port to a port on the router until UnmapAllPorts is
|
|
||||||
// called.
|
|
||||||
func (m *mapper) MapPort(newInternalPort, newExternalPort uint16) error {
|
|
||||||
m.wg.Add(1)
|
|
||||||
go m.mapPort(newInternalPort, newExternalPort)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *mapper) mapPort(newInternalPort, newExternalPort uint16) {
|
|
||||||
// duration is set to 0 here so that the select case will execute
|
|
||||||
// immediately
|
|
||||||
updateTimer := time.NewTimer(0)
|
|
||||||
defer func() {
|
|
||||||
updateTimer.Stop()
|
|
||||||
|
|
||||||
m.errLock.Lock()
|
|
||||||
m.errs.Add(m.router.UnmapPort(
|
|
||||||
m.networkProtocol,
|
|
||||||
newInternalPort,
|
|
||||||
newExternalPort))
|
|
||||||
m.errLock.Unlock()
|
|
||||||
|
|
||||||
m.log.Debug("Unmapped external port %d to internal port %d",
|
|
||||||
newExternalPort,
|
|
||||||
newInternalPort)
|
|
||||||
|
|
||||||
m.wg.Done()
|
|
||||||
}()
|
|
||||||
|
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case <-updateTimer.C:
|
|
||||||
err := m.router.MapPort(
|
|
||||||
m.networkProtocol,
|
|
||||||
newInternalPort,
|
|
||||||
newExternalPort,
|
|
||||||
m.mappingNames,
|
|
||||||
m.mappingTimeout)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
m.errLock.Lock()
|
|
||||||
m.errs.Add(err)
|
|
||||||
m.errLock.Unlock()
|
|
||||||
|
|
||||||
m.log.Debug("Failed to add mapping from external port %d to internal port %d due to %s",
|
|
||||||
newExternalPort,
|
|
||||||
newInternalPort,
|
|
||||||
err)
|
|
||||||
} else {
|
|
||||||
m.log.Debug("Mapped external port %d to internal port %d",
|
|
||||||
newExternalPort,
|
|
||||||
newInternalPort)
|
|
||||||
}
|
|
||||||
|
|
||||||
// remap the port in m.mappingUpdateInterval
|
|
||||||
updateTimer.Reset(m.mappingUpdateInterval)
|
|
||||||
case _, _ = <-m.closer:
|
|
||||||
return // only return when all ports are unmapped
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *mapper) UnmapAllPorts() error {
|
|
||||||
close(m.closer)
|
|
||||||
m.wg.Wait()
|
|
||||||
return m.errs.Err
|
|
||||||
}
|
|
|
@ -0,0 +1,134 @@
|
||||||
|
// (c) 2019-2020, Ava Labs, Inc. All rights reserved.
|
||||||
|
// See the file LICENSE for licensing terms.
|
||||||
|
|
||||||
|
package nat
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/ava-labs/gecko/utils/logging"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
mapTimeout = 30 * time.Second
|
||||||
|
mapUpdateTimeout = mapTimeout / 2
|
||||||
|
maxRetries = 20
|
||||||
|
)
|
||||||
|
|
||||||
|
// Router describes the functionality that a network device must support to be
|
||||||
|
// able to open ports to an external IP.
|
||||||
|
type Router interface {
|
||||||
|
MapPort(protocol string, intPort, extPort uint16, desc string, duration time.Duration) error
|
||||||
|
UnmapPort(protocol string, intPort, extPort uint16) error
|
||||||
|
ExternalIP() (net.IP, error)
|
||||||
|
GetPortMappingEntry(extPort uint16, protocol string) (
|
||||||
|
InternalIP string,
|
||||||
|
InternalPort uint16,
|
||||||
|
Description string,
|
||||||
|
err error,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetRouter returns a router on the current network.
|
||||||
|
func GetRouter() Router {
|
||||||
|
if r := getUPnPRouter(); r != nil {
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
if r := getPMPRouter(); r != nil {
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
return NewNoRouter()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mapper attempts to open a set of ports on a router
|
||||||
|
type Mapper struct {
|
||||||
|
log logging.Logger
|
||||||
|
r Router
|
||||||
|
closer chan struct{}
|
||||||
|
wg sync.WaitGroup
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewPortMapper returns an initialized mapper
|
||||||
|
func NewPortMapper(log logging.Logger, r Router) Mapper {
|
||||||
|
return Mapper{
|
||||||
|
log: log,
|
||||||
|
r: r,
|
||||||
|
closer: make(chan struct{}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Map sets up port mapping using given protocol, internal and external ports
|
||||||
|
// and returns the final port mapped. It returns 0 if mapping failed after the
|
||||||
|
// maximun number of retries
|
||||||
|
func (dev *Mapper) Map(protocol string, intPort uint16, desc string) uint16 {
|
||||||
|
mappedPort := make(chan uint16)
|
||||||
|
|
||||||
|
go dev.keepPortMapping(mappedPort, protocol, intPort, desc)
|
||||||
|
|
||||||
|
return <-mappedPort
|
||||||
|
}
|
||||||
|
|
||||||
|
// keepPortMapping runs in the background to keep a port mapped. It renews the
|
||||||
|
// the port mapping in mapUpdateTimeout.
|
||||||
|
func (dev *Mapper) keepPortMapping(mappedPort chan<- uint16, protocol string,
|
||||||
|
intPort uint16, desc string) {
|
||||||
|
updateTimer := time.NewTimer(mapUpdateTimeout)
|
||||||
|
|
||||||
|
for i := 0; i <= maxRetries; i++ {
|
||||||
|
extPort := intPort + uint16(i)
|
||||||
|
if intaddr, intPort, desc, err := dev.r.GetPortMappingEntry(extPort, protocol); err == nil {
|
||||||
|
dev.log.Debug("Port %d is taken by %s:%d: %s, retry with the next port",
|
||||||
|
extPort, intaddr, intPort, desc)
|
||||||
|
} else if err := dev.r.MapPort(protocol, intPort, extPort, desc, mapTimeout); err != nil {
|
||||||
|
dev.log.Debug("Map port failed. Protocol %s Internal %d External %d. %s",
|
||||||
|
protocol, intPort, extPort, err)
|
||||||
|
} else {
|
||||||
|
dev.log.Info("Mapped Protocol %s Internal %d External %d.", protocol,
|
||||||
|
intPort, extPort)
|
||||||
|
|
||||||
|
dev.wg.Add(1)
|
||||||
|
|
||||||
|
mappedPort <- extPort
|
||||||
|
|
||||||
|
defer func(extPort uint16) {
|
||||||
|
updateTimer.Stop()
|
||||||
|
|
||||||
|
dev.log.Debug("Unmap protocol %s external port %d", protocol, extPort)
|
||||||
|
dev.r.UnmapPort(protocol, intPort, extPort)
|
||||||
|
|
||||||
|
dev.wg.Done()
|
||||||
|
}(extPort)
|
||||||
|
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-updateTimer.C:
|
||||||
|
if err := dev.r.MapPort(protocol, intPort, extPort, desc, mapTimeout); err != nil {
|
||||||
|
dev.log.Error("Renewing port mapping from external port %d to internal port %d failed with %s",
|
||||||
|
intPort, extPort, err)
|
||||||
|
} else {
|
||||||
|
dev.log.Info("Renewed port mapping from external port %d to internal port %d.",
|
||||||
|
intPort, extPort)
|
||||||
|
}
|
||||||
|
|
||||||
|
updateTimer.Reset(mapUpdateTimeout)
|
||||||
|
case _, _ = <-dev.closer:
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dev.log.Debug("Unable to map port %d~%d", intPort, intPort+maxRetries)
|
||||||
|
mappedPort <- 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmapAllPorts stops mapping all ports from this mapper and attempts to unmap
|
||||||
|
// them.
|
||||||
|
func (dev *Mapper) UnmapAllPorts() {
|
||||||
|
close(dev.closer)
|
||||||
|
dev.wg.Wait()
|
||||||
|
dev.log.Info("Unmapped all ports")
|
||||||
|
}
|
|
@ -4,25 +4,57 @@
|
||||||
package nat
|
package nat
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
const googleDNSServer = "8.8.8.8:80"
|
||||||
errNoRouter = errors.New("no nat enabled router was discovered")
|
|
||||||
)
|
|
||||||
|
|
||||||
type noRouter struct{}
|
type noRouter struct {
|
||||||
|
ip net.IP
|
||||||
func (noRouter) MapPort(_ NetworkProtocol, _, _ uint16, _ string, _ time.Duration) error {
|
|
||||||
return errNoRouter
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (noRouter) UnmapPort(_ NetworkProtocol, _, _ uint16) error {
|
func (noRouter) MapPort(_ string, intPort, extPort uint16, _ string, _ time.Duration) error {
|
||||||
return errNoRouter
|
if intPort != extPort {
|
||||||
|
return fmt.Errorf("cannot map port %d to %d", intPort, extPort)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (noRouter) IP() (net.IP, error) {
|
func (noRouter) UnmapPort(string, uint16, uint16) error {
|
||||||
return nil, errNoRouter
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r noRouter) ExternalIP() (net.IP, error) {
|
||||||
|
return r.ip, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (noRouter) GetPortMappingEntry(uint16, string) (string, uint16, string, error) {
|
||||||
|
return "", 0, "", nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getOutboundIP() (net.IP, error) {
|
||||||
|
conn, err := net.Dial("udp", googleDNSServer)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if udpAddr, ok := conn.LocalAddr().(*net.UDPAddr); ok {
|
||||||
|
return udpAddr.IP, conn.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
conn.Close()
|
||||||
|
return nil, fmt.Errorf("getting outbound IP failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewNoRouter returns a router that assumes the network is public
|
||||||
|
func NewNoRouter() Router {
|
||||||
|
ip, err := getOutboundIP()
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return &noRouter{
|
||||||
|
ip: ip,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
28
nat/pmp.go
28
nat/pmp.go
|
@ -4,11 +4,13 @@
|
||||||
package nat
|
package nat
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/jackpal/gateway"
|
"github.com/jackpal/gateway"
|
||||||
"github.com/jackpal/go-nat-pmp"
|
|
||||||
|
natpmp "github.com/jackpal/go-nat-pmp"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -17,12 +19,12 @@ var (
|
||||||
|
|
||||||
// natPMPClient adapts the NAT-PMP protocol implementation so it conforms to
|
// natPMPClient adapts the NAT-PMP protocol implementation so it conforms to
|
||||||
// the common interface.
|
// the common interface.
|
||||||
type pmpClient struct {
|
type pmpRouter struct {
|
||||||
client *natpmp.Client
|
client *natpmp.Client
|
||||||
}
|
}
|
||||||
|
|
||||||
func (pmp *pmpClient) MapPort(
|
func (pmp *pmpRouter) MapPort(
|
||||||
networkProtocol NetworkProtocol,
|
networkProtocol string,
|
||||||
newInternalPort uint16,
|
newInternalPort uint16,
|
||||||
newExternalPort uint16,
|
newExternalPort uint16,
|
||||||
mappingName string,
|
mappingName string,
|
||||||
|
@ -37,8 +39,8 @@ func (pmp *pmpClient) MapPort(
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (pmp *pmpClient) UnmapPort(
|
func (pmp *pmpRouter) UnmapPort(
|
||||||
networkProtocol NetworkProtocol,
|
networkProtocol string,
|
||||||
internalPort uint16,
|
internalPort uint16,
|
||||||
_ uint16) error {
|
_ uint16) error {
|
||||||
protocol := string(networkProtocol)
|
protocol := string(networkProtocol)
|
||||||
|
@ -48,7 +50,7 @@ func (pmp *pmpClient) UnmapPort(
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (pmp *pmpClient) IP() (net.IP, error) {
|
func (pmp *pmpRouter) ExternalIP() (net.IP, error) {
|
||||||
response, err := pmp.client.GetExternalAddress()
|
response, err := pmp.client.GetExternalAddress()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -56,14 +58,20 @@ func (pmp *pmpClient) IP() (net.IP, error) {
|
||||||
return response.ExternalIPAddress[:], nil
|
return response.ExternalIPAddress[:], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getPMPRouter() Router {
|
// go-nat-pmp does not support port mapping entry query
|
||||||
|
func (pmp *pmpRouter) GetPortMappingEntry(externalPort uint16, protocol string) (
|
||||||
|
string, uint16, string, error) {
|
||||||
|
return "", 0, "", fmt.Errorf("port mapping entry not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
func getPMPRouter() *pmpRouter {
|
||||||
gatewayIP, err := gateway.DiscoverGateway()
|
gatewayIP, err := gateway.DiscoverGateway()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
pmp := &pmpClient{natpmp.NewClientWithTimeout(gatewayIP, pmpClientTimeout)}
|
pmp := &pmpRouter{natpmp.NewClientWithTimeout(gatewayIP, pmpClientTimeout)}
|
||||||
if _, err := pmp.IP(); err != nil {
|
if _, err := pmp.ExternalIP(); err != nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,65 +0,0 @@
|
||||||
// (c) 2019-2020, Ava Labs, Inc. All rights reserved.
|
|
||||||
// See the file LICENSE for licensing terms.
|
|
||||||
|
|
||||||
// Package nat performs network address translation and provides helpers for
|
|
||||||
// routing ports.
|
|
||||||
package nat
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
// NetworkProtocol is a protocol that will be used through a port
|
|
||||||
type NetworkProtocol string
|
|
||||||
|
|
||||||
// Available protocol
|
|
||||||
const (
|
|
||||||
TCP NetworkProtocol = "TCP"
|
|
||||||
UDP NetworkProtocol = "UDP"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Router provides a standard NAT router functions. Specifically, allowing the
|
|
||||||
// fetching of public IPs and port forwarding to this computer.
|
|
||||||
type Router interface {
|
|
||||||
// mapPort creates a mapping between a port on the local computer to an
|
|
||||||
// external port on the router.
|
|
||||||
//
|
|
||||||
// The mappingName is something displayed on the router, so it is included
|
|
||||||
// for completeness.
|
|
||||||
MapPort(
|
|
||||||
networkProtocol NetworkProtocol,
|
|
||||||
newInternalPort uint16,
|
|
||||||
newExternalPort uint16,
|
|
||||||
mappingName string,
|
|
||||||
mappingDuration time.Duration) error
|
|
||||||
|
|
||||||
// UnmapPort clears a mapping that was previous made by a call to MapPort
|
|
||||||
UnmapPort(
|
|
||||||
networkProtocol NetworkProtocol,
|
|
||||||
internalPort uint16,
|
|
||||||
externalPort uint16) error
|
|
||||||
|
|
||||||
// Returns the routers IP address on the network the router considers
|
|
||||||
// external
|
|
||||||
IP() (net.IP, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewRouter returns a new router discovered on the local network
|
|
||||||
func NewRouter() Router {
|
|
||||||
routers := make(chan Router)
|
|
||||||
// Because getting a router can take a noticeable amount of time to error,
|
|
||||||
// we run these requests in parallel
|
|
||||||
go func() {
|
|
||||||
routers <- getUPnPRouter()
|
|
||||||
}()
|
|
||||||
go func() {
|
|
||||||
routers <- getPMPRouter()
|
|
||||||
}()
|
|
||||||
for i := 0; i < 2; i++ {
|
|
||||||
if router := <-routers; router != nil {
|
|
||||||
return router
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return noRouter{}
|
|
||||||
}
|
|
244
nat/upnp.go
244
nat/upnp.go
|
@ -4,7 +4,6 @@
|
||||||
package nat
|
package nat
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"time"
|
"time"
|
||||||
|
@ -15,11 +14,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
soapTimeout = time.Second
|
soapRequestTimeout = 3 * time.Second
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
errNoGateway = errors.New("Failed to connect to any avaliable gateways")
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// upnpClient is the interface used by goupnp for their client implementations
|
// upnpClient is the interface used by goupnp for their client implementations
|
||||||
|
@ -47,69 +42,30 @@ type upnpClient interface {
|
||||||
|
|
||||||
// returns if there is rsip available, nat enabled, or an unexpected error.
|
// returns if there is rsip available, nat enabled, or an unexpected error.
|
||||||
GetNATRSIPStatus() (newRSIPAvailable bool, natEnabled bool, err error)
|
GetNATRSIPStatus() (newRSIPAvailable bool, natEnabled bool, err error)
|
||||||
}
|
|
||||||
|
|
||||||
type upnpRouter struct {
|
// attempts to get port mapping information give a external port and protocol
|
||||||
root *goupnp.RootDevice
|
GetSpecificPortMappingEntry(
|
||||||
client upnpClient
|
NewRemoteHost string,
|
||||||
}
|
NewExternalPort uint16,
|
||||||
|
NewProtocol string,
|
||||||
func (n *upnpRouter) MapPort(
|
) (
|
||||||
networkProtocol NetworkProtocol,
|
NewInternalPort uint16,
|
||||||
newInternalPort uint16,
|
NewInternalClient string,
|
||||||
newExternalPort uint16,
|
NewEnabled bool,
|
||||||
mappingName string,
|
NewPortMappingDescription string,
|
||||||
mappingDuration time.Duration,
|
NewLeaseDuration uint32,
|
||||||
) error {
|
err error,
|
||||||
ip, err := n.localAddress()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
protocol := string(networkProtocol)
|
|
||||||
// goupnp uses seconds to denote their lifetime
|
|
||||||
lifetime := uint32(mappingDuration / time.Second)
|
|
||||||
|
|
||||||
// UnmapPort's error is intentionally dropped, because the mapping may not
|
|
||||||
// exist.
|
|
||||||
n.UnmapPort(networkProtocol, newInternalPort, newExternalPort)
|
|
||||||
|
|
||||||
return n.client.AddPortMapping(
|
|
||||||
"", // newRemoteHost isn't used to limit the mapping to a host
|
|
||||||
newExternalPort,
|
|
||||||
protocol,
|
|
||||||
newInternalPort,
|
|
||||||
ip.String(), // newInternalClient is the client traffic should be sent to
|
|
||||||
true, // newEnabled enables port mappings
|
|
||||||
mappingName,
|
|
||||||
lifetime,
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *upnpRouter) UnmapPort(networkProtocol NetworkProtocol, _, externalPort uint16) error {
|
type upnpRouter struct {
|
||||||
protocol := string(networkProtocol)
|
dev *goupnp.RootDevice
|
||||||
return n.client.DeletePortMapping(
|
client upnpClient
|
||||||
"", // newRemoteHost isn't used to limit the mapping to a host
|
|
||||||
externalPort,
|
|
||||||
protocol)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *upnpRouter) IP() (net.IP, error) {
|
func (r *upnpRouter) localIP() (net.IP, error) {
|
||||||
ipStr, err := n.client.GetExternalIPAddress()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
ip := net.ParseIP(ipStr)
|
|
||||||
if ip == nil {
|
|
||||||
return nil, fmt.Errorf("invalid IP %s", ipStr)
|
|
||||||
}
|
|
||||||
return ip, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *upnpRouter) localAddress() (net.IP, error) {
|
|
||||||
// attempt to get an address on the router
|
// attempt to get an address on the router
|
||||||
deviceAddr, err := net.ResolveUDPAddr("udp4", n.root.URLBase.Host)
|
deviceAddr, err := net.ResolveUDPAddr("udp", r.dev.URLBase.Host)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -120,7 +76,7 @@ func (n *upnpRouter) localAddress() (net.IP, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// attempt to find one of my ips that the router would know about
|
// attempt to find one of my IPs that matches router's record
|
||||||
for _, netInterface := range netInterfaces {
|
for _, netInterface := range netInterfaces {
|
||||||
addrs, err := netInterface.Addrs()
|
addrs, err := netInterface.Addrs()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -128,9 +84,6 @@ func (n *upnpRouter) localAddress() (net.IP, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, addr := range addrs {
|
for _, addr := range addrs {
|
||||||
// this is pretty janky, but it seems to be the best way to get the
|
|
||||||
// ip mask and properly check if the ip references the device we are
|
|
||||||
// connected to
|
|
||||||
ipNet, ok := addr.(*net.IPNet)
|
ipNet, ok := addr.(*net.IPNet)
|
||||||
if !ok {
|
if !ok {
|
||||||
continue
|
continue
|
||||||
|
@ -144,110 +97,119 @@ func (n *upnpRouter) localAddress() (net.IP, error) {
|
||||||
return nil, fmt.Errorf("couldn't find the local address in the same network as %s", deviceIP)
|
return nil, fmt.Errorf("couldn't find the local address in the same network as %s", deviceIP)
|
||||||
}
|
}
|
||||||
|
|
||||||
// getUPnPRouter searches for all Gateway Devices that have avaliable
|
func (r *upnpRouter) ExternalIP() (net.IP, error) {
|
||||||
// connections in the goupnp library and returns the first connection it can
|
str, err := r.client.GetExternalIPAddress()
|
||||||
// find.
|
if err != nil {
|
||||||
func getUPnPRouter() Router {
|
return nil, err
|
||||||
routers := make(chan *upnpRouter)
|
|
||||||
// Because DiscoverDevices takes a noticeable amount of time to error, we
|
|
||||||
// run these requests in parallel
|
|
||||||
go func() {
|
|
||||||
routers <- connectToGateway(internetgateway1.URN_WANConnectionDevice_1, gateway1)
|
|
||||||
}()
|
|
||||||
go func() {
|
|
||||||
routers <- connectToGateway(internetgateway2.URN_WANConnectionDevice_2, gateway2)
|
|
||||||
}()
|
|
||||||
for i := 0; i < 2; i++ {
|
|
||||||
if router := <-routers; router != nil {
|
|
||||||
return router
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ip := net.ParseIP(str)
|
||||||
|
if ip == nil {
|
||||||
|
return nil, fmt.Errorf("invalid IP %s", str)
|
||||||
}
|
}
|
||||||
return nil
|
return ip, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func gateway1(client goupnp.ServiceClient) upnpClient {
|
func (r *upnpRouter) MapPort(protocol string, intPort, extPort uint16,
|
||||||
|
desc string, duration time.Duration) error {
|
||||||
|
ip, err := r.localIP()
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
lifetime := uint32(duration / time.Second)
|
||||||
|
|
||||||
|
return r.client.AddPortMapping("", extPort, protocol, intPort,
|
||||||
|
ip.String(), true, desc, lifetime)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *upnpRouter) UnmapPort(protocol string, _, extPort uint16) error {
|
||||||
|
return r.client.DeletePortMapping("", extPort, protocol)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *upnpRouter) GetPortMappingEntry(extPort uint16, protocol string) (string, uint16, string, error) {
|
||||||
|
intPort, intAddr, _, desc, _, err := r.client.GetSpecificPortMappingEntry("", extPort, protocol)
|
||||||
|
return intAddr, intPort, desc, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// create UPnP SOAP service client with URN
|
||||||
|
func getUPnPClient(client goupnp.ServiceClient) upnpClient {
|
||||||
switch client.Service.ServiceType {
|
switch client.Service.ServiceType {
|
||||||
case internetgateway1.URN_WANIPConnection_1:
|
case internetgateway1.URN_WANIPConnection_1:
|
||||||
return &internetgateway1.WANIPConnection1{ServiceClient: client}
|
return &internetgateway1.WANIPConnection1{ServiceClient: client}
|
||||||
case internetgateway1.URN_WANPPPConnection_1:
|
case internetgateway1.URN_WANPPPConnection_1:
|
||||||
return &internetgateway1.WANPPPConnection1{ServiceClient: client}
|
return &internetgateway1.WANPPPConnection1{ServiceClient: client}
|
||||||
default:
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func gateway2(client goupnp.ServiceClient) upnpClient {
|
|
||||||
switch client.Service.ServiceType {
|
|
||||||
case internetgateway2.URN_WANIPConnection_1:
|
|
||||||
return &internetgateway2.WANIPConnection1{ServiceClient: client}
|
|
||||||
case internetgateway2.URN_WANIPConnection_2:
|
case internetgateway2.URN_WANIPConnection_2:
|
||||||
return &internetgateway2.WANIPConnection2{ServiceClient: client}
|
return &internetgateway2.WANIPConnection2{ServiceClient: client}
|
||||||
case internetgateway2.URN_WANPPPConnection_1:
|
|
||||||
return &internetgateway2.WANPPPConnection1{ServiceClient: client}
|
|
||||||
default:
|
default:
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func connectToGateway(deviceType string, toClient func(goupnp.ServiceClient) upnpClient) *upnpRouter {
|
// discover() tries to find gateway device
|
||||||
devs, err := goupnp.DiscoverDevices(deviceType)
|
func discover(target string) *upnpRouter {
|
||||||
|
devs, err := goupnp.DiscoverDevices(target)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
// we are iterating over all the network devices, acting a possible roots
|
|
||||||
for i := range devs {
|
router := make(chan *upnpRouter)
|
||||||
dev := &devs[i]
|
for i := 0; i < len(devs); i++ {
|
||||||
if dev.Root == nil {
|
if devs[i].Root == nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
go func(dev *goupnp.MaybeRootDevice) {
|
||||||
// the root device may be a router, so attempt to connect to that
|
var r *upnpRouter = nil
|
||||||
rootDevice := &dev.Root.Device
|
dev.Root.Device.VisitServices(func(service *goupnp.Service) {
|
||||||
if upnp := getRouter(dev, rootDevice, toClient); upnp != nil {
|
c := goupnp.ServiceClient{
|
||||||
return upnp
|
SOAPClient: service.NewSOAPClient(),
|
||||||
}
|
RootDevice: dev.Root,
|
||||||
|
Location: dev.Location,
|
||||||
// attempt to connect to any sub devices
|
|
||||||
devices := rootDevice.Devices
|
|
||||||
for i := range devices {
|
|
||||||
if upnp := getRouter(dev, &devices[i], toClient); upnp != nil {
|
|
||||||
return upnp
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func getRouter(rootDevice *goupnp.MaybeRootDevice, device *goupnp.Device, toClient func(goupnp.ServiceClient) upnpClient) *upnpRouter {
|
|
||||||
for i := range device.Services {
|
|
||||||
service := &device.Services[i]
|
|
||||||
|
|
||||||
soapClient := service.NewSOAPClient()
|
|
||||||
// make sure the client times out if needed
|
|
||||||
soapClient.HTTPClient.Timeout = soapTimeout
|
|
||||||
|
|
||||||
// attempt to create a client connection
|
|
||||||
serviceClient := goupnp.ServiceClient{
|
|
||||||
SOAPClient: soapClient,
|
|
||||||
RootDevice: rootDevice.Root,
|
|
||||||
Location: rootDevice.Location,
|
|
||||||
Service: service,
|
Service: service,
|
||||||
}
|
}
|
||||||
client := toClient(serviceClient)
|
c.SOAPClient.HTTPClient.Timeout = soapRequestTimeout
|
||||||
|
client := getUPnPClient(c)
|
||||||
if client == nil {
|
if client == nil {
|
||||||
continue
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// check whether port mapping is enabled
|
|
||||||
if _, nat, err := client.GetNATRSIPStatus(); err != nil || !nat {
|
if _, nat, err := client.GetNATRSIPStatus(); err != nil || !nat {
|
||||||
continue
|
return
|
||||||
|
}
|
||||||
|
r = &upnpRouter{dev.Root, client}
|
||||||
|
})
|
||||||
|
router <- r
|
||||||
|
}(&devs[i])
|
||||||
}
|
}
|
||||||
|
|
||||||
// we found a router!
|
for i := 0; i < len(devs); i++ {
|
||||||
return &upnpRouter{
|
if r := <-router; r != nil {
|
||||||
root: rootDevice.Root,
|
return r
|
||||||
client: client,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// getUPnPRouter searches for internet gateway using both Device Control Protocol
|
||||||
|
// and returns the first one it can find. It returns nil if no UPnP gateway is found
|
||||||
|
func getUPnPRouter() *upnpRouter {
|
||||||
|
targets := []string{
|
||||||
|
internetgateway1.URN_WANConnectionDevice_1,
|
||||||
|
internetgateway2.URN_WANConnectionDevice_2,
|
||||||
|
}
|
||||||
|
|
||||||
|
routers := make(chan *upnpRouter)
|
||||||
|
|
||||||
|
for _, urn := range targets {
|
||||||
|
go func(urn string) {
|
||||||
|
routers <- discover(urn)
|
||||||
|
}(urn)
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < len(targets); i++ {
|
||||||
|
if r := <-routers; r != nil {
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,6 +34,7 @@ type Config struct {
|
||||||
|
|
||||||
// Staking configuration
|
// Staking configuration
|
||||||
StakingIP utils.IPDesc
|
StakingIP utils.IPDesc
|
||||||
|
StakingLocalPort uint16
|
||||||
EnableP2PTLS bool
|
EnableP2PTLS bool
|
||||||
EnableStaking bool
|
EnableStaking bool
|
||||||
StakingKeyFile string
|
StakingKeyFile string
|
||||||
|
|
|
@ -113,7 +113,7 @@ type Node struct {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
func (n *Node) initNetworking() error {
|
func (n *Node) initNetworking() error {
|
||||||
listener, err := net.Listen(TCP, n.Config.StakingIP.PortString())
|
listener, err := net.Listen(TCP, fmt.Sprintf(":%d", n.Config.StakingLocalPort))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue