forked from cwtch.im/tapir
93 lines
2.9 KiB
Go
93 lines
2.9 KiB
Go
package tokenboard
|
|
|
|
// NOTE: This is a sketch implementation, Not suitable for production use. The real auditable store is still being designed.
|
|
|
|
import (
|
|
"cwtch.im/tapir"
|
|
"cwtch.im/tapir/applications"
|
|
"cwtch.im/tapir/primitives/auditable"
|
|
"cwtch.im/tapir/primitives/privacypass"
|
|
"encoding/json"
|
|
"git.openprivacy.ca/openprivacy/log"
|
|
)
|
|
|
|
// NewTokenBoardServer generates new Server for Token Board
|
|
func NewTokenBoardServer(tokenService *privacypass.TokenServer, store *auditable.Store) tapir.Application {
|
|
tba := new(Server)
|
|
tba.TokenService = tokenService
|
|
tba.AuditableStore = store
|
|
return tba
|
|
}
|
|
|
|
// Server defines the token board server
|
|
type Server struct {
|
|
applications.AuthApp
|
|
connection tapir.Connection
|
|
TokenService *privacypass.TokenServer
|
|
AuditableStore *auditable.Store
|
|
}
|
|
|
|
// NewInstance creates a new TokenBoardApp
|
|
func (ta *Server) NewInstance() tapir.Application {
|
|
tba := new(Server)
|
|
tba.TokenService = ta.TokenService
|
|
tba.AuditableStore = ta.AuditableStore
|
|
return tba
|
|
}
|
|
|
|
// Init initializes the cryptographic TokenBoardApp
|
|
func (ta *Server) Init(connection tapir.Connection) {
|
|
ta.AuthApp.Init(connection)
|
|
|
|
if connection.HasCapability(applications.AuthCapability) {
|
|
ta.connection = connection
|
|
go ta.Listen()
|
|
return
|
|
}
|
|
connection.Close()
|
|
}
|
|
|
|
// Listen processes the messages for this application
|
|
func (ta *Server) Listen() {
|
|
for {
|
|
data := ta.connection.Expect()
|
|
if len(data) == 0 {
|
|
return // connection is closed
|
|
}
|
|
|
|
var message Message
|
|
json.Unmarshal(data, &message)
|
|
|
|
switch message.MessageType {
|
|
case postRequestMessage:
|
|
postrequest := message.PostRequest
|
|
log.Debugf("Received a Post Message Request: %x %x", postrequest.Token, postrequest.Message)
|
|
ta.postMessageRequest(postrequest.Token, postrequest.Message)
|
|
case replayRequestMessage:
|
|
log.Debugf("Received Replay Request %v", message.ReplayRequest)
|
|
state := ta.AuditableStore.GetStateAfter(message.ReplayRequest.LastCommit)
|
|
response, _ := json.Marshal(Message{MessageType: replayResultMessage, ReplayResult: replayResult{len(state.Messages)}})
|
|
log.Debugf("Sending Replay Response %v", replayResult{len(state.Messages)})
|
|
ta.connection.Send(response)
|
|
for _, message := range state.Messages {
|
|
ta.connection.Send(message)
|
|
}
|
|
data, _ := json.Marshal(state.SignedProof)
|
|
ta.connection.Send(data)
|
|
}
|
|
}
|
|
}
|
|
|
|
func (ta *Server) postMessageRequest(token privacypass.SpentToken, message auditable.Message) {
|
|
if err := ta.TokenService.SpendToken(token, append(message, ta.connection.ID().Hostname()...)); err == nil {
|
|
log.Debugf("Token is valid")
|
|
signedproof := ta.AuditableStore.Add(message)
|
|
data, _ := json.Marshal(Message{MessageType: postResultMessage, PostResult: postResult{true, signedproof}})
|
|
ta.connection.Send(data)
|
|
} else {
|
|
log.Debugf("Attempt to spend an invalid token: %v", err)
|
|
data, _ := json.Marshal(Message{MessageType: postResultMessage, PostResult: postResult{false, auditable.SignedProof{}}})
|
|
ta.connection.Send(data)
|
|
}
|
|
}
|