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.

394 lines
11 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
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. "bytes"
  4. "errors"
  5. "fmt"
  6. "time"
  7. . "github.com/tendermint/tendermint/binary"
  8. . "github.com/tendermint/tendermint/blocks"
  9. . "github.com/tendermint/tendermint/common"
  10. db_ "github.com/tendermint/tendermint/db"
  11. "github.com/tendermint/tendermint/merkle"
  12. )
  13. var (
  14. ErrStateInvalidAccountId = errors.New("Error State invalid account id")
  15. ErrStateInvalidSignature = errors.New("Error State invalid signature")
  16. ErrStateInvalidSequenceNumber = errors.New("Error State invalid sequence number")
  17. ErrStateInvalidAccountState = errors.New("Error State invalid account state")
  18. ErrStateInsufficientFunds = errors.New("Error State insufficient funds")
  19. stateKey = []byte("stateKey")
  20. minBondAmount = uint64(1) // TODO adjust
  21. defaultAccountDetailsCacheCapacity = 1000 // TODO adjust
  22. unbondingPeriodBlocks = uint32(60 * 24 * 365) // TODO probably better to make it time based.
  23. validatorTimeoutBlocks = uint32(10) // TODO adjust
  24. )
  25. //-----------------------------------------------------------------------------
  26. type InvalidTxError struct {
  27. Tx Tx
  28. Reason error
  29. }
  30. func (txErr InvalidTxError) Error() string {
  31. return fmt.Sprintf("Invalid tx: [%v] reason: [%v]", txErr.Tx, txErr.Reason)
  32. }
  33. //-----------------------------------------------------------------------------
  34. // NOTE: not goroutine-safe.
  35. type State struct {
  36. DB db_.DB
  37. Height uint32 // Last known block height
  38. BlockHash []byte // Last known block hash
  39. BlockTime time.Time // LastKnown block time
  40. BondedValidators *ValidatorSet
  41. UnbondingValidators *ValidatorSet
  42. accountDetails merkle.Tree // Shouldn't be accessed directly.
  43. }
  44. func LoadState(db db_.DB) *State {
  45. s := &State{DB: db}
  46. buf := db.Get(stateKey)
  47. if len(buf) == 0 {
  48. return nil
  49. } else {
  50. reader := bytes.NewReader(buf)
  51. var n int64
  52. var err error
  53. s.Height = ReadUInt32(reader, &n, &err)
  54. s.BlockHash = ReadByteSlice(reader, &n, &err)
  55. s.BlockTime = ReadTime(reader, &n, &err)
  56. s.BondedValidators = ReadValidatorSet(reader, &n, &err)
  57. s.UnbondingValidators = ReadValidatorSet(reader, &n, &err)
  58. accountDetailsHash := ReadByteSlice(reader, &n, &err)
  59. s.accountDetails = merkle.NewIAVLTree(BasicCodec, AccountDetailCodec, defaultAccountDetailsCacheCapacity, db)
  60. s.accountDetails.Load(accountDetailsHash)
  61. if err != nil {
  62. panic(err)
  63. }
  64. // TODO: ensure that buf is completely read.
  65. }
  66. return s
  67. }
  68. // Save this state into the db.
  69. func (s *State) Save() {
  70. s.accountDetails.Save()
  71. var buf bytes.Buffer
  72. var n int64
  73. var err error
  74. WriteUInt32(&buf, s.Height, &n, &err)
  75. WriteByteSlice(&buf, s.BlockHash, &n, &err)
  76. WriteTime(&buf, s.BlockTime, &n, &err)
  77. WriteBinary(&buf, s.BondedValidators, &n, &err)
  78. WriteBinary(&buf, s.UnbondingValidators, &n, &err)
  79. WriteByteSlice(&buf, s.accountDetails.Hash(), &n, &err)
  80. if err != nil {
  81. panic(err)
  82. }
  83. s.DB.Set(stateKey, buf.Bytes())
  84. }
  85. func (s *State) Copy() *State {
  86. return &State{
  87. DB: s.DB,
  88. Height: s.Height,
  89. BlockHash: s.BlockHash,
  90. BlockTime: s.BlockTime,
  91. BondedValidators: s.BondedValidators.Copy(),
  92. UnbondingValidators: s.UnbondingValidators.Copy(),
  93. accountDetails: s.accountDetails.Copy(),
  94. }
  95. }
  96. // If the tx is invalid, an error will be returned.
  97. // Unlike AppendBlock(), state will not be altered.
  98. func (s *State) ExecTx(tx Tx) error {
  99. accDet := s.GetAccountDetail(tx.GetSignature().SignerId)
  100. if accDet == nil {
  101. return ErrStateInvalidAccountId
  102. }
  103. // Check signature
  104. if !accDet.Verify(tx) {
  105. return ErrStateInvalidSignature
  106. }
  107. // Check and update sequence
  108. if tx.GetSequence() <= accDet.Sequence {
  109. return ErrStateInvalidSequenceNumber
  110. } else {
  111. // TODO consider prevSequence for tx chaining.
  112. accDet.Sequence = tx.GetSequence()
  113. }
  114. // Subtract fee from balance.
  115. if accDet.Balance < tx.GetFee() {
  116. return ErrStateInsufficientFunds
  117. } else {
  118. accDet.Balance -= tx.GetFee()
  119. }
  120. // Exec tx
  121. switch tx.(type) {
  122. case *SendTx:
  123. stx := tx.(*SendTx)
  124. toAccDet := s.GetAccountDetail(stx.To)
  125. // Accounts must be nominal
  126. if accDet.Status != AccountStatusNominal {
  127. return ErrStateInvalidAccountState
  128. }
  129. if toAccDet.Status != AccountStatusNominal {
  130. return ErrStateInvalidAccountState
  131. }
  132. // Check account balance
  133. if accDet.Balance < stx.Amount {
  134. return ErrStateInsufficientFunds
  135. }
  136. // Check existence of destination account
  137. if toAccDet == nil {
  138. return ErrStateInvalidAccountId
  139. }
  140. // Good!
  141. accDet.Balance -= stx.Amount
  142. toAccDet.Balance += stx.Amount
  143. s.SetAccountDetail(accDet)
  144. s.SetAccountDetail(toAccDet)
  145. return nil
  146. //case *NameTx
  147. case *BondTx:
  148. //btx := tx.(*BondTx)
  149. // Account must be nominal
  150. if accDet.Status != AccountStatusNominal {
  151. return ErrStateInvalidAccountState
  152. }
  153. // Check account balance
  154. if accDet.Balance < minBondAmount {
  155. return ErrStateInsufficientFunds
  156. }
  157. // Good!
  158. accDet.Status = AccountStatusBonded
  159. s.SetAccountDetail(accDet)
  160. added := s.BondedValidators.Add(&Validator{
  161. Account: accDet.Account,
  162. BondHeight: s.Height,
  163. VotingPower: accDet.Balance,
  164. Accum: 0,
  165. })
  166. if !added {
  167. panic("Failed to add validator")
  168. }
  169. return nil
  170. case *UnbondTx:
  171. //utx := tx.(*UnbondTx)
  172. // Account must be bonded.
  173. if accDet.Status != AccountStatusBonded {
  174. return ErrStateInvalidAccountState
  175. }
  176. // Good!
  177. s.unbondValidator(accDet.Id, accDet)
  178. s.SetAccountDetail(accDet)
  179. return nil
  180. case *DupeoutTx:
  181. {
  182. // NOTE: accDet is the one who created this transaction.
  183. // Subtract any fees, save, and forget.
  184. s.SetAccountDetail(accDet)
  185. accDet = nil
  186. }
  187. dtx := tx.(*DupeoutTx)
  188. // Verify the signatures
  189. if dtx.VoteA.SignerId != dtx.VoteB.SignerId {
  190. return ErrStateInvalidSignature
  191. }
  192. accused := s.GetAccountDetail(dtx.VoteA.SignerId)
  193. if !accused.Verify(&dtx.VoteA) || !accused.Verify(&dtx.VoteB) {
  194. return ErrStateInvalidSignature
  195. }
  196. // Verify equivocation
  197. if dtx.VoteA.Height != dtx.VoteB.Height {
  198. return errors.New("DupeoutTx height must be the same.")
  199. }
  200. if dtx.VoteA.Type == VoteTypeCommit && dtx.VoteA.Round < dtx.VoteB.Round {
  201. // Check special case.
  202. // Validators should not sign another vote after committing.
  203. } else {
  204. if dtx.VoteA.Round != dtx.VoteB.Round {
  205. return errors.New("DupeoutTx rounds don't match")
  206. }
  207. if dtx.VoteA.Type != dtx.VoteB.Type {
  208. return errors.New("DupeoutTx types don't match")
  209. }
  210. if bytes.Equal(dtx.VoteA.BlockHash, dtx.VoteB.BlockHash) {
  211. return errors.New("DupeoutTx blockhash shouldn't match")
  212. }
  213. }
  214. // Good! (Bad validator!)
  215. if accused.Status == AccountStatusBonded {
  216. _, removed := s.BondedValidators.Remove(accused.Id)
  217. if !removed {
  218. panic("Failed to remove accused validator")
  219. }
  220. } else if accused.Status == AccountStatusUnbonding {
  221. _, removed := s.UnbondingValidators.Remove(accused.Id)
  222. if !removed {
  223. panic("Failed to remove accused validator")
  224. }
  225. } else {
  226. panic("Couldn't find accused validator")
  227. }
  228. accused.Status = AccountStatusDupedOut
  229. updated := s.SetAccountDetail(accused)
  230. if !updated {
  231. panic("Failed to update accused validator account")
  232. }
  233. return nil
  234. default:
  235. panic("Unknown Tx type")
  236. }
  237. }
  238. // accDet optional
  239. func (s *State) unbondValidator(accountId uint64, accDet *AccountDetail) {
  240. if accDet == nil {
  241. accDet = s.GetAccountDetail(accountId)
  242. }
  243. accDet.Status = AccountStatusUnbonding
  244. s.SetAccountDetail(accDet)
  245. val, removed := s.BondedValidators.Remove(accDet.Id)
  246. if !removed {
  247. panic("Failed to remove validator")
  248. }
  249. val.UnbondHeight = s.Height
  250. added := s.UnbondingValidators.Add(val)
  251. if !added {
  252. panic("Failed to add validator")
  253. }
  254. }
  255. func (s *State) releaseValidator(accountId uint64) {
  256. accDet := s.GetAccountDetail(accountId)
  257. if accDet.Status != AccountStatusUnbonding {
  258. panic("Cannot release validator")
  259. }
  260. accDet.Status = AccountStatusNominal
  261. // TODO: move balance to designated address, UnbondTo.
  262. s.SetAccountDetail(accDet)
  263. _, removed := s.UnbondingValidators.Remove(accountId)
  264. if !removed {
  265. panic("Couldn't release validator")
  266. }
  267. }
  268. // "checkStateHash": If false, instead of checking the resulting
  269. // state.Hash() against block.StateHash, it *sets* the block.StateHash.
  270. // (used for constructing a new proposal)
  271. // NOTE: If an error occurs during block execution, state will be left
  272. // at an invalid state. Copy the state before calling AppendBlock!
  273. func (s *State) AppendBlock(b *Block, checkStateHash bool) error {
  274. // Basic block validation.
  275. err := b.ValidateBasic(s.Height, s.BlockHash)
  276. if err != nil {
  277. return err
  278. }
  279. // Commit each tx
  280. for _, tx := range b.Data.Txs {
  281. err := s.ExecTx(tx)
  282. if err != nil {
  283. return InvalidTxError{tx, err}
  284. }
  285. }
  286. // Update LastCommitHeight as necessary.
  287. for _, sig := range b.Validation.Signatures {
  288. _, val := s.BondedValidators.GetById(sig.SignerId)
  289. if val == nil {
  290. return ErrStateInvalidSignature
  291. }
  292. val.LastCommitHeight = b.Height
  293. updated := s.BondedValidators.Update(val)
  294. if !updated {
  295. panic("Failed to update validator LastCommitHeight")
  296. }
  297. }
  298. // If any unbonding periods are over,
  299. // reward account with bonded coins.
  300. toRelease := []*Validator{}
  301. s.UnbondingValidators.Iterate(func(val *Validator) bool {
  302. if val.UnbondHeight+unbondingPeriodBlocks < b.Height {
  303. toRelease = append(toRelease, val)
  304. }
  305. return false
  306. })
  307. for _, val := range toRelease {
  308. s.releaseValidator(val.Id)
  309. }
  310. // If any validators haven't signed in a while,
  311. // unbond them, they have timed out.
  312. toTimeout := []*Validator{}
  313. s.BondedValidators.Iterate(func(val *Validator) bool {
  314. if val.LastCommitHeight+validatorTimeoutBlocks < b.Height {
  315. toTimeout = append(toTimeout, val)
  316. }
  317. return false
  318. })
  319. for _, val := range toTimeout {
  320. s.unbondValidator(val.Id, nil)
  321. }
  322. // Increment validator AccumPowers
  323. s.BondedValidators.IncrementAccum()
  324. // Check or set block.StateHash
  325. stateHash := s.Hash()
  326. if checkStateHash {
  327. // State hash should match
  328. if !bytes.Equal(stateHash, b.StateHash) {
  329. return Errorf("Invalid state hash. Got %X, block says %X",
  330. stateHash, b.StateHash)
  331. }
  332. } else {
  333. // Set the state hash.
  334. if b.StateHash != nil {
  335. panic("Cannot overwrite block.StateHash")
  336. }
  337. b.StateHash = stateHash
  338. }
  339. s.Height = b.Height
  340. s.BlockHash = b.Hash()
  341. s.BlockTime = b.Time
  342. return nil
  343. }
  344. // The returned AccountDetail is a copy, so mutating it
  345. // has no side effects.
  346. func (s *State) GetAccountDetail(accountId uint64) *AccountDetail {
  347. _, accDet := s.accountDetails.Get(accountId)
  348. if accDet == nil {
  349. return nil
  350. }
  351. return accDet.(*AccountDetail).Copy()
  352. }
  353. // Returns false if new, true if updated.
  354. // The accDet is copied before setting, so mutating it
  355. // afterwards has no side effects.
  356. func (s *State) SetAccountDetail(accDet *AccountDetail) (updated bool) {
  357. return s.accountDetails.Set(accDet.Id, accDet.Copy())
  358. }
  359. // Returns a hash that represents the state data,
  360. // excluding Height, BlockHash.
  361. func (s *State) Hash() []byte {
  362. hashables := []merkle.Hashable{
  363. s.BondedValidators,
  364. s.UnbondingValidators,
  365. s.accountDetails,
  366. }
  367. return merkle.HashFromHashables(hashables)
  368. }