decred.org/dcrdex@v1.0.5/server/account/account.go (about)

     1  // This code is available on the terms of the project LICENSE.md file,
     2  // also available online at https://blueoakcouncil.org/license/1.0.0.
     3  
     4  package account
     5  
     6  import (
     7  	"database/sql/driver"
     8  	"encoding/hex"
     9  	"encoding/json"
    10  	"fmt"
    11  	"math"
    12  
    13  	"github.com/decred/dcrd/crypto/blake256"
    14  	"github.com/decred/dcrd/dcrec/secp256k1/v4"
    15  )
    16  
    17  // PrivateKey is the private key type used by DEX.
    18  type PrivateKey = secp256k1.PrivateKey
    19  
    20  const (
    21  	PrivKeySize   = secp256k1.PrivKeyBytesLen
    22  	PubKeySize    = secp256k1.PubKeyBytesLenCompressed
    23  	HashSize      = blake256.Size
    24  	PrepaidBondID = math.MaxInt32
    25  )
    26  
    27  // HashFunc is the hash function used to generate account IDs from pubkeys.
    28  var HashFunc = blake256.Sum256
    29  
    30  // AccountID is a DEX account identifier.
    31  type AccountID [HashSize]byte
    32  
    33  // NewID generates a unique account id with the provided public key bytes.
    34  func NewID(pk []byte) AccountID {
    35  	// Hash the pubkey hash.
    36  	h := HashFunc(pk)
    37  	return HashFunc(h[:])
    38  }
    39  
    40  // String returns a hexadecimal representation of the AccountID. String
    41  // implements fmt.Stringer.
    42  func (aid AccountID) String() string {
    43  	return hex.EncodeToString(aid[:])
    44  }
    45  
    46  // MarshalJSON satisfies the json.Marshaller interface, and will marshal the
    47  // id to a hex string.
    48  func (aid AccountID) MarshalJSON() ([]byte, error) {
    49  	return json.Marshal(aid.String())
    50  }
    51  
    52  // Value implements the sql/driver.Valuer interface.
    53  func (aid AccountID) Value() (driver.Value, error) {
    54  	return aid[:], nil // []byte
    55  }
    56  
    57  // Scan implements the sql.Scanner interface.
    58  func (aid *AccountID) Scan(src any) error {
    59  	switch src := src.(type) {
    60  	case []byte:
    61  		copy(aid[:], src)
    62  		return nil
    63  		//case string:
    64  		// case nil:
    65  		// 	*oid = nil
    66  		// 	return nil
    67  	}
    68  
    69  	return fmt.Errorf("cannot convert %T to AccountID", src)
    70  }
    71  
    72  // Account represents a dex client account.
    73  type Account struct {
    74  	ID     AccountID
    75  	PubKey *secp256k1.PublicKey
    76  }
    77  
    78  // NewAccountFromPubKey creates a dex client account from the provided public
    79  // key bytes.
    80  func NewAccountFromPubKey(pk []byte) (*Account, error) {
    81  	if len(pk) != PubKeySize {
    82  		return nil, fmt.Errorf("invalid pubkey length, "+
    83  			"expected %d, got %d", PubKeySize, len(pk))
    84  	}
    85  
    86  	pubKey, err := secp256k1.ParsePubKey(pk)
    87  	if err != nil {
    88  		return nil, err
    89  	}
    90  
    91  	return &Account{
    92  		ID:     NewID(pk),
    93  		PubKey: pubKey,
    94  	}, nil
    95  }
    96  
    97  // Rule represents a rule of community conduct.
    98  type Rule uint8
    99  
   100  const (
   101  	// NoRule indicates that no rules have been broken. This may be an invalid
   102  	// value in some contexts.
   103  	NoRule Rule = iota
   104  	// PreimageReveal means an account failed to respond with a valid preimage
   105  	// for their order during epoch processing.
   106  	PreimageReveal
   107  	// FailureToAct means that an account has not followed through on one of their
   108  	// swap negotiation steps.
   109  	FailureToAct
   110  	// CancellationRate means the account's cancellation rate  has dropped below
   111  	// the acceptable level.
   112  	CancellationRate
   113  	// LowFees means an account made a transaction that didn't pay fees at the
   114  	// requisite level.
   115  	LowFees
   116  	// MaxRule in not an actual rule. It is a placeholder that is used to
   117  	// determine the total number of rules. It must always be the last
   118  	// definition in this list.
   119  	MaxRule
   120  )
   121  
   122  // details holds rule specific details.
   123  type details struct {
   124  	name, description string
   125  }
   126  
   127  // ruleDetails maps rules to rule details.
   128  var ruleDetails = map[Rule]details{
   129  	NoRule: {
   130  		name:        "NoRule",
   131  		description: "no rules have been broken",
   132  	},
   133  	PreimageReveal: {
   134  		name:        "PreimageReveal",
   135  		description: "failed to respond with a valid preimage for an order during epoch processing",
   136  	},
   137  	FailureToAct: {
   138  		name:        "FailureToAct",
   139  		description: "did not follow through on a swap negotiation step",
   140  	},
   141  	CancellationRate: {
   142  		name:        "CancellationRate",
   143  		description: "cancellation rate dropped below the acceptable level",
   144  	},
   145  	LowFees: {
   146  		name:        "LowFees",
   147  		description: "did not pay transaction mining fees at the requisite level",
   148  	},
   149  }
   150  
   151  // String satisfies the Stringer interface.
   152  func (r Rule) String() string {
   153  	if d, ok := ruleDetails[r]; ok {
   154  		return d.name
   155  	}
   156  	return "unknown rule"
   157  }
   158  
   159  // Description returns a description of the rule.
   160  func (r Rule) Description() string {
   161  	if d, ok := ruleDetails[r]; ok {
   162  		return d.description
   163  	}
   164  	return "description not specified"
   165  }
   166  
   167  // Punishable returns whether breaking this rule incurs a penalty.
   168  func (r Rule) Punishable() bool {
   169  	return r > NoRule && r < MaxRule
   170  }
   171  
   172  // Reputation is a part of a number of server-originating messages. It was
   173  // introduced with the v2 ConnectResult.
   174  type Reputation struct {
   175  	// BondedTier is the tier indicated by the user's active bonds. BondedTier
   176  	// does not account for penalties.
   177  	BondedTier int64 `json:"bondedTier"`
   178  	// Penalties are the number of tiers that are currently revoked due to low
   179  	// user score.
   180  	Penalties uint16 `json:"penalties"`
   181  	// Score is the user's current score. Score must be evaluated against a
   182  	// server's configured penalty threshold to calculate penalties.
   183  	Score int32 `json:"score"`
   184  }
   185  
   186  // Effective calculates the effective tier for trading limit calculations.
   187  func (r *Reputation) EffectiveTier() int64 {
   188  	tier := r.BondedTier - int64(r.Penalties)
   189  	return tier
   190  }