Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for VRF implementation with libsodium #297

Merged
merged 4 commits into from
Sep 3, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions DOCKER/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
FROM golang:1.15-alpine as builder
RUN apk update && \
apk upgrade && \
apk add --no-cache git make gcc libc-dev build-base curl jq bash file gmp-dev clang
apk add --no-cache git make gcc libc-dev build-base curl jq bash file gmp-dev clang libtool autoconf automake
COPY / /ostracon
WORKDIR /ostracon
RUN make build-linux
Expand All @@ -25,7 +25,7 @@ ENV OCHOME /ostracon
# could execute bash commands.
RUN apk update && \
apk upgrade && \
apk add --no-cache git make gcc libc-dev build-base curl jq bash file gmp-dev clang && \
apk add --no-cache git make gcc libc-dev build-base curl jq bash file gmp-dev clang libtool autoconf automake && \
addgroup ostracon && \
adduser -S -G ostracon ostracon -h "$OCHOME"

Expand Down
15 changes: 9 additions & 6 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@ SRCPATH=$(shell pwd)
OUTPUT?=build/ostracon

INCLUDE = -I=${GOPATH}/src/github.com/line/ostracon -I=${GOPATH}/src -I=${GOPATH}/src/github.com/gogo/protobuf/protobuf
BUILD_TAGS?=ostracon
BUILD_TAGS ?= ostracon
VERSION := $(shell git describe --always)
LIBSODIUM_TARGET=
ifeq ($(LIBSODIUM), 1)
LIBSODIUM_TARGET=libsodium
BUILD_TAGS += libsodium
LIBSODIUM_TARGET = libsodium
else
BUILD_TAGS += r2ishiguro
LIBSODIUM_TARGET =
endif
LD_FLAGS = -X github.com/line/ostracon/version.Version=$(VERSION)
BUILD_FLAGS = -mod=readonly -ldflags "$(LD_FLAGS)"
Expand Down Expand Up @@ -150,16 +152,17 @@ LIBSODIUM_ROOT = $(VRF_ROOT)/libsodium
LIBSODIUM_OS = $(VRF_ROOT)/sodium/$(TARGET_OS)_$(TARGET_ARCH)

libsodium:
rm -rf $(LIBSODIUM_ROOT)
mkdir $(LIBSODIUM_ROOT)
git submodule update --init --recursive
@if [ ! -f $(LIBSODIUM_OS)/lib/libsodium.a ]; then \
rm -rf $(LIBSODIUM_ROOT) && \
mkdir $(LIBSODIUM_ROOT) && \
git submodule update --init --recursive && \
cd $(LIBSODIUM_ROOT) && \
./autogen.sh && \
./configure --disable-shared --prefix="$(LIBSODIUM_OS)" && \
$(MAKE) && \
$(MAKE) install; \
fi
.PHONY: libsodium

########################################
### Distribution
Expand Down
14 changes: 7 additions & 7 deletions crypto/vrf/internal/vrf/vrf.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// +build libsodium

// This vrf package makes the VRF API in Algorand's libsodium C library available to golang.
// Package vrf makes the VRF API in Algorand's libsodium C library available to golang.
package vrf

/*
Expand Down Expand Up @@ -39,7 +39,7 @@ func init() {
}
}

// Generate an Ed25519 key pair for use with VRF.
// KeyPair generates an Ed25519 key pair for use with VRF.
func KeyPair() (*[PUBLICKEYBYTES]byte, *[SECRETKEYBYTES]byte) {
publicKey := [PUBLICKEYBYTES]byte{}
privateKey := [SECRETKEYBYTES]byte{}
Expand All @@ -49,7 +49,7 @@ func KeyPair() (*[PUBLICKEYBYTES]byte, *[SECRETKEYBYTES]byte) {
return &publicKey, &privateKey
}

// Generate an Ed25519 key pair for use with VRF. Parameter `seed` means the cofactor in Curve25519 and EdDSA.
// KeyPairFromSeed Generates an Ed25519 key pair for use with VRF. Parameter `seed` means the cofactor in Curve25519 and EdDSA.
func KeyPairFromSeed(seed *[SEEDBYTES]byte) (*[PUBLICKEYBYTES]byte, *[SECRETKEYBYTES]byte) {
publicKey := [PUBLICKEYBYTES]byte{}
privateKey := [SECRETKEYBYTES]byte{}
Expand All @@ -60,13 +60,13 @@ func KeyPairFromSeed(seed *[SEEDBYTES]byte) (*[PUBLICKEYBYTES]byte, *[SECRETKEYB
return &publicKey, &privateKey
}

// Verifies that the specified public key is valid.
// IsValidKey verifies that the specified public key is valid.
func IsValidKey(publicKey *[PUBLICKEYBYTES]byte) bool {
publicKeyPtr := (*C.uchar)(&publicKey[0])
return C.crypto_vrf_is_valid_key(publicKeyPtr) != 0
}

// Construct a VRF proof from given secret key and message.
// Prove constructs a VRF proof from given secret key and message.
func Prove(privateKey *[SECRETKEYBYTES]byte, message []byte) (*[PROOFBYTES]byte, error) {
proof := [PROOFBYTES]byte{}
proofPtr := (*C.uchar)(&proof[0])
Expand All @@ -79,7 +79,7 @@ func Prove(privateKey *[SECRETKEYBYTES]byte, message []byte) (*[PROOFBYTES]byte,
return &proof, nil
}

// Verifies that proof was legitimately generated by private key for the given public key, and stores the
// Verify verifies that proof was legitimately generated by private key for the given public key, and stores the
// VRF hash in output. Note that VRF "verify()" means the process of generating output from public key,
// proof, and message.
// https://tools.ietf.org/html/draft-irtf-cfrg-vrf-04#section-5.3
Expand All @@ -100,7 +100,7 @@ func Verify(publicKey *[PUBLICKEYBYTES]byte, proof *[PROOFBYTES]byte, message []
return &output, nil
}

// Calculate the output (hash value) from the specified proof.
// ProofToHash calculates the output (hash value) from the specified proof.
// In essence, this function returns a valid value if given proof is any point on the finite field. Otherwise,
// this will return an error.
func ProofToHash(proof *[PROOFBYTES]byte) (*[OUTPUTBYTES]byte, error) {
Expand Down
7 changes: 4 additions & 3 deletions evidence/pool.go
Original file line number Diff line number Diff line change
Expand Up @@ -270,14 +270,15 @@ func (evpool *Pool) fastCheck(ev types.Evidence) bool {
evpool.logger.Error("Failed to load light client attack evidence", "err", err, "key(height/hash)", key)
return false
}
var trustedPb tmproto.LightClientAttackEvidence
err = trustedPb.Unmarshal(evBytes)
var trustedPbEv tmproto.Evidence
err = trustedPbEv.Unmarshal(evBytes)
trustedPb := trustedPbEv.GetLightClientAttackEvidence()
if err != nil {
evpool.logger.Error("Failed to convert light client attack evidence from bytes",
"err", err, "key(height/hash)", key)
return false
}
trustedEv, err := types.LightClientAttackEvidenceFromProto(&trustedPb)
trustedEv, err := types.LightClientAttackEvidenceFromProto(trustedPb)
if err != nil {
evpool.logger.Error("Failed to convert light client attack evidence from protobuf",
"err", err, "key(height/hash)", key)
Expand Down
8 changes: 1 addition & 7 deletions evidence/pool_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,7 @@ func TestCheckEvidenceWithLightClientAttack(t *testing.T) {
ValidatorSet: conflictingVals,
VoterSet: conflictingVoters,
},
CommonHeight: 10,
CommonHeight: height,
TotalVotingPower: int64(nValidators) * validatorPower,
ByzantineValidators: conflictingVals.Validators,
Timestamp: defaultEvidenceTime,
Expand Down Expand Up @@ -326,12 +326,6 @@ func TestCheckEvidenceWithLightClientAttack(t *testing.T) {

err = pool.CheckEvidence(types.EvidenceList{ev})
assert.NoError(t, err)

// take away the last signature -> there are less validators then what we have detected,
// hence this should fail
commit.Signatures = append(commit.Signatures[:nValidators-1], types.NewCommitSigAbsent())
err = pool.CheckEvidence(types.EvidenceList{ev})
assert.Error(t, err)
}

// Tests that restarting the evidence pool after a potential failure will recover the
Expand Down
14 changes: 8 additions & 6 deletions evidence/verify_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,11 @@ import (
)

func TestVerifyLightClientAttack_Lunatic(t *testing.T) {

commonVals, commonVoters, commonPrivVals := types.RandVoterSet(2, 10)
// use the correct Proof to bypass the checks in libsodium
var proof []byte
proof, err := commonPrivVals[0].GenerateVRFProof([]byte{})

newVal, newPrivVal := types.RandValidatorForPrivKey(types.PrivKeyEd25519, false, 9)

Expand All @@ -39,11 +43,13 @@ func TestVerifyLightClientAttack_Lunatic(t *testing.T) {

commonHeader := makeHeaderRandom(4)
commonHeader.Time = defaultEvidenceTime
commonHeader.Proof = proof
trustedHeader := makeHeaderRandom(10)

conflictingHeader := makeHeaderRandom(10)
conflictingHeader.Time = defaultEvidenceTime.Add(1 * time.Hour)
conflictingHeader.VotersHash = conflictingVoterSet.Hash()
conflictingHeader.Proof = proof

// we are simulating a lunatic light client attack
blockID := makeBlockID(conflictingHeader.Hash(), 1000, []byte("partshash"))
Expand All @@ -69,6 +75,8 @@ func TestVerifyLightClientAttack_Lunatic(t *testing.T) {
Header: commonHeader,
Commit: &types.Commit{},
}
commonSignedHeader.Proof = proof

trustedBlockID := makeBlockID(trustedHeader.Hash(), 1000, []byte("partshash"))
_, voters, privVals := types.RandVoterSet(3, 8)
trustedVoteSet := types.NewVoteSet(evidenceChainID, 10, 1, tmproto.SignedMsgType(2), voters)
Expand Down Expand Up @@ -153,12 +161,6 @@ func TestVerifyLightClientAttack_Lunatic(t *testing.T) {
err = pool.CheckEvidence(evList)
assert.Error(t, err)
ev.ByzantineValidators = commonVals.Validators // restore evidence

// If evidence is submitted with an altered timestamp it should return an error
ev.Timestamp = defaultEvidenceTime.Add(1 * time.Minute)
err = pool.CheckEvidence(evList)
assert.Error(t, err)

}

func TestVerifyLightClientAttack_Equivocation(t *testing.T) {
Expand Down
2 changes: 1 addition & 1 deletion networks/local/localnode/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ FROM golang:1.15-alpine

RUN apk update && \
apk upgrade && \
apk add --no-cache git make gcc libc-dev build-base curl jq bash file gmp-dev clang
apk add --no-cache git make gcc libc-dev build-base curl jq bash file gmp-dev clang libtool autoconf automake

VOLUME [ "/ostracon" ]
WORKDIR /ostracon
Expand Down
12 changes: 6 additions & 6 deletions tests.mk
Original file line number Diff line number Diff line change
Expand Up @@ -60,22 +60,22 @@ vagrant_test:

### go tests
test:
@echo "--> Running go test"
@go test -p 1 $(PACKAGES) -tags deadlock
@echo "--> Running go test -- deadlock $(BUILD_TAGS)"
@go test -p 1 $(PACKAGES) -tags "deadlock $(BUILD_TAGS)"
.PHONY: test

test_race:
@echo "--> Running go test --race"
@go test -p 1 -v -race $(PACKAGES)
@echo "--> Running go test -- race $(BUILD_TAGS)"
@go test -p 1 -v -race $(PACKAGES) -tags "$(BUILD_TAGS)"
.PHONY: test_race

test_deadlock:
@echo "--> Running go test --deadlock"
@echo "--> Running go test -- deadlock"
@go test -p 1 -v $(PACKAGES) -tags deadlock
.PHONY: test_race

test_tags:
@echo "--> Running go test"
@echo "--> Running go test -- $(BUILD_TAGS)"
@go test -p 1 $(PACKAGES) -tags "$(BUILD_TAGS)"
.PHONY: test

Expand Down