package handler import ( "encoding/binary" "encoding/hex" "ripple/config" "ripple/crypto" "ripple/datavisor" "ripple/helpers" "ripple/services" "ripple/state" "ripple/types" ) type UserHandlers struct { st *state.State m *datavisor.AccountManager pm *services.PaymentManager } func NewUserHandlers( st *state.State, m *datavisor.AccountManager, pm *services.PaymentManager, ) *UserHandlers { return &UserHandlers{ st: st, m: m, pm: pm, } } func successResponse(data []byte) (byte, []byte) { return 0x00, data } func errorResponse(data []byte) (byte, []byte) { return 0x01, data } func successMsg(msg string) (byte, []byte) { return successResponse([]byte(msg)) } func errorMsg(msg string) (byte, []byte) { return errorResponse([]byte(msg)) } func (h *UserHandlers) decrypt(ciphertext [32]byte, counter uint32) [32]byte { sk := h.st.Storage.User.SecretKey return crypto.XorWithOneTimeKey(ciphertext, sk, counter) } func (h *UserHandlers) SetTrustline(r types.ClientRemote, args []byte) (byte, []byte) { if len(args) < 72 { return errorMsg("Invalid arguments") } id := types.NewUserIdentifierFromBytes(args[0:64]) value := binary.BigEndian.Uint64(args[64:72]) if !h.st.Storage.AccountExists(id) { return errorMsg("Peer does not exist") } account := h.st.Storage.MustGetAccount(id) account.Creditlimit = value h.st.Storage.Accounts[id] = account return successMsg("Set trustline") } func (h *UserHandlers) AddAccount(r types.ClientRemote, args []byte) (byte, []byte) { if len(args) < 98 { return errorMsg("Invalid arguments") } id := types.NewUserIdentifierFromBytes(args[0:64]) portBytes := args[64:66] var ciph [32]byte copy(ciph[:], args[66:98]) if h.st.Storage.AccountExists(id) { return errorMsg("Peer already exists") } if len(h.st.Storage.Accounts) >= config.BufferSize { return errorMsg("Peer slots full") } port := binary.BigEndian.Uint16(portBytes) secretKey := h.decrypt(ciph, r.Counter) if err := h.m.AddAccount(id, int(port), secretKey); err != nil { return errorMsg("Error") } return successMsg("Add account") } func (h *UserHandlers) NewPayment(r types.ClientRemote, args []byte) (byte, []byte) { if len(args) < 119 { return errorMsg("Invalid arguments") } id := types.NewUserIdentifierFromBytes(args[0:64]) port := int(binary.BigEndian.Uint16(args[64:66])) var ciph [32]byte copy(ciph[:], args[66:98]) amount := binary.BigEndian.Uint64(args[98:106]) inOrOut := args[106] penaltyRate := binary.BigEndian.Uint32(args[107:111]) fee := binary.BigEndian.Uint64(args[111:119]) secretKey := h.decrypt(ciph, r.Counter) h.pm.InitPayment(id, port, secretKey, amount, helpers.ByteToBool(inOrOut), penaltyRate, fee) return successMsg("New payment") } func (h *UserHandlers) StartPayment(r types.ClientRemote, args []byte) (byte, []byte) { paymentID := h.st.Memory.GetPaymentID() if _, ok := h.st.Memory.GetPathfinding(paymentID); !ok { return errorMsg("No active payment") } h.pm.ForwardFindPath(paymentID) return successMsg("Start payment") } func (h *UserHandlers) GetNumAccounts(r types.ClientRemote, args []byte) (byte, []byte) { count := len(h.st.Storage.Accounts) buf := []byte{byte(count)} return successResponse(buf) } func (h *UserHandlers) GetAccount(r types.ClientRemote, args []byte) (byte, []byte) { if len(args) < 1 { return errorMsg("Invalid arguments") } idx := int(args[0]) id, ok := h.st.Storage.GetAccountByIndex(idx) if !ok { return errorMsg("Invalid account index") } account, ok := h.st.Storage.Accounts[id] if !ok { return errorMsg("Account not found") } buf := make([]byte, 88) copy(buf[0:32], []byte(id.Username)) copy(buf[32:64], []byte(id.ServerAddress)) binary.BigEndian.PutUint64(buf[64:], uint64(account.Balance)) binary.BigEndian.PutUint64(buf[80:], account.Creditlimit) return successResponse(buf) } func (h *UserHandlers) GetPayment(r types.ClientRemote, args []byte) (byte, []byte) { paymentID := h.st.Memory.GetPaymentID() if _, ok := h.st.Memory.GetPathfinding(paymentID); !ok { return errorMsg("No active payment") } hexID := hex.EncodeToString(paymentID[:]) return successMsg(hexID) }