You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

177 lines
4.3 KiB

10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
  1. package state
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "io"
  6. "io/ioutil"
  7. "github.com/tendermint/go-ed25519"
  8. . "github.com/tendermint/tendermint/binary"
  9. . "github.com/tendermint/tendermint/blocks"
  10. . "github.com/tendermint/tendermint/common"
  11. )
  12. const (
  13. AccountStatusNominal = byte(0x00)
  14. AccountStatusBonded = byte(0x01)
  15. AccountStatusUnbonding = byte(0x02)
  16. AccountStatusDupedOut = byte(0x03)
  17. )
  18. type Account struct {
  19. Id uint64 // Numeric id of account, incrementing.
  20. PubKey []byte
  21. }
  22. func ReadAccount(r io.Reader, n *int64, err *error) Account {
  23. return Account{
  24. Id: ReadUInt64(r, n, err),
  25. PubKey: ReadByteSlice(r, n, err),
  26. }
  27. }
  28. func (account Account) WriteTo(w io.Writer) (n int64, err error) {
  29. WriteUInt64(w, account.Id, &n, &err)
  30. WriteByteSlice(w, account.PubKey, &n, &err)
  31. return
  32. }
  33. func (account Account) VerifyBytes(msg []byte, sig Signature) bool {
  34. if sig.SignerId != account.Id {
  35. panic("account.id doesn't match sig.signerid")
  36. }
  37. if len(sig.Bytes) == 0 {
  38. panic("signature is empty")
  39. }
  40. v1 := &ed25519.Verify{
  41. Message: msg,
  42. PubKey: account.PubKey,
  43. Signature: sig.Bytes,
  44. }
  45. ok := ed25519.VerifyBatch([]*ed25519.Verify{v1})
  46. return ok
  47. }
  48. func (account Account) Verify(o Signable) bool {
  49. sig := o.GetSignature()
  50. o.SetSignature(Signature{}) // clear
  51. msg := BinaryBytes(o)
  52. o.SetSignature(sig) // restore
  53. return account.VerifyBytes(msg, sig)
  54. }
  55. func (account Account) String() string {
  56. return fmt.Sprintf("Account{%v:%X}", account.Id, account.PubKey[:6])
  57. }
  58. //-----------------------------------------------------------------------------
  59. type AccountDetail struct {
  60. Account
  61. Sequence uint
  62. Balance uint64
  63. Status byte
  64. }
  65. func ReadAccountDetail(r io.Reader, n *int64, err *error) *AccountDetail {
  66. return &AccountDetail{
  67. Account: ReadAccount(r, n, err),
  68. Sequence: ReadUVarInt(r, n, err),
  69. Balance: ReadUInt64(r, n, err),
  70. Status: ReadByte(r, n, err),
  71. }
  72. }
  73. func (accDet *AccountDetail) WriteTo(w io.Writer) (n int64, err error) {
  74. WriteBinary(w, accDet.Account, &n, &err)
  75. WriteUVarInt(w, accDet.Sequence, &n, &err)
  76. WriteUInt64(w, accDet.Balance, &n, &err)
  77. WriteByte(w, accDet.Status, &n, &err)
  78. return
  79. }
  80. func (accDet *AccountDetail) String() string {
  81. return fmt.Sprintf("AccountDetail{%v:%X Sequence:%v Balance:%v Status:%X}",
  82. accDet.Id, accDet.PubKey, accDet.Sequence, accDet.Balance, accDet.Status)
  83. }
  84. func (accDet *AccountDetail) Copy() *AccountDetail {
  85. accDetCopy := *accDet
  86. return &accDetCopy
  87. }
  88. //-------------------------------------
  89. var AccountDetailCodec = accountDetailCodec{}
  90. type accountDetailCodec struct{}
  91. func (abc accountDetailCodec) Encode(accDet interface{}, w io.Writer, n *int64, err *error) {
  92. WriteBinary(w, accDet.(*AccountDetail), n, err)
  93. }
  94. func (abc accountDetailCodec) Decode(r io.Reader, n *int64, err *error) interface{} {
  95. return ReadAccountDetail(r, n, err)
  96. }
  97. func (abc accountDetailCodec) Compare(o1 interface{}, o2 interface{}) int {
  98. panic("AccountDetailCodec.Compare not implemented")
  99. }
  100. //-----------------------------------------------------------------------------
  101. type PrivAccount struct {
  102. Account
  103. PrivKey []byte
  104. }
  105. // Generates a new account with private key.
  106. // The Account.Id is empty since it isn't in the blockchain.
  107. func GenPrivAccount() *PrivAccount {
  108. privKey := CRandBytes(32)
  109. pubKey := ed25519.MakePubKey(privKey)
  110. return &PrivAccount{
  111. Account: Account{
  112. Id: uint64(0),
  113. PubKey: pubKey,
  114. },
  115. PrivKey: privKey,
  116. }
  117. }
  118. // The Account.Id is empty since it isn't in the blockchain.
  119. func PrivAccountFromJSON(jsonBlob []byte) (privAccount *PrivAccount) {
  120. err := json.Unmarshal(jsonBlob, &privAccount)
  121. if err != nil {
  122. Panicf("Couldn't read PrivAccount: %v", err)
  123. }
  124. return
  125. }
  126. // The Account.Id is empty since it isn't in the blockchain.
  127. func PrivAccountFromFile(file string) *PrivAccount {
  128. jsonBlob, err := ioutil.ReadFile(file)
  129. if err != nil {
  130. Panicf("Couldn't read PrivAccount from file: %v", err)
  131. }
  132. return PrivAccountFromJSON(jsonBlob)
  133. }
  134. func (pa *PrivAccount) SignBytes(msg []byte) Signature {
  135. signature := ed25519.SignMessage(msg, pa.PrivKey, pa.PubKey)
  136. sig := Signature{
  137. SignerId: pa.Id,
  138. Bytes: signature,
  139. }
  140. return sig
  141. }
  142. func (pa *PrivAccount) Sign(o Signable) {
  143. if !o.GetSignature().IsZero() {
  144. panic("Cannot sign: already signed")
  145. }
  146. msg := BinaryBytes(o)
  147. sig := pa.SignBytes(msg)
  148. o.SetSignature(sig)
  149. }