diff --git a/.vscode/dict.txt b/.vscode/dict.txt index c63ce2c6..b8a44836 100644 --- a/.vscode/dict.txt +++ b/.vscode/dict.txt @@ -3,6 +3,7 @@ Bano Baudet BFT's Bitfield +bitmask cerr chainedhotstuff checkf @@ -10,6 +11,7 @@ Chursin clientpb cmdqueue Cmds +cmpopts CODECOV covermode coverpkg @@ -17,6 +19,7 @@ coverprofile cpuprofile Debugf durationpb +dylib eddsa emptypb Erevik @@ -28,6 +31,7 @@ Feng ferr fgprof fgprofprofile +gcflags gocyclo golangci golint @@ -36,6 +40,7 @@ gorums gpool grpc Gueta +handelpb Hein hostnames HOTSTUFF @@ -44,6 +49,7 @@ hotstuffpb iagotest ICDCS iface +Iinternal Infof Jalalzai Jehl @@ -51,6 +57,7 @@ Jianyu keygen kilic latencygen +ldflags leaderrotation Malkhi Mathieu @@ -72,6 +79,7 @@ propsed proto protobuf protoc +protos protostream ptypes QC's diff --git a/.vscode/settings.json b/.vscode/settings.json index 49a998a6..13e27018 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -16,5 +16,17 @@ "go.testFlags": [ "-count=1" ], - "cSpell.enabled": true + "cSpell.enabled": true, + "cSpell.ignorePaths": [ + "package-lock.json", + "node_modules", + "vscode-extension", + ".git/{info,lfs,logs,refs,objects}/**", + ".git/{index,*refs,*HEAD}", + ".vscode", + ".vscode-insiders", + "go.mod", + "go.sum", + "**/**/*.pb.go" + ] } diff --git a/crypto/bls12/bls12.go b/crypto/bls12/bls12.go index ffcc5793..a413a1e4 100644 --- a/crypto/bls12/bls12.go +++ b/crypto/bls12/bls12.go @@ -320,7 +320,7 @@ func (bls *bls12Base) fastAggregateVerify(publicKeys []*PublicKey, message []byt return bls.coreVerify(&PublicKey{p: &aggregate}, message, signature, domain) } -// Sign creates a cryptographic signature of the given messsage. +// Sign creates a cryptographic signature of the given message. func (bls *bls12Base) Sign(message []byte) (signature hotstuff.QuorumSignature, err error) { p, err := bls.coreSign(message, domain) if err != nil { diff --git a/docs/experimentation.md b/docs/experimentation.md index 6ea6c5df..da7abba5 100644 --- a/docs/experimentation.md +++ b/docs/experimentation.md @@ -235,7 +235,7 @@ these additional flags are used: - `--worker` runs a worker locally, in addition to the remote hosts specified. Use this if you want the local machine to participate in the experiment. -Additionally, it is possible to specify an *internal address* for each host. +Additionally, it is possible to specify an _internal address_ for each host. The internal address is used by replicas instead of the address used by the controller. This is useful if the controller is connecting to the remote hosts using a global address, whereas the hosts can communicate using local addresses. @@ -243,11 +243,11 @@ The internal address is configured through the configuration file (loaded by the ```toml [[hosts-config]] -name = "hotstuff_worker_1" +name = "hotstuff-worker-1" internal-address = "192.168.10.2" [[hosts-config]] -name = "hotstuff_worker_1" +name = "hotstuff-worker-1" internal-address = "192.168.10.3" ``` @@ -262,21 +262,21 @@ The following shows a configuration file that customizes the client and replica clients = 2 replicas = 8 -hosts = [ - "hotstuff_worker_1", - "hotstuff_worker_2", - "hotstuff_worker_3", - "hotstuff_worker_4", +hosts = [ + "hotstuff-worker-1", + "hotstuff-worker-2", + "hotstuff-worker-3", + "hotstuff-worker-4", ] # specific assignments for some hosts [[hosts-config]] -name = "hotstuff_worker_1" +name = "hotstuff-worker-1" clients = 2 replicas = 0 ``` -In particular, in this example the host named `hotstuff_worker_1` is configured to run both clients and no replicas. +In particular, in this example the host named `hotstuff-worker-1` is configured to run both clients and no replicas. The remaining replicas are divided among the remaining hosts. If all hosts are manually configured, the total number of clients and replicas configured must equal the requested number of clients and replicas. diff --git a/go.mod b/go.mod index 71eda768..6f169849 100644 --- a/go.mod +++ b/go.mod @@ -6,6 +6,7 @@ require ( github.com/felixge/fgprof v0.9.4 github.com/golang/mock v1.6.0 github.com/golang/protobuf v1.5.4 + github.com/google/go-cmp v0.6.0 github.com/kilic/bls12-381 v0.1.1-0.20210208205449-6045b0235e36 github.com/mattn/go-isatty v0.0.20 github.com/mitchellh/go-homedir v1.1.0 @@ -46,7 +47,6 @@ require ( github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect github.com/gonuts/binary v0.2.0 // indirect - github.com/google/go-cmp v0.6.0 // indirect github.com/google/pprof v0.0.0-20240227163752-401108e1b7e7 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect diff --git a/internal/proto/hotstuffpb/convert.go b/internal/proto/hotstuffpb/convert.go index 71c3292e..2d55b794 100644 --- a/internal/proto/hotstuffpb/convert.go +++ b/internal/proto/hotstuffpb/convert.go @@ -162,7 +162,7 @@ func TimeoutMsgFromProto(m *TimeoutMsg) hotstuff.TimeoutMsg { SyncInfo: SyncInfoFromProto(m.GetSyncInfo()), ViewSignature: QuorumSignatureFromProto(m.GetViewSig()), } - if m.GetViewSig() != nil { + if m.GetMsgSig() != nil { timeoutMsg.MsgSignature = QuorumSignatureFromProto(m.GetMsgSig()) } return timeoutMsg diff --git a/internal/proto/hotstuffpb/convert_test.go b/internal/proto/hotstuffpb/convert_test.go index 8540d6a3..1768b5b8 100644 --- a/internal/proto/hotstuffpb/convert_test.go +++ b/internal/proto/hotstuffpb/convert_test.go @@ -4,6 +4,8 @@ import ( "bytes" "testing" + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" "github.com/relab/hotstuff" "github.com/relab/hotstuff/modules" @@ -95,3 +97,27 @@ func TestConvertTimeoutCertBLS12(t *testing.T) { t.Fatal("Failed to verify timeout cert") } } + +func TestTimeoutMsgFromProto_Issue129(t *testing.T) { + sig := &QuorumSignature{Sig: &QuorumSignature_ECDSASigs{ECDSASigs: &ECDSAMultiSignature{Sigs: []*ECDSASignature{}}}} + sync := &SyncInfo{QC: &QuorumCert{Sig: sig, Hash: []byte{1, 2, 3, 4}}} + + tests := []struct { + name string + msg *TimeoutMsg + want hotstuff.TimeoutMsg + }{ + {name: "only-view", msg: &TimeoutMsg{View: 1}, want: hotstuff.TimeoutMsg{View: 1}}, + {name: "only-sync-info", msg: &TimeoutMsg{SyncInfo: sync}, want: hotstuff.TimeoutMsg{SyncInfo: SyncInfoFromProto(sync)}}, + {name: "only-msg-signature", msg: &TimeoutMsg{MsgSig: sig}, want: hotstuff.TimeoutMsg{MsgSignature: QuorumSignatureFromProto(sig)}}, + {name: "only-view-signature", msg: &TimeoutMsg{ViewSig: sig}, want: hotstuff.TimeoutMsg{ViewSignature: QuorumSignatureFromProto(sig)}}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := TimeoutMsgFromProto(tt.msg) + if diff := cmp.Diff(tt.want, got, cmpopts.IgnoreUnexported(hotstuff.SyncInfo{})); diff != "" { + t.Errorf("TimeoutMsgFromProto() mismatch (-want +got):\n%s", diff) + } + }) + } +} diff --git a/scripts/deploy_test.sh b/scripts/deploy_test.sh index 91f00a6c..2e6b4490 100644 --- a/scripts/deploy_test.sh +++ b/scripts/deploy_test.sh @@ -1,6 +1,6 @@ #!/bin/bash -join () { +join() { local IFS="$1" shift echo "$*" @@ -10,23 +10,22 @@ num_hosts=4 declare -A hosts -for ((i=1; i<=num_hosts; i++)); do - hosts[$i]="hotstuff_worker_$i" +for ((i = 1; i <= num_hosts; i++)); do + hosts[$i]="hotstuff-worker-$i" done - if [ ! -f "./id" ]; then ssh-keygen -t ed25519 -C "hotstuff-test" -f "./id" -N "" fi compose_args="--project-name=hotstuff" -docker-compose $compose_args up -d --build --scale worker=4 +docker compose $compose_args up -d --build --scale worker=4 -docker-compose $compose_args exec -T controller /bin/sh -c "ssh-keyscan -H $(join ' ' "${hosts[@]}") >> ~/.ssh/known_hosts" &>/dev/null -docker-compose $compose_args exec -T controller /bin/sh -c "hotstuff run --hosts '$(join ',' "${hosts[@]}")' --config ./example_config.toml --log-level info" +docker compose $compose_args exec -T controller /bin/sh -c "ssh-keyscan -H $(join ' ' "${hosts[@]}") >> ~/.ssh/known_hosts" &>/dev/null +docker compose $compose_args exec -T controller /bin/sh -c "hotstuff run --hosts '$(join ',' "${hosts[@]}")' --config ./example_config.toml --log-level info" exit_code="$?" -docker-compose $compose_args down +docker compose $compose_args down exit $exit_code diff --git a/scripts/docker-compose.yml b/scripts/docker-compose.yml index 1d7ca4fa..ec32b11c 100644 --- a/scripts/docker-compose.yml +++ b/scripts/docker-compose.yml @@ -1,5 +1,3 @@ -version: '3.8' - services: worker: build: diff --git a/scripts/example_config.toml b/scripts/example_config.toml index 6f63de3f..d75ce971 100644 --- a/scripts/example_config.toml +++ b/scripts/example_config.toml @@ -1,15 +1,15 @@ clients = 2 replicas = 8 -hosts = [ - "hotstuff_worker_1", - "hotstuff_worker_2", - "hotstuff_worker_3", - "hotstuff_worker_4", +hosts = [ + "hotstuff-worker-1", + "hotstuff-worker-2", + "hotstuff-worker-3", + "hotstuff-worker-4", ] -# specific assingments for some hosts +# specific assignments for some hosts [[hosts-config]] -name = "hotstuff_worker_1" +name = "hotstuff-worker-1" clients = 2 replicas = 0 diff --git a/scripts/single_worker.sh b/scripts/single_worker.sh index 73c5036c..e7ecf185 100644 --- a/scripts/single_worker.sh +++ b/scripts/single_worker.sh @@ -1,20 +1,20 @@ #!/bin/bash -image="hotstuff_worker" +image="hotstuff-worker" if [ ! -f "./id" ]; then ssh-keygen -t ed25519 -C "hotstuff-test" -f "./id" -N "" fi # ensure that the image is built -docker images | grep "$image" &>/dev/null \ - || docker build -t "$image" -f "./Dockerfile.worker" ".." +docker images | grep "$image" &>/dev/null || + docker build -t "$image" -f "./Dockerfile.worker" ".." container="$(docker run --rm -d -p 2020:22 -p 4000:4000 "$image")" sleep 1s -ssh-keyscan -p 2020 127.0.0.1 localhost > known_hosts +ssh-keyscan -p 2020 127.0.0.1 localhost >known_hosts docker logs --follow "$container" docker rm -f "$container" &>/dev/null diff --git a/scripts/ssh_config b/scripts/ssh_config index a78aba93..a1b57d62 100644 --- a/scripts/ssh_config +++ b/scripts/ssh_config @@ -1,5 +1,5 @@ # ssh_config used with the controller container -Host hotstuff_worker_* +Host hotstuff-worker-* User root IdentityFile ~/.ssh/id