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.

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