package transport import ( "encoding/binary" "net" "ripple/crypto" "ripple/types" "ripple/udpr" ) type AccountTransport struct { d *Data c *udpr.UDPRConn m *AccountSenderManager } func NewAccountTransport(c *udpr.UDPRConn, d *Data) (*AccountTransport, *AccountSenderManager) { t := &AccountTransport{d: d, c: c} m := newAccountSenderManager(t) t.m = m return t, m } func (t *AccountTransport) Receive(tx []byte, addr *net.UDPAddr) (types.Transaction, error) { if len(tx) < 1+32+64+4+1+32 { return types.Transaction{}, errInvalidTransaction } id := parseTxFrom(tx) acc, ok := t.d.Storage.Accounts[id] if !ok { return types.Transaction{}, errInvalidTransaction } if !crypto.VerifySignature(tx, acc.SecretKey) { return types.Transaction{}, errInvalidTransaction } counter := binary.BigEndian.Uint32(tx[97:101]) if counter <= acc.CounterIn { return types.Transaction{}, errInvalidTransaction } t.d.mustSetAccountCounterIn(id, counter) command := tx[101] args := tx[102:len(tx)-32] return types.Transaction{ Identifier: id, Instruction: types.Instruction{Command: command, Arguments: args}, }, nil } func (t *AccountTransport) send(tx types.Transaction) { id := tx.Identifier counter, err := t.d.incrementAndGetAccountCounterOut(id) if err != nil { return } raw := buildTx( accountType, id.Username, t.d.Storage.User.UserIdentifier, counter, tx.Instruction, ) acc, ok := t.d.getAccount(id) if !ok { return } signed := crypto.SignData(raw, acc.SecretKey) addr, err := getAddr(id.ServerAddress, acc.Port) if err != nil { return } _ = t.c.WriteToUDPR(signed, addr) } func (t *AccountTransport) SendPriority(id types.UserIdentifier, instr types.Instruction) { t.m.enqueueWithIndex(highCh, types.Transaction{Identifier: id, Instruction: instr}) } func (t *AccountTransport) Send(id types.UserIdentifier, instr types.Instruction) { t.m.enqueueWithIndex(lowCh, types.Transaction{Identifier: id, Instruction: instr}) }