This repository has been archived by the owner on May 26, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 42
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #173 from libp2p/interop
use GitHub Actions to test interopability of releases
- Loading branch information
Showing
7 changed files
with
404 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
#!/bin/bash | ||
|
||
set -e | ||
|
||
SERVER=$1 | ||
CLIENT=$2 | ||
SERVER_ADDR="/ip4/127.0.0.1/udp/12345/quic" | ||
|
||
for k1 in server*.key; do | ||
for k2 in client*.key; do | ||
echo "Running with server $SERVER ($k1) and client $CLIENT ($k2)" | ||
./$SERVER -role server -key $k1 -peerkey $k2 -addr $SERVER_ADDR & | ||
./$CLIENT -role client -key $k2 -peerkey $k1 -addr $SERVER_ADDR | ||
wait & | ||
done; | ||
done; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
name: interop | ||
on: | ||
push: | ||
branches: master | ||
tags: | ||
pull_request: | ||
branches: master | ||
|
||
jobs: | ||
keygen: | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/checkout@v2 | ||
- uses: actions/setup-go@v1 | ||
with: | ||
go-version: '^1.15' | ||
- name: Generate keys | ||
run: | | ||
go build -o keygen integrationtests/keygen/keygen.go | ||
./keygen -prefix server | ||
./keygen -prefix client | ||
- name: Upload keys | ||
uses: actions/upload-artifact@v2 | ||
with: | ||
name: keys | ||
path: ./*.key | ||
matrix: | ||
runs-on: ubuntu-latest | ||
outputs: | ||
matrix: ${{ steps.set-matrix.outputs.matrix }} | ||
steps: | ||
- uses: actions/checkout@v2 | ||
- id: set-matrix | ||
run: | | ||
TASKS=$(echo $(grep -o '^[^//]*' .github/workflows/matrix.jsonc) | sed 's/ //g' ) | ||
echo $TASKS | ||
echo "::set-output name=matrix::$TASKS" | ||
builder: | ||
needs: [ matrix ] | ||
runs-on: ubuntu-latest | ||
strategy: | ||
matrix: | ||
cfg: ${{ fromJson(needs.matrix.outputs.matrix) }} | ||
name: Builder (${{ matrix.cfg.commit }}, Go ${{ matrix.cfg.go }}) | ||
steps: | ||
- uses: actions/checkout@v2 | ||
with: | ||
fetch-depth: 0 | ||
- uses: actions/setup-go@v1 | ||
with: | ||
go-version: ${{ matrix.cfg.go }} | ||
- run: go version | ||
- name: Build transport | ||
run: | | ||
cp -r integrationtests builder | ||
git checkout ${{ matrix.cfg.commit }} | ||
rm -rf integrationtests || true | ||
mv builder integrationtests | ||
git reflog --decorate -1 | ||
if [[ `git merge-base --is-ancestor HEAD 126c64772ba0aef0b2b6d58ff36e55a93f9253a7; echo $?` == "1" ]]; then | ||
go build -o transport-go${{ matrix.cfg.go }}-${{ matrix.cfg.commit }} integrationtests/main.go | ||
else | ||
go build -tags oldstream -o transport-go${{ matrix.cfg.go }}-${{ matrix.cfg.commit }} integrationtests/main.go | ||
fi | ||
- name: Upload binary | ||
uses: actions/upload-artifact@v2 | ||
with: | ||
name: binary | ||
path: ./transport-go${{ matrix.cfg.go }}-${{ matrix.cfg.commit }} | ||
interop: | ||
runs-on: ubuntu-latest | ||
needs: [ matrix, keygen, builder ] | ||
strategy: | ||
matrix: | ||
server: ${{ fromJson(needs.matrix.outputs.matrix) }} | ||
client: ${{ fromJson(needs.matrix.outputs.matrix) }} | ||
name: server (${{ matrix.server.commit }}, Go ${{ matrix.server.go }}) - client (${{ matrix.client.commit }}, Go ${{ matrix.client.go }}) | ||
steps: | ||
- uses: actions/checkout@v2 | ||
- run: mkdir interop | ||
- name: Download keys | ||
uses: actions/download-artifact@v2 | ||
with: | ||
name: keys | ||
path: interop/ | ||
- name: Download binary | ||
uses: actions/download-artifact@v2 | ||
with: | ||
name: binary | ||
path: interop/ | ||
- name: Run interop | ||
run: | | ||
cd interop | ||
chmod 744 transport* | ||
../.github/workflows/interop.sh transport-go${{ matrix.server.go }}-${{ matrix.server.commit }} transport-go${{ matrix.client.go }}-${{ matrix.client.commit }} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
[ | ||
{ "go": "1.13", "commit": "v0.6.0" }, | ||
{ "go": "1.14", "commit": "v0.6.0" }, | ||
{ "go": "1.13", "commit": "v0.7.0" }, | ||
{ "go": "1.14", "commit": "v0.7.0" }, | ||
// v0.7.1 was never released in IPFS. | ||
{ "go": "1.14", "commit": "v0.8.0" }, | ||
{ "go": "1.15", "commit": "v0.8.0" }, | ||
{ "go": "1.14", "commit": "HEAD" }, | ||
{ "go": "1.15", "commit": "HEAD" } | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
package main | ||
|
||
import ( | ||
"crypto/rand" | ||
"flag" | ||
"io/ioutil" | ||
"log" | ||
|
||
"github.com/libp2p/go-libp2p-core/crypto" | ||
) | ||
|
||
func main() { | ||
prefix := flag.String("prefix", "", "output file name prefix") | ||
flag.Parse() | ||
|
||
if err := exportKeys(*prefix); err != nil { | ||
log.Fatal(err) | ||
} | ||
} | ||
|
||
func exportKeys(prefix string) error { | ||
rsa, _, err := crypto.GenerateRSAKeyPair(2048, rand.Reader) | ||
if err != nil { | ||
return err | ||
} | ||
if err := writeKey(rsa, prefix+"-rsa"); err != nil { | ||
return err | ||
} | ||
|
||
ecdsa, _, err := crypto.GenerateECDSAKeyPair(rand.Reader) | ||
if err != nil { | ||
return err | ||
} | ||
if err := writeKey(ecdsa, prefix+"-ecdsa"); err != nil { | ||
return err | ||
} | ||
|
||
ed, _, err := crypto.GenerateEd25519Key(rand.Reader) | ||
if err != nil { | ||
return err | ||
} | ||
if err := writeKey(ed, prefix+"-ed25519"); err != nil { | ||
return err | ||
} | ||
|
||
sec, _, err := crypto.GenerateSecp256k1Key(rand.Reader) | ||
if err != nil { | ||
return err | ||
} | ||
return writeKey(sec, prefix+"-secp256k1") | ||
} | ||
|
||
func writeKey(priv crypto.PrivKey, name string) error { | ||
privBytes, err := crypto.MarshalPrivateKey(priv) | ||
if err != nil { | ||
log.Fatal(err) | ||
} | ||
filename := name + ".key" | ||
log.Println("Exporting key to", filename) | ||
return ioutil.WriteFile(filename, privBytes, 0644) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,162 @@ | ||
package main | ||
|
||
import ( | ||
"bytes" | ||
"context" | ||
"crypto/rand" | ||
"errors" | ||
"flag" | ||
"fmt" | ||
"io/ioutil" | ||
"log" | ||
"time" | ||
|
||
"github.com/libp2p/go-libp2p-core/crypto" | ||
"github.com/libp2p/go-libp2p-core/peer" | ||
libp2pquic "github.com/libp2p/go-libp2p-quic-transport" | ||
ma "github.com/multiformats/go-multiaddr" | ||
|
||
"github.com/libp2p/go-libp2p-quic-transport/integrationtests/stream" | ||
) | ||
|
||
func main() { | ||
hostKeyFile := flag.String("key", "", "file containing the libp2p private key") | ||
peerKeyFile := flag.String("peerkey", "", "file containing the libp2p private key of the peer") | ||
addrStr := flag.String("addr", "", "address to listen on (for the server) or to dial (for the client)") | ||
role := flag.String("role", "", "server or client") | ||
flag.Parse() | ||
|
||
hostKey, peerPubKey, err := readKeys(*hostKeyFile, *peerKeyFile) | ||
if err != nil { | ||
log.Fatal(err) | ||
} | ||
addr, err := ma.NewMultiaddr(*addrStr) | ||
if err != nil { | ||
log.Fatal(err) | ||
} | ||
|
||
switch *role { | ||
case "server": | ||
if err := runServer(hostKey, peerPubKey, addr); err != nil { | ||
log.Fatal(err) | ||
} | ||
case "client": | ||
if err := runClient(hostKey, peerPubKey, addr); err != nil { | ||
log.Fatal(err) | ||
} | ||
} | ||
} | ||
|
||
// We pass in both the private keys of host and peer. | ||
// We never use the private key of the peer though. | ||
// That's why this function returns the peer's public key. | ||
func readKeys(hostKeyFile, peerKeyFile string) (crypto.PrivKey, crypto.PubKey, error) { | ||
// read the host key | ||
hostKeyBytes, err := ioutil.ReadFile(hostKeyFile) | ||
if err != nil { | ||
return nil, nil, err | ||
} | ||
hostKey, err := crypto.UnmarshalPrivateKey(hostKeyBytes) | ||
if err != nil { | ||
return nil, nil, err | ||
} | ||
// read the peers key | ||
peerKeyBytes, err := ioutil.ReadFile(peerKeyFile) | ||
if err != nil { | ||
return nil, nil, err | ||
} | ||
peerKey, err := crypto.UnmarshalPrivateKey(peerKeyBytes) | ||
if err != nil { | ||
return nil, nil, err | ||
} | ||
return hostKey, peerKey.GetPublic(), nil | ||
} | ||
|
||
func runServer(hostKey crypto.PrivKey, peerKey crypto.PubKey, addr ma.Multiaddr) error { | ||
tr, err := libp2pquic.NewTransport(hostKey, nil, nil) | ||
if err != nil { | ||
return err | ||
} | ||
ln, err := tr.Listen(addr) | ||
if err != nil { | ||
return err | ||
} | ||
conn, err := ln.Accept() | ||
if err != nil { | ||
return err | ||
} | ||
defer ln.Close() | ||
if !conn.RemotePublicKey().Equals(peerKey) { | ||
return errors.New("mismatching public keys") | ||
} | ||
clientPeerID, err := peer.IDFromPublicKey(peerKey) | ||
if err != nil { | ||
return err | ||
} | ||
if conn.RemotePeer() != clientPeerID { | ||
return fmt.Errorf("remote Peer ID mismatch. Got %s, expected %s", conn.RemotePeer().Pretty(), clientPeerID.Pretty()) | ||
} | ||
for { | ||
st, err := conn.AcceptStream() | ||
if err != nil { | ||
return nil | ||
} | ||
str := stream.WrapStream(st) | ||
defer str.Close() | ||
data, err := ioutil.ReadAll(str) | ||
if err != nil { | ||
return err | ||
} | ||
if _, err := str.Write(data); err != nil { | ||
return err | ||
} | ||
if err := str.CloseWrite(); err != nil { | ||
return err | ||
} | ||
} | ||
} | ||
|
||
func runClient(hostKey crypto.PrivKey, peerKey crypto.PubKey, addr ma.Multiaddr) error { | ||
tr, err := libp2pquic.NewTransport(hostKey, nil, nil) | ||
if err != nil { | ||
return err | ||
} | ||
serverPeerID, err := peer.IDFromPublicKey(peerKey) | ||
if err != nil { | ||
return err | ||
} | ||
ctx, cancel := context.WithTimeout(context.Background(), time.Second) | ||
defer cancel() | ||
conn, err := tr.Dial(ctx, addr, serverPeerID) | ||
if err != nil { | ||
return err | ||
} | ||
defer conn.Close() | ||
if !conn.RemotePublicKey().Equals(peerKey) { | ||
return errors.New("mismatching public keys") | ||
} | ||
if conn.RemotePeer() != serverPeerID { | ||
return fmt.Errorf("remote Peer ID mismatch. Got %s, expected %s", conn.RemotePeer().Pretty(), serverPeerID.Pretty()) | ||
} | ||
st, err := conn.OpenStream() | ||
if err != nil { | ||
return err | ||
} | ||
str := stream.WrapStream(st) | ||
data := make([]byte, 1<<15) | ||
rand.Read(data) | ||
if _, err := str.Write(data); err != nil { | ||
return err | ||
} | ||
if err := str.CloseWrite(); err != nil { | ||
return err | ||
} | ||
echoed, err := ioutil.ReadAll(str) | ||
if err != nil { | ||
return err | ||
} | ||
if !bytes.Equal(data, echoed) { | ||
return errors.New("echoed data does not match") | ||
} | ||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
package stream | ||
|
||
import ( | ||
"io" | ||
"time" | ||
|
||
"github.com/libp2p/go-libp2p-core/mux" | ||
) | ||
|
||
type Stream interface { | ||
io.Reader | ||
io.Writer | ||
io.Closer | ||
|
||
CloseWrite() error | ||
CloseRead() error | ||
Reset() error | ||
|
||
SetDeadline(time.Time) error | ||
SetReadDeadline(time.Time) error | ||
SetWriteDeadline(time.Time) error | ||
} | ||
|
||
type stream struct { | ||
mux.MuxedStream | ||
} | ||
|
||
func WrapStream(str mux.MuxedStream) *stream { | ||
return &stream{MuxedStream: str} | ||
} |
Oops, something went wrong.