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.

304 lines
8.0 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
  1. package state
  2. import (
  3. . "github.com/tendermint/tendermint/blocks"
  4. . "github.com/tendermint/tendermint/common"
  5. . "github.com/tendermint/tendermint/config"
  6. db_ "github.com/tendermint/tendermint/db"
  7. "bytes"
  8. "testing"
  9. "time"
  10. )
  11. func randAccountDetail(id uint64, status byte) (*AccountDetail, *PrivAccount) {
  12. privAccount := GenPrivAccount()
  13. privAccount.Id = id
  14. account := privAccount.Account
  15. return &AccountDetail{
  16. Account: account,
  17. Sequence: RandUInt(),
  18. Balance: RandUInt64() + 1000, // At least 1000.
  19. Status: status,
  20. }, privAccount
  21. }
  22. // The first numValidators accounts are validators.
  23. func randGenesisState(numAccounts int, numValidators int) (*State, []*PrivAccount) {
  24. db := db_.NewMemDB()
  25. accountDetails := make([]*AccountDetail, numAccounts)
  26. privAccounts := make([]*PrivAccount, numAccounts)
  27. for i := 0; i < numAccounts; i++ {
  28. if i < numValidators {
  29. accountDetails[i], privAccounts[i] =
  30. randAccountDetail(uint64(i), AccountStatusBonded)
  31. } else {
  32. accountDetails[i], privAccounts[i] =
  33. randAccountDetail(uint64(i), AccountStatusNominal)
  34. }
  35. }
  36. s0 := GenesisState(db, time.Now(), accountDetails)
  37. s0.Save()
  38. return s0, privAccounts
  39. }
  40. func TestCopyState(t *testing.T) {
  41. // Generate a state
  42. s0, _ := randGenesisState(10, 5)
  43. s0Hash := s0.Hash()
  44. if len(s0Hash) == 0 {
  45. t.Error("Expected state hash")
  46. }
  47. // Check hash of copy
  48. s0Copy := s0.Copy()
  49. if !bytes.Equal(s0Hash, s0Copy.Hash()) {
  50. t.Error("Expected state copy hash to be the same")
  51. }
  52. // Mutate the original; hash should change.
  53. accDet := s0.GetAccountDetail(0)
  54. accDet.Balance += 1
  55. // The account balance shouldn't have changed yet.
  56. if s0.GetAccountDetail(0).Balance == accDet.Balance {
  57. t.Error("Account balance changed unexpectedly")
  58. }
  59. // Setting, however, should change the balance.
  60. s0.SetAccountDetail(accDet)
  61. if s0.GetAccountDetail(0).Balance != accDet.Balance {
  62. t.Error("Account balance wasn't set")
  63. }
  64. // How that the state changed, the hash should change too.
  65. if bytes.Equal(s0Hash, s0.Hash()) {
  66. t.Error("Expected state hash to have changed")
  67. }
  68. // The s0Copy shouldn't have changed though.
  69. if !bytes.Equal(s0Hash, s0Copy.Hash()) {
  70. t.Error("Expected state copy hash to have not changed")
  71. }
  72. }
  73. func TestGenesisSaveLoad(t *testing.T) {
  74. // Generate a state, save & load it.
  75. s0, _ := randGenesisState(10, 5)
  76. // Mutate the state to append one empty block.
  77. block := &Block{
  78. Header: Header{
  79. Network: Config.Network,
  80. Height: 1,
  81. StateHash: nil,
  82. },
  83. Data: Data{
  84. Txs: []Tx{},
  85. },
  86. }
  87. // The second argument to AppendBlock() is false,
  88. // which sets Block.Header.StateHash.
  89. err := s0.Copy().AppendBlock(block, false)
  90. if err != nil {
  91. t.Error("Error appending initial block:", err)
  92. }
  93. if len(block.Header.StateHash) == 0 {
  94. t.Error("Expected StateHash but got nothing.")
  95. }
  96. // Now append the block to s0.
  97. // This time we also check the StateHash (as computed above).
  98. err = s0.AppendBlock(block, true)
  99. if err != nil {
  100. t.Error("Error appending initial block:", err)
  101. }
  102. // Save s0
  103. s0.Save()
  104. // Sanity check s0
  105. //s0.DB.(*db_.MemDB).Print()
  106. if s0.BondedValidators.TotalVotingPower() == 0 {
  107. t.Error("s0 BondedValidators TotalVotingPower should not be 0")
  108. }
  109. if s0.Height != 1 {
  110. t.Error("s0 Height should be 1, got", s0.Height)
  111. }
  112. // Load s1
  113. s1 := LoadState(s0.DB)
  114. // Compare height & blockHash
  115. if s0.Height != s1.Height {
  116. t.Error("Height mismatch")
  117. }
  118. if !bytes.Equal(s0.BlockHash, s1.BlockHash) {
  119. t.Error("BlockHash mismatch")
  120. }
  121. // Compare state merkle trees
  122. if s0.BondedValidators.Size() != s1.BondedValidators.Size() {
  123. t.Error("BondedValidators Size mismatch")
  124. }
  125. if s0.BondedValidators.TotalVotingPower() != s1.BondedValidators.TotalVotingPower() {
  126. t.Error("BondedValidators TotalVotingPower mismatch")
  127. }
  128. if bytes.Equal(s0.BondedValidators.Hash(), s1.BondedValidators.Hash()) {
  129. // The BondedValidators hash should have changed because
  130. // each AppendBlock() calls IncrementAccum(),
  131. // changing each validator's Accum.
  132. t.Error("BondedValidators hash should have changed")
  133. }
  134. if s0.UnbondingValidators.Size() != s1.UnbondingValidators.Size() {
  135. t.Error("UnbondingValidators Size mismatch")
  136. }
  137. if s0.UnbondingValidators.TotalVotingPower() != s1.UnbondingValidators.TotalVotingPower() {
  138. t.Error("UnbondingValidators TotalVotingPower mismatch")
  139. }
  140. if !bytes.Equal(s0.UnbondingValidators.Hash(), s1.UnbondingValidators.Hash()) {
  141. t.Error("UnbondingValidators hash mismatch")
  142. }
  143. if !bytes.Equal(s0.accountDetails.Hash(), s1.accountDetails.Hash()) {
  144. t.Error("AccountDetail mismatch")
  145. }
  146. }
  147. func TestTxSequence(t *testing.T) {
  148. state, privAccounts := randGenesisState(3, 1)
  149. acc1 := state.GetAccountDetail(1) // Non-validator
  150. // Try executing a SendTx with various sequence numbers.
  151. stx := &SendTx{
  152. BaseTx: BaseTx{
  153. Sequence: acc1.Sequence + 1,
  154. Fee: 0},
  155. To: 2,
  156. Amount: 1,
  157. }
  158. // Test a variety of sequence numbers for the tx.
  159. // The tx should only pass when i == 1.
  160. for i := -1; i < 3; i++ {
  161. stx.Sequence = uint(int(acc1.Sequence) + i)
  162. privAccounts[1].Sign(stx)
  163. stateCopy := state.Copy()
  164. err := stateCopy.ExecTx(stx)
  165. if i >= 1 {
  166. // Sequence is good.
  167. if err != nil {
  168. t.Errorf("Expected good sequence to pass")
  169. }
  170. // Check accDet.Sequence.
  171. newAcc1 := stateCopy.GetAccountDetail(1)
  172. if newAcc1.Sequence != stx.Sequence {
  173. t.Errorf("Expected account sequence to change")
  174. }
  175. } else {
  176. // Sequence is bad.
  177. if err == nil {
  178. t.Errorf("Expected bad sequence to fail")
  179. }
  180. // Check accDet.Sequence. (shouldn't have changed)
  181. newAcc1 := stateCopy.GetAccountDetail(1)
  182. if newAcc1.Sequence != acc1.Sequence {
  183. t.Errorf("Expected account sequence to not change")
  184. }
  185. }
  186. }
  187. }
  188. func TestTxs(t *testing.T) {
  189. state, privAccounts := randGenesisState(3, 1)
  190. acc0 := state.GetAccountDetail(0) // Validator
  191. acc1 := state.GetAccountDetail(1) // Non-validator
  192. acc2 := state.GetAccountDetail(2) // Non-validator
  193. // SendTx.
  194. {
  195. state := state.Copy()
  196. stx := &SendTx{
  197. BaseTx: BaseTx{
  198. Sequence: acc1.Sequence + 1,
  199. Fee: 0},
  200. To: 2,
  201. Amount: 1,
  202. }
  203. privAccounts[1].Sign(stx)
  204. err := state.ExecTx(stx)
  205. if err != nil {
  206. t.Errorf("Got error in executing send transaction, %v", err)
  207. }
  208. newAcc1 := state.GetAccountDetail(1)
  209. if acc1.Balance-1 != newAcc1.Balance {
  210. t.Errorf("Unexpected newAcc1 balance. Expected %v, got %v",
  211. acc1.Balance-1, newAcc1.Balance)
  212. }
  213. newAcc2 := state.GetAccountDetail(2)
  214. if acc2.Balance+1 != newAcc2.Balance {
  215. t.Errorf("Unexpected newAcc2 balance. Expected %v, got %v",
  216. acc2.Balance+1, newAcc2.Balance)
  217. }
  218. }
  219. // TODO: test overflows.
  220. // SendTx should fail for bonded validators.
  221. {
  222. state := state.Copy()
  223. stx := &SendTx{
  224. BaseTx: BaseTx{
  225. Sequence: acc0.Sequence + 1,
  226. Fee: 0},
  227. To: 2,
  228. Amount: 1,
  229. }
  230. privAccounts[0].Sign(stx)
  231. err := state.ExecTx(stx)
  232. if err == nil {
  233. t.Errorf("Expected error, SendTx should fail for bonded validators")
  234. }
  235. }
  236. // TODO: test for unbonding validators.
  237. // BondTx.
  238. {
  239. state := state.Copy()
  240. btx := &BondTx{
  241. BaseTx: BaseTx{
  242. Sequence: acc1.Sequence + 1,
  243. Fee: 0},
  244. }
  245. privAccounts[1].Sign(btx)
  246. err := state.ExecTx(btx)
  247. if err != nil {
  248. t.Errorf("Got error in executing bond transaction, %v", err)
  249. }
  250. newAcc1 := state.GetAccountDetail(1)
  251. if acc1.Balance != newAcc1.Balance {
  252. t.Errorf("Unexpected newAcc1 balance. Expected %v, got %v",
  253. acc1.Balance, newAcc1.Balance)
  254. }
  255. if newAcc1.Status != AccountStatusBonded {
  256. t.Errorf("Unexpected newAcc1 status.")
  257. }
  258. _, acc1Val := state.BondedValidators.GetById(acc1.Id)
  259. if acc1Val == nil {
  260. t.Errorf("acc1Val not present")
  261. }
  262. if acc1Val.BondHeight != state.Height {
  263. t.Errorf("Unexpected bond height. Expected %v, got %v",
  264. state.Height, acc1Val.BondHeight)
  265. }
  266. if acc1Val.VotingPower != acc1.Balance {
  267. t.Errorf("Unexpected voting power. Expected %v, got %v",
  268. acc1Val.VotingPower, acc1.Balance)
  269. }
  270. if acc1Val.Accum != 0 {
  271. t.Errorf("Unexpected accum. Expected 0, got %v",
  272. acc1Val.Accum)
  273. }
  274. }
  275. // TODO UnbondTx.
  276. // TODO NameTx.
  277. }