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.

725 lines
22 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
  1. package state
  2. import (
  3. "bytes"
  4. "errors"
  5. "fmt"
  6. "github.com/tendermint/tendermint/account"
  7. . "github.com/tendermint/tendermint/common"
  8. "github.com/tendermint/tendermint/events"
  9. "github.com/tendermint/tendermint/types"
  10. "github.com/tendermint/tendermint/vm"
  11. )
  12. // NOTE: If an error occurs during block execution, state will be left
  13. // at an invalid state. Copy the state before calling ExecBlock!
  14. func ExecBlock(s *State, block *types.Block, blockPartsHeader types.PartSetHeader) error {
  15. err := execBlock(s, block, blockPartsHeader)
  16. if err != nil {
  17. return err
  18. }
  19. // State.Hash should match block.StateHash
  20. stateHash := s.Hash()
  21. if !bytes.Equal(stateHash, block.StateHash) {
  22. return fmt.Errorf("Invalid state hash. Expected %X, got %X",
  23. stateHash, block.StateHash)
  24. }
  25. return nil
  26. }
  27. // executes transactions of a block, does not check block.StateHash
  28. // NOTE: If an error occurs during block execution, state will be left
  29. // at an invalid state. Copy the state before calling execBlock!
  30. func execBlock(s *State, block *types.Block, blockPartsHeader types.PartSetHeader) error {
  31. // Basic block validation.
  32. err := block.ValidateBasic(s.ChainID, s.LastBlockHeight, s.LastBlockHash, s.LastBlockParts, s.LastBlockTime)
  33. if err != nil {
  34. return err
  35. }
  36. // Validate block LastValidation.
  37. if block.Height == 1 {
  38. if len(block.LastValidation.Precommits) != 0 {
  39. return errors.New("Block at height 1 (first block) should have no LastValidation precommits")
  40. }
  41. } else {
  42. if uint(len(block.LastValidation.Precommits)) != s.LastBondedValidators.Size() {
  43. return errors.New(Fmt("Invalid block validation size. Expected %v, got %v",
  44. s.LastBondedValidators.Size(), len(block.LastValidation.Precommits)))
  45. }
  46. err := s.LastBondedValidators.VerifyValidation(
  47. s.ChainID, s.LastBlockHash, s.LastBlockParts, block.Height-1, block.LastValidation)
  48. if err != nil {
  49. return err
  50. }
  51. }
  52. // Update Validator.LastCommitHeight as necessary.
  53. for i, precommit := range block.LastValidation.Precommits {
  54. if precommit == nil {
  55. continue
  56. }
  57. _, val := s.LastBondedValidators.GetByIndex(uint(i))
  58. if val == nil {
  59. panic(Fmt("Failed to fetch validator at index %v", i))
  60. }
  61. if _, val_ := s.BondedValidators.GetByAddress(val.Address); val_ != nil {
  62. val_.LastCommitHeight = block.Height - 1
  63. updated := s.BondedValidators.Update(val_)
  64. if !updated {
  65. panic("Failed to update bonded validator LastCommitHeight")
  66. }
  67. } else if _, val_ := s.UnbondingValidators.GetByAddress(val.Address); val_ != nil {
  68. val_.LastCommitHeight = block.Height - 1
  69. updated := s.UnbondingValidators.Update(val_)
  70. if !updated {
  71. panic("Failed to update unbonding validator LastCommitHeight")
  72. }
  73. } else {
  74. panic("Could not find validator")
  75. }
  76. }
  77. // Remember LastBondedValidators
  78. s.LastBondedValidators = s.BondedValidators.Copy()
  79. // Create BlockCache to cache changes to state.
  80. blockCache := NewBlockCache(s)
  81. // Execute each tx
  82. for _, tx := range block.Data.Txs {
  83. err := ExecTx(blockCache, tx, true, s.evc)
  84. if err != nil {
  85. return InvalidTxError{tx, err}
  86. }
  87. }
  88. // Now sync the BlockCache to the backend.
  89. blockCache.Sync()
  90. // If any unbonding periods are over,
  91. // reward account with bonded coins.
  92. toRelease := []*Validator{}
  93. s.UnbondingValidators.Iterate(func(index uint, val *Validator) bool {
  94. if val.UnbondHeight+unbondingPeriodBlocks < block.Height {
  95. toRelease = append(toRelease, val)
  96. }
  97. return false
  98. })
  99. for _, val := range toRelease {
  100. s.releaseValidator(val)
  101. }
  102. // If any validators haven't signed in a while,
  103. // unbond them, they have timed out.
  104. toTimeout := []*Validator{}
  105. s.BondedValidators.Iterate(func(index uint, val *Validator) bool {
  106. lastActivityHeight := MaxUint(val.BondHeight, val.LastCommitHeight)
  107. if lastActivityHeight+validatorTimeoutBlocks < block.Height {
  108. log.Info("Validator timeout", "validator", val, "height", block.Height)
  109. toTimeout = append(toTimeout, val)
  110. }
  111. return false
  112. })
  113. for _, val := range toTimeout {
  114. s.unbondValidator(val)
  115. }
  116. // Increment validator AccumPowers
  117. s.BondedValidators.IncrementAccum(1)
  118. s.LastBlockHeight = block.Height
  119. s.LastBlockHash = block.Hash()
  120. s.LastBlockParts = blockPartsHeader
  121. s.LastBlockTime = block.Time
  122. return nil
  123. }
  124. // The accounts from the TxInputs must either already have
  125. // account.PubKey.(type) != nil, (it must be known),
  126. // or it must be specified in the TxInput. If redeclared,
  127. // the TxInput is modified and input.PubKey set to nil.
  128. func getOrMakeAccounts(state AccountGetter, ins []*types.TxInput, outs []*types.TxOutput) (map[string]*account.Account, error) {
  129. accounts := map[string]*account.Account{}
  130. for _, in := range ins {
  131. // Account shouldn't be duplicated
  132. if _, ok := accounts[string(in.Address)]; ok {
  133. return nil, types.ErrTxDuplicateAddress
  134. }
  135. acc := state.GetAccount(in.Address)
  136. if acc == nil {
  137. return nil, types.ErrTxInvalidAddress
  138. }
  139. // PubKey should be present in either "account" or "in"
  140. if err := checkInputPubKey(acc, in); err != nil {
  141. return nil, err
  142. }
  143. accounts[string(in.Address)] = acc
  144. }
  145. for _, out := range outs {
  146. // Account shouldn't be duplicated
  147. if _, ok := accounts[string(out.Address)]; ok {
  148. return nil, types.ErrTxDuplicateAddress
  149. }
  150. acc := state.GetAccount(out.Address)
  151. // output account may be nil (new)
  152. if acc == nil {
  153. acc = &account.Account{
  154. Address: out.Address,
  155. PubKey: nil,
  156. Sequence: 0,
  157. Balance: 0,
  158. }
  159. }
  160. accounts[string(out.Address)] = acc
  161. }
  162. return accounts, nil
  163. }
  164. func checkInputPubKey(acc *account.Account, in *types.TxInput) error {
  165. if acc.PubKey == nil {
  166. if in.PubKey == nil {
  167. return types.ErrTxUnknownPubKey
  168. }
  169. if !bytes.Equal(in.PubKey.Address(), acc.Address) {
  170. return types.ErrTxInvalidPubKey
  171. }
  172. acc.PubKey = in.PubKey
  173. } else {
  174. in.PubKey = nil
  175. }
  176. return nil
  177. }
  178. func validateInputs(accounts map[string]*account.Account, signBytes []byte, ins []*types.TxInput) (total uint64, err error) {
  179. for _, in := range ins {
  180. acc := accounts[string(in.Address)]
  181. if acc == nil {
  182. panic("validateInputs() expects account in accounts")
  183. }
  184. err = validateInput(acc, signBytes, in)
  185. if err != nil {
  186. return
  187. }
  188. // Good. Add amount to total
  189. total += in.Amount
  190. }
  191. return total, nil
  192. }
  193. func validateInput(acc *account.Account, signBytes []byte, in *types.TxInput) (err error) {
  194. // Check TxInput basic
  195. if err := in.ValidateBasic(); err != nil {
  196. return err
  197. }
  198. // Check signatures
  199. if !acc.PubKey.VerifyBytes(signBytes, in.Signature) {
  200. return types.ErrTxInvalidSignature
  201. }
  202. // Check sequences
  203. if acc.Sequence+1 != in.Sequence {
  204. return types.ErrTxInvalidSequence{
  205. Got: uint64(in.Sequence),
  206. Expected: uint64(acc.Sequence + 1),
  207. }
  208. }
  209. // Check amount
  210. if acc.Balance < in.Amount {
  211. return types.ErrTxInsufficientFunds
  212. }
  213. return nil
  214. }
  215. func validateOutputs(outs []*types.TxOutput) (total uint64, err error) {
  216. for _, out := range outs {
  217. // Check TxOutput basic
  218. if err := out.ValidateBasic(); err != nil {
  219. return 0, err
  220. }
  221. // Good. Add amount to total
  222. total += out.Amount
  223. }
  224. return total, nil
  225. }
  226. func adjustByInputs(accounts map[string]*account.Account, ins []*types.TxInput) {
  227. for _, in := range ins {
  228. acc := accounts[string(in.Address)]
  229. if acc == nil {
  230. panic("adjustByInputs() expects account in accounts")
  231. }
  232. if acc.Balance < in.Amount {
  233. panic("adjustByInputs() expects sufficient funds")
  234. }
  235. acc.Balance -= in.Amount
  236. acc.Sequence += 1
  237. }
  238. }
  239. func adjustByOutputs(accounts map[string]*account.Account, outs []*types.TxOutput) {
  240. for _, out := range outs {
  241. acc := accounts[string(out.Address)]
  242. if acc == nil {
  243. panic("adjustByOutputs() expects account in accounts")
  244. }
  245. acc.Balance += out.Amount
  246. }
  247. }
  248. // If the tx is invalid, an error will be returned.
  249. // Unlike ExecBlock(), state will not be altered.
  250. func ExecTx(blockCache *BlockCache, tx_ types.Tx, runCall bool, evc events.Fireable) error {
  251. // TODO: do something with fees
  252. fees := uint64(0)
  253. _s := blockCache.State() // hack to access validators and block height
  254. // Exec tx
  255. switch tx := tx_.(type) {
  256. case *types.SendTx:
  257. accounts, err := getOrMakeAccounts(blockCache, tx.Inputs, tx.Outputs)
  258. if err != nil {
  259. return err
  260. }
  261. signBytes := account.SignBytes(_s.ChainID, tx)
  262. inTotal, err := validateInputs(accounts, signBytes, tx.Inputs)
  263. if err != nil {
  264. return err
  265. }
  266. outTotal, err := validateOutputs(tx.Outputs)
  267. if err != nil {
  268. return err
  269. }
  270. if outTotal > inTotal {
  271. return types.ErrTxInsufficientFunds
  272. }
  273. fee := inTotal - outTotal
  274. fees += fee
  275. // Good! Adjust accounts
  276. adjustByInputs(accounts, tx.Inputs)
  277. adjustByOutputs(accounts, tx.Outputs)
  278. for _, acc := range accounts {
  279. blockCache.UpdateAccount(acc)
  280. }
  281. // if the evc is nil, nothing will happen
  282. if evc != nil {
  283. for _, i := range tx.Inputs {
  284. evc.FireEvent(types.EventStringAccInput(i.Address), tx)
  285. }
  286. for _, o := range tx.Outputs {
  287. evc.FireEvent(types.EventStringAccOutput(o.Address), tx)
  288. }
  289. }
  290. return nil
  291. case *types.CallTx:
  292. var inAcc, outAcc *account.Account
  293. // Validate input
  294. inAcc = blockCache.GetAccount(tx.Input.Address)
  295. if inAcc == nil {
  296. log.Debug(Fmt("Can't find in account %X", tx.Input.Address))
  297. return types.ErrTxInvalidAddress
  298. }
  299. // pubKey should be present in either "inAcc" or "tx.Input"
  300. if err := checkInputPubKey(inAcc, tx.Input); err != nil {
  301. log.Debug(Fmt("Can't find pubkey for %X", tx.Input.Address))
  302. return err
  303. }
  304. signBytes := account.SignBytes(_s.ChainID, tx)
  305. err := validateInput(inAcc, signBytes, tx.Input)
  306. if err != nil {
  307. log.Debug(Fmt("validateInput failed on %X: %v", tx.Input.Address, err))
  308. return err
  309. }
  310. if tx.Input.Amount < tx.Fee {
  311. log.Debug(Fmt("Sender did not send enough to cover the fee %X", tx.Input.Address))
  312. return types.ErrTxInsufficientFunds
  313. }
  314. createAccount := len(tx.Address) == 0
  315. if !createAccount {
  316. // Validate output
  317. if len(tx.Address) != 20 {
  318. log.Debug(Fmt("Destination address is not 20 bytes %X", tx.Address))
  319. return types.ErrTxInvalidAddress
  320. }
  321. // this may be nil if we are still in mempool and contract was created in same block as this tx
  322. // but that's fine, because the account will be created properly when the create tx runs in the block
  323. // and then this won't return nil. otherwise, we take their fee
  324. outAcc = blockCache.GetAccount(tx.Address)
  325. }
  326. log.Debug(Fmt("Out account: %v", outAcc))
  327. // Good!
  328. value := tx.Input.Amount - tx.Fee
  329. inAcc.Sequence += 1
  330. if runCall {
  331. var (
  332. gas uint64 = tx.GasLimit
  333. err error = nil
  334. caller *vm.Account = toVMAccount(inAcc)
  335. callee *vm.Account = nil
  336. code []byte = nil
  337. txCache = NewTxCache(blockCache)
  338. params = vm.Params{
  339. BlockHeight: uint64(_s.LastBlockHeight),
  340. BlockHash: LeftPadWord256(_s.LastBlockHash),
  341. BlockTime: _s.LastBlockTime.Unix(),
  342. GasLimit: 10000000,
  343. }
  344. )
  345. // Maybe create a new callee account if
  346. // this transaction is creating a new contract.
  347. if !createAccount {
  348. if outAcc == nil || len(outAcc.Code) == 0 {
  349. // if you call an account that doesn't exist
  350. // or an account with no code then we take fees (sorry pal)
  351. // NOTE: it's fine to create a contract and call it within one
  352. // block (nonce will prevent re-ordering of those txs)
  353. // but to create with one account and call with another
  354. // you have to wait a block to avoid a re-ordering attack
  355. // that will take your fees
  356. inAcc.Balance -= tx.Fee
  357. blockCache.UpdateAccount(inAcc)
  358. if outAcc == nil {
  359. log.Debug(Fmt("Cannot find destination address %X. Deducting fee from caller", tx.Address))
  360. } else {
  361. log.Debug(Fmt("Attempting to call an account (%X) with no code. Deducting fee from caller", tx.Address))
  362. }
  363. return types.ErrTxInvalidAddress
  364. }
  365. callee = toVMAccount(outAcc)
  366. code = callee.Code
  367. log.Debug(Fmt("Calling contract %X with code %X", callee.Address, callee.Code))
  368. } else {
  369. callee = txCache.CreateAccount(caller)
  370. log.Debug(Fmt("Created new account %X", callee.Address))
  371. code = tx.Data
  372. }
  373. log.Debug(Fmt("Code for this contract: %X", code))
  374. txCache.UpdateAccount(caller) // because we adjusted by input above, and bumped nonce maybe.
  375. txCache.UpdateAccount(callee) // because we adjusted by input above.
  376. vmach := vm.NewVM(txCache, params, caller.Address, account.HashSignBytes(_s.ChainID, tx))
  377. vmach.SetFireable(evc)
  378. // NOTE: Call() transfers the value from caller to callee iff call succeeds.
  379. ret, err := vmach.Call(caller, callee, code, tx.Data, value, &gas)
  380. exception := ""
  381. if err != nil {
  382. exception = err.Error()
  383. // Failure. Charge the gas fee. The 'value' was otherwise not transferred.
  384. log.Debug(Fmt("Error on execution: %v", err))
  385. inAcc.Balance -= tx.Fee
  386. blockCache.UpdateAccount(inAcc)
  387. // Throw away 'txCache' which holds incomplete updates (don't sync it).
  388. } else {
  389. log.Debug("Successful execution")
  390. // Success
  391. if createAccount {
  392. callee.Code = ret
  393. }
  394. txCache.Sync()
  395. }
  396. // Create a receipt from the ret and whether errored.
  397. log.Info("VM call complete", "caller", caller, "callee", callee, "return", ret, "err", err)
  398. // Fire Events for sender and receiver
  399. // a separate event will be fired from vm for each additional call
  400. if evc != nil {
  401. evc.FireEvent(types.EventStringAccInput(tx.Input.Address), types.EventMsgCallTx{tx, ret, exception})
  402. evc.FireEvent(types.EventStringAccOutput(tx.Address), types.EventMsgCallTx{tx, ret, exception})
  403. }
  404. } else {
  405. // The mempool does not call txs until
  406. // the proposer determines the order of txs.
  407. // So mempool will skip the actual .Call(),
  408. // and only deduct from the caller's balance.
  409. inAcc.Balance -= value
  410. if createAccount {
  411. inAcc.Sequence += 1
  412. }
  413. blockCache.UpdateAccount(inAcc)
  414. }
  415. return nil
  416. case *types.NameTx:
  417. var inAcc *account.Account
  418. // Validate input
  419. inAcc = blockCache.GetAccount(tx.Input.Address)
  420. if inAcc == nil {
  421. log.Debug(Fmt("Can't find in account %X", tx.Input.Address))
  422. return types.ErrTxInvalidAddress
  423. }
  424. // pubKey should be present in either "inAcc" or "tx.Input"
  425. if err := checkInputPubKey(inAcc, tx.Input); err != nil {
  426. log.Debug(Fmt("Can't find pubkey for %X", tx.Input.Address))
  427. return err
  428. }
  429. signBytes := account.SignBytes(_s.ChainID, tx)
  430. err := validateInput(inAcc, signBytes, tx.Input)
  431. if err != nil {
  432. log.Debug(Fmt("validateInput failed on %X: %v", tx.Input.Address, err))
  433. return err
  434. }
  435. // fee is in addition to the amount which is used to determine the TTL
  436. if tx.Input.Amount < tx.Fee {
  437. log.Debug(Fmt("Sender did not send enough to cover the fee %X", tx.Input.Address))
  438. return types.ErrTxInsufficientFunds
  439. }
  440. // validate the input strings
  441. if err := tx.ValidateStrings(); err != nil {
  442. log.Debug(err.Error())
  443. return types.ErrTxInvalidString
  444. }
  445. value := tx.Input.Amount - tx.Fee
  446. // let's say cost of a name for one block is len(data) + 32
  447. costPerBlock := types.NameCostPerBlock * types.NameCostPerByte * tx.BaseEntryCost()
  448. expiresIn := value / uint64(costPerBlock)
  449. lastBlockHeight := uint64(_s.LastBlockHeight)
  450. log.Debug("New NameTx", "value", value, "costPerBlock", costPerBlock, "expiresIn", expiresIn, "lastBlock", lastBlockHeight)
  451. // check if the name exists
  452. entry := blockCache.GetNameRegEntry(tx.Name)
  453. if entry != nil {
  454. var expired bool
  455. // if the entry already exists, and hasn't expired, we must be owner
  456. if entry.Expires > lastBlockHeight {
  457. // ensure we are owner
  458. if bytes.Compare(entry.Owner, tx.Input.Address) != 0 {
  459. log.Debug(Fmt("Sender %X is trying to update a name (%s) for which he is not owner", tx.Input.Address, tx.Name))
  460. return types.ErrIncorrectOwner
  461. }
  462. } else {
  463. expired = true
  464. }
  465. // no value and empty data means delete the entry
  466. if value == 0 && len(tx.Data) == 0 {
  467. // maybe we reward you for telling us we can delete this crap
  468. // (owners if not expired, anyone if expired)
  469. log.Debug("Removing namereg entry", "name", entry.Name)
  470. blockCache.RemoveNameRegEntry(entry.Name)
  471. } else {
  472. // update the entry by bumping the expiry
  473. // and changing the data
  474. if expired {
  475. if expiresIn < types.MinNameRegistrationPeriod {
  476. return fmt.Errorf("Names must be registered for at least %d blocks", types.MinNameRegistrationPeriod)
  477. }
  478. entry.Expires = lastBlockHeight + expiresIn
  479. entry.Owner = tx.Input.Address
  480. log.Debug("An old namereg entry has expired and been reclaimed", "name", entry.Name, "expiresIn", expiresIn, "owner", entry.Owner)
  481. } else {
  482. // since the size of the data may have changed
  483. // we use the total amount of "credit"
  484. oldCredit := (entry.Expires - lastBlockHeight) * types.BaseEntryCost(entry.Name, entry.Data)
  485. credit := oldCredit + value
  486. expiresIn = credit / costPerBlock
  487. if expiresIn < types.MinNameRegistrationPeriod {
  488. return fmt.Errorf("Names must be registered for at least %d blocks", types.MinNameRegistrationPeriod)
  489. }
  490. entry.Expires = lastBlockHeight + expiresIn
  491. log.Debug("Updated namereg entry", "name", entry.Name, "expiresIn", expiresIn, "oldCredit", oldCredit, "value", value, "credit", credit)
  492. }
  493. entry.Data = tx.Data
  494. blockCache.UpdateNameRegEntry(entry)
  495. }
  496. } else {
  497. if expiresIn < types.MinNameRegistrationPeriod {
  498. return fmt.Errorf("Names must be registered for at least %d blocks", types.MinNameRegistrationPeriod)
  499. }
  500. // entry does not exist, so create it
  501. entry = &types.NameRegEntry{
  502. Name: tx.Name,
  503. Owner: tx.Input.Address,
  504. Data: tx.Data,
  505. Expires: lastBlockHeight + expiresIn,
  506. }
  507. log.Debug("Creating namereg entry", "name", entry.Name, "expiresIn", expiresIn)
  508. blockCache.UpdateNameRegEntry(entry)
  509. }
  510. // TODO: something with the value sent?
  511. // Good!
  512. inAcc.Sequence += 1
  513. inAcc.Balance -= value
  514. blockCache.UpdateAccount(inAcc)
  515. // TODO: maybe we want to take funds on error and allow txs in that don't do anythingi?
  516. return nil
  517. case *types.BondTx:
  518. valInfo := blockCache.State().GetValidatorInfo(tx.PubKey.Address())
  519. if valInfo != nil {
  520. // TODO: In the future, check that the validator wasn't destroyed,
  521. // add funds, merge UnbondTo outputs, and unbond validator.
  522. return errors.New("Adding coins to existing validators not yet supported")
  523. }
  524. accounts, err := getOrMakeAccounts(blockCache, tx.Inputs, nil)
  525. if err != nil {
  526. return err
  527. }
  528. signBytes := account.SignBytes(_s.ChainID, tx)
  529. inTotal, err := validateInputs(accounts, signBytes, tx.Inputs)
  530. if err != nil {
  531. return err
  532. }
  533. if err := tx.PubKey.ValidateBasic(); err != nil {
  534. return err
  535. }
  536. if !tx.PubKey.VerifyBytes(signBytes, tx.Signature) {
  537. return types.ErrTxInvalidSignature
  538. }
  539. outTotal, err := validateOutputs(tx.UnbondTo)
  540. if err != nil {
  541. return err
  542. }
  543. if outTotal > inTotal {
  544. return types.ErrTxInsufficientFunds
  545. }
  546. fee := inTotal - outTotal
  547. fees += fee
  548. // Good! Adjust accounts
  549. adjustByInputs(accounts, tx.Inputs)
  550. for _, acc := range accounts {
  551. blockCache.UpdateAccount(acc)
  552. }
  553. // Add ValidatorInfo
  554. _s.SetValidatorInfo(&ValidatorInfo{
  555. Address: tx.PubKey.Address(),
  556. PubKey: tx.PubKey,
  557. UnbondTo: tx.UnbondTo,
  558. FirstBondHeight: _s.LastBlockHeight + 1,
  559. FirstBondAmount: outTotal,
  560. })
  561. // Add Validator
  562. added := _s.BondedValidators.Add(&Validator{
  563. Address: tx.PubKey.Address(),
  564. PubKey: tx.PubKey,
  565. BondHeight: _s.LastBlockHeight + 1,
  566. VotingPower: outTotal,
  567. Accum: 0,
  568. })
  569. if !added {
  570. panic("Failed to add validator")
  571. }
  572. if evc != nil {
  573. evc.FireEvent(types.EventStringBond(), tx)
  574. }
  575. return nil
  576. case *types.UnbondTx:
  577. // The validator must be active
  578. _, val := _s.BondedValidators.GetByAddress(tx.Address)
  579. if val == nil {
  580. return types.ErrTxInvalidAddress
  581. }
  582. // Verify the signature
  583. signBytes := account.SignBytes(_s.ChainID, tx)
  584. if !val.PubKey.VerifyBytes(signBytes, tx.Signature) {
  585. return types.ErrTxInvalidSignature
  586. }
  587. // tx.Height must be greater than val.LastCommitHeight
  588. if tx.Height <= val.LastCommitHeight {
  589. return errors.New("Invalid unbond height")
  590. }
  591. // Good!
  592. _s.unbondValidator(val)
  593. if evc != nil {
  594. evc.FireEvent(types.EventStringUnbond(), tx)
  595. }
  596. return nil
  597. case *types.RebondTx:
  598. // The validator must be inactive
  599. _, val := _s.UnbondingValidators.GetByAddress(tx.Address)
  600. if val == nil {
  601. return types.ErrTxInvalidAddress
  602. }
  603. // Verify the signature
  604. signBytes := account.SignBytes(_s.ChainID, tx)
  605. if !val.PubKey.VerifyBytes(signBytes, tx.Signature) {
  606. return types.ErrTxInvalidSignature
  607. }
  608. // tx.Height must be equal to the next height
  609. if tx.Height != _s.LastBlockHeight+1 {
  610. return errors.New(Fmt("Invalid rebond height. Expected %v, got %v", _s.LastBlockHeight+1, tx.Height))
  611. }
  612. // Good!
  613. _s.rebondValidator(val)
  614. if evc != nil {
  615. evc.FireEvent(types.EventStringRebond(), tx)
  616. }
  617. return nil
  618. case *types.DupeoutTx:
  619. // Verify the signatures
  620. _, accused := _s.BondedValidators.GetByAddress(tx.Address)
  621. if accused == nil {
  622. _, accused = _s.UnbondingValidators.GetByAddress(tx.Address)
  623. if accused == nil {
  624. return types.ErrTxInvalidAddress
  625. }
  626. }
  627. voteASignBytes := account.SignBytes(_s.ChainID, &tx.VoteA)
  628. voteBSignBytes := account.SignBytes(_s.ChainID, &tx.VoteB)
  629. if !accused.PubKey.VerifyBytes(voteASignBytes, tx.VoteA.Signature) ||
  630. !accused.PubKey.VerifyBytes(voteBSignBytes, tx.VoteB.Signature) {
  631. return types.ErrTxInvalidSignature
  632. }
  633. // Verify equivocation
  634. // TODO: in the future, just require one vote from a previous height that
  635. // doesn't exist on this chain.
  636. if tx.VoteA.Height != tx.VoteB.Height {
  637. return errors.New("DupeoutTx heights don't match")
  638. }
  639. if tx.VoteA.Round != tx.VoteB.Round {
  640. return errors.New("DupeoutTx rounds don't match")
  641. }
  642. if tx.VoteA.Type != tx.VoteB.Type {
  643. return errors.New("DupeoutTx types don't match")
  644. }
  645. if bytes.Equal(tx.VoteA.BlockHash, tx.VoteB.BlockHash) {
  646. return errors.New("DupeoutTx blockhashes shouldn't match")
  647. }
  648. // Good! (Bad validator!)
  649. _s.destroyValidator(accused)
  650. if evc != nil {
  651. evc.FireEvent(types.EventStringDupeout(), tx)
  652. }
  653. return nil
  654. default:
  655. panic("Unknown Tx type")
  656. }
  657. }