2019-09-15 21:20:05 +00:00
|
|
|
package tokenboard
|
|
|
|
|
|
|
|
import (
|
|
|
|
"errors"
|
2021-04-09 00:55:17 +00:00
|
|
|
"git.openprivacy.ca/cwtch.im/tapir/applications"
|
|
|
|
"git.openprivacy.ca/cwtch.im/tapir/networks/tor"
|
|
|
|
"git.openprivacy.ca/cwtch.im/tapir/primitives"
|
|
|
|
"git.openprivacy.ca/cwtch.im/tapir/primitives/auditable"
|
|
|
|
"git.openprivacy.ca/cwtch.im/tapir/primitives/privacypass"
|
2020-02-06 23:54:13 +00:00
|
|
|
"git.openprivacy.ca/openprivacy/connectivity"
|
|
|
|
torProvider "git.openprivacy.ca/openprivacy/connectivity/tor"
|
|
|
|
"git.openprivacy.ca/openprivacy/log"
|
2020-06-29 21:32:38 +00:00
|
|
|
"os"
|
2019-09-15 21:20:05 +00:00
|
|
|
"runtime"
|
|
|
|
"sync"
|
|
|
|
"testing"
|
|
|
|
"time"
|
|
|
|
)
|
|
|
|
|
|
|
|
type Handler struct {
|
|
|
|
Store *auditable.Store
|
|
|
|
}
|
|
|
|
|
|
|
|
func (h Handler) HandleNewMessages(previousLastCommit []byte) {
|
|
|
|
log.Debugf("Handling Messages After %x", previousLastCommit)
|
|
|
|
messages := h.Store.GetMessagesAfter(previousLastCommit)
|
|
|
|
for _, message := range messages {
|
|
|
|
log.Debugf("Message %s", message)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
type FreePaymentHandler struct {
|
|
|
|
tokens []*privacypass.Token
|
|
|
|
TokenService *privacypass.TokenServer
|
|
|
|
ACN connectivity.ACN
|
|
|
|
ServerHostname string
|
|
|
|
}
|
|
|
|
|
|
|
|
func (fph *FreePaymentHandler) MakePayment() {
|
|
|
|
id, sk := primitives.InitializeEphemeralIdentity()
|
2021-06-09 17:36:34 +00:00
|
|
|
client := new(tor.BaseOnionService)
|
2019-09-15 21:20:05 +00:00
|
|
|
client.Init(fph.ACN, sk, &id)
|
|
|
|
|
|
|
|
tokenApplication := new(applications.TokenApplication)
|
|
|
|
tokenApplication.TokenService = fph.TokenService
|
|
|
|
powTokenApp := new(applications.ApplicationChain).
|
|
|
|
ChainApplication(new(applications.ProofOfWorkApplication), applications.SuccessfulProofOfWorkCapability).
|
|
|
|
ChainApplication(tokenApplication, applications.HasTokensCapability)
|
|
|
|
client.Connect(fph.ServerHostname, powTokenApp)
|
2019-11-26 21:10:09 +00:00
|
|
|
conn, err := client.WaitForCapabilityOrClose(fph.ServerHostname, applications.HasTokensCapability)
|
2019-09-15 21:20:05 +00:00
|
|
|
if err == nil {
|
|
|
|
powtapp, _ := conn.App().(*applications.TokenApplication)
|
|
|
|
fph.tokens = append(fph.tokens, powtapp.Tokens...)
|
|
|
|
log.Debugf("Transcript: %v", powtapp.Transcript().OutputTranscriptToAudit())
|
|
|
|
conn.Close()
|
2019-11-26 21:10:09 +00:00
|
|
|
return
|
2019-09-15 21:20:05 +00:00
|
|
|
}
|
|
|
|
log.Debugf("Error making payment: %v", err)
|
|
|
|
}
|
|
|
|
|
2019-11-26 21:10:09 +00:00
|
|
|
func (fph *FreePaymentHandler) NextToken(data []byte, hostname string) (privacypass.SpentToken, error) {
|
2019-09-15 21:20:05 +00:00
|
|
|
if len(fph.tokens) == 0 {
|
|
|
|
return privacypass.SpentToken{}, errors.New("No more tokens")
|
|
|
|
}
|
|
|
|
token := fph.tokens[0]
|
|
|
|
fph.tokens = fph.tokens[1:]
|
2019-11-26 21:10:09 +00:00
|
|
|
return token.SpendToken(append(data, hostname...)), nil
|
2019-09-15 21:20:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestTokenBoardApp(t *testing.T) {
|
|
|
|
// numRoutinesStart := runtime.NumGoroutine()
|
|
|
|
log.SetLevel(log.LevelDebug)
|
|
|
|
log.Infof("Number of goroutines open at start: %d", runtime.NumGoroutine())
|
2020-06-29 21:32:38 +00:00
|
|
|
|
|
|
|
os.MkdirAll("./tor/", 0700)
|
2021-04-09 00:14:41 +00:00
|
|
|
builder := new(torProvider.TorrcBuilder)
|
|
|
|
builder.WithHashedPassword("tapir-integration-test").Build("./tor/torrc")
|
2020-06-29 21:32:38 +00:00
|
|
|
|
2019-09-15 21:20:05 +00:00
|
|
|
// Connect to Tor
|
2020-06-29 21:32:38 +00:00
|
|
|
acn, err := torProvider.NewTorACNWithAuth("./", "", 9051, torProvider.HashedPasswordAuthenticator{Password: "tapir-integration-test"})
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("could not launch ACN %v", err)
|
|
|
|
}
|
2019-09-15 21:20:05 +00:00
|
|
|
acn.WaitTillBootstrapped()
|
|
|
|
|
|
|
|
// Generate Server Key
|
|
|
|
sid, sk := primitives.InitializeEphemeralIdentity()
|
|
|
|
tokenService := privacypass.NewTokenServer()
|
|
|
|
serverAuditableStore := new(auditable.Store)
|
|
|
|
serverAuditableStore.Init(sid)
|
|
|
|
|
|
|
|
clientAuditableStore := new(auditable.Store)
|
|
|
|
// Only initialize with public parameters
|
|
|
|
sidpubk := sid.PublicKey()
|
|
|
|
publicsid := primitives.InitializeIdentity("server", nil, &sidpubk)
|
|
|
|
clientAuditableStore.Init(publicsid)
|
|
|
|
|
|
|
|
// Init the Server running the Simple App.
|
2021-06-09 17:36:34 +00:00
|
|
|
service := new(tor.BaseOnionService)
|
2019-09-15 21:20:05 +00:00
|
|
|
service.Init(acn, sk, &sid)
|
|
|
|
|
|
|
|
// Goroutine Management
|
|
|
|
sg := new(sync.WaitGroup)
|
|
|
|
sg.Add(1)
|
|
|
|
go func() {
|
2019-11-26 21:10:09 +00:00
|
|
|
service.Listen(NewTokenBoardServer(tokenService, serverAuditableStore))
|
2019-09-15 21:20:05 +00:00
|
|
|
sg.Done()
|
|
|
|
}()
|
|
|
|
|
|
|
|
// Init the Server running the PoW Token App.
|
2021-06-09 17:36:34 +00:00
|
|
|
powTokenService := new(tor.BaseOnionService)
|
2019-09-15 21:20:05 +00:00
|
|
|
spowid, spowk := primitives.InitializeEphemeralIdentity()
|
|
|
|
powTokenService.Init(acn, spowk, &spowid)
|
|
|
|
sg.Add(1)
|
|
|
|
go func() {
|
|
|
|
tokenApplication := new(applications.TokenApplication)
|
2019-11-26 21:10:09 +00:00
|
|
|
tokenApplication.TokenService = tokenService
|
2019-09-15 21:20:05 +00:00
|
|
|
powTokenApp := new(applications.ApplicationChain).
|
|
|
|
ChainApplication(new(applications.ProofOfWorkApplication), applications.SuccessfulProofOfWorkCapability).
|
|
|
|
ChainApplication(tokenApplication, applications.HasTokensCapability)
|
|
|
|
powTokenService.Listen(powTokenApp)
|
|
|
|
sg.Done()
|
|
|
|
}()
|
|
|
|
|
|
|
|
time.Sleep(time.Second * 60) // wait for server to initialize
|
|
|
|
id, sk := primitives.InitializeEphemeralIdentity()
|
2021-06-09 17:36:34 +00:00
|
|
|
client := new(tor.BaseOnionService)
|
2019-09-15 21:20:05 +00:00
|
|
|
client.Init(acn, sk, &id)
|
2019-11-26 21:10:09 +00:00
|
|
|
client.Connect(sid.Hostname(), NewTokenBoardClient(clientAuditableStore, Handler{Store: clientAuditableStore}, &FreePaymentHandler{ACN: acn, TokenService: tokenService, ServerHostname: spowid.Hostname()}))
|
2019-09-15 21:20:05 +00:00
|
|
|
client.WaitForCapabilityOrClose(sid.Hostname(), applications.AuthCapability)
|
|
|
|
conn, _ := client.GetConnection(sid.Hostname())
|
|
|
|
tba, _ := conn.App().(*Client)
|
|
|
|
tba.PurchaseTokens()
|
|
|
|
tba.Post([]byte("HELLO 1"))
|
|
|
|
tba.Post([]byte("HELLO 2"))
|
|
|
|
tba.Post([]byte("HELLO 3"))
|
|
|
|
tba.Post([]byte("HELLO 4"))
|
|
|
|
tba.Post([]byte("HELLO 5"))
|
|
|
|
tba.Replay()
|
|
|
|
time.Sleep(time.Second * 10) // We have to wait for the async replay request!
|
|
|
|
tba.Post([]byte("HELLO 6"))
|
|
|
|
tba.Post([]byte("HELLO 7"))
|
|
|
|
tba.Post([]byte("HELLO 8"))
|
|
|
|
tba.Post([]byte("HELLO 9"))
|
|
|
|
tba.Post([]byte("HELLO 10"))
|
|
|
|
tba.Replay()
|
|
|
|
time.Sleep(time.Second * 10) // We have to wait for the async replay request!
|
|
|
|
|
|
|
|
if tba.Post([]byte("HELLO 11")) {
|
|
|
|
t.Errorf("Post should have failed.")
|
|
|
|
}
|
|
|
|
|
|
|
|
time.Sleep(time.Second * 10)
|
|
|
|
acn.Close()
|
|
|
|
sg.Wait()
|
|
|
|
}
|