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.

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