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.

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