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.

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