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.

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