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.

831 lines
25 KiB

9 years ago
10 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 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. if !hasBondPermission(blockCache, accounts) {
  574. return fmt.Errorf("At least one input lacks permission to bond")
  575. }
  576. signBytes := account.SignBytes(_s.ChainID, tx)
  577. inTotal, err := validateInputs(accounts, signBytes, tx.Inputs)
  578. if err != nil {
  579. return err
  580. }
  581. if err := tx.PubKey.ValidateBasic(); err != nil {
  582. return err
  583. }
  584. if !tx.PubKey.VerifyBytes(signBytes, tx.Signature) {
  585. return types.ErrTxInvalidSignature
  586. }
  587. outTotal, err := validateOutputs(tx.UnbondTo)
  588. if err != nil {
  589. return err
  590. }
  591. if outTotal > inTotal {
  592. return types.ErrTxInsufficientFunds
  593. }
  594. fee := inTotal - outTotal
  595. fees += fee
  596. // Good! Adjust accounts
  597. adjustByInputs(accounts, tx.Inputs)
  598. for _, acc := range accounts {
  599. blockCache.UpdateAccount(acc)
  600. }
  601. // Add ValidatorInfo
  602. _s.SetValidatorInfo(&ValidatorInfo{
  603. Address: tx.PubKey.Address(),
  604. PubKey: tx.PubKey,
  605. UnbondTo: tx.UnbondTo,
  606. FirstBondHeight: _s.LastBlockHeight + 1,
  607. FirstBondAmount: outTotal,
  608. })
  609. // Add Validator
  610. added := _s.BondedValidators.Add(&Validator{
  611. Address: tx.PubKey.Address(),
  612. PubKey: tx.PubKey,
  613. BondHeight: _s.LastBlockHeight + 1,
  614. VotingPower: outTotal,
  615. Accum: 0,
  616. })
  617. if !added {
  618. // SOMETHING HAS GONE HORRIBLY WRONG
  619. panic("Failed to add validator")
  620. }
  621. if evc != nil {
  622. evc.FireEvent(types.EventStringBond(), tx)
  623. }
  624. return nil
  625. case *types.UnbondTx:
  626. // The validator must be active
  627. _, val := _s.BondedValidators.GetByAddress(tx.Address)
  628. if val == nil {
  629. return types.ErrTxInvalidAddress
  630. }
  631. // Verify the signature
  632. signBytes := account.SignBytes(_s.ChainID, tx)
  633. if !val.PubKey.VerifyBytes(signBytes, tx.Signature) {
  634. return types.ErrTxInvalidSignature
  635. }
  636. // tx.Height must be greater than val.LastCommitHeight
  637. if tx.Height <= val.LastCommitHeight {
  638. return errors.New("Invalid unbond height")
  639. }
  640. // Good!
  641. _s.unbondValidator(val)
  642. if evc != nil {
  643. evc.FireEvent(types.EventStringUnbond(), tx)
  644. }
  645. return nil
  646. case *types.RebondTx:
  647. // The validator must be inactive
  648. _, val := _s.UnbondingValidators.GetByAddress(tx.Address)
  649. if val == nil {
  650. return types.ErrTxInvalidAddress
  651. }
  652. // Verify the signature
  653. signBytes := account.SignBytes(_s.ChainID, tx)
  654. if !val.PubKey.VerifyBytes(signBytes, tx.Signature) {
  655. return types.ErrTxInvalidSignature
  656. }
  657. // tx.Height must be equal to the next height
  658. if tx.Height != _s.LastBlockHeight+1 {
  659. return errors.New(Fmt("Invalid rebond height. Expected %v, got %v", _s.LastBlockHeight+1, tx.Height))
  660. }
  661. // Good!
  662. _s.rebondValidator(val)
  663. if evc != nil {
  664. evc.FireEvent(types.EventStringRebond(), tx)
  665. }
  666. return nil
  667. case *types.DupeoutTx:
  668. // Verify the signatures
  669. _, accused := _s.BondedValidators.GetByAddress(tx.Address)
  670. if accused == nil {
  671. _, accused = _s.UnbondingValidators.GetByAddress(tx.Address)
  672. if accused == nil {
  673. return types.ErrTxInvalidAddress
  674. }
  675. }
  676. voteASignBytes := account.SignBytes(_s.ChainID, &tx.VoteA)
  677. voteBSignBytes := account.SignBytes(_s.ChainID, &tx.VoteB)
  678. if !accused.PubKey.VerifyBytes(voteASignBytes, tx.VoteA.Signature) ||
  679. !accused.PubKey.VerifyBytes(voteBSignBytes, tx.VoteB.Signature) {
  680. return types.ErrTxInvalidSignature
  681. }
  682. // Verify equivocation
  683. // TODO: in the future, just require one vote from a previous height that
  684. // doesn't exist on this chain.
  685. if tx.VoteA.Height != tx.VoteB.Height {
  686. return errors.New("DupeoutTx heights don't match")
  687. }
  688. if tx.VoteA.Round != tx.VoteB.Round {
  689. return errors.New("DupeoutTx rounds don't match")
  690. }
  691. if tx.VoteA.Type != tx.VoteB.Type {
  692. return errors.New("DupeoutTx types don't match")
  693. }
  694. if bytes.Equal(tx.VoteA.BlockHash, tx.VoteB.BlockHash) {
  695. return errors.New("DupeoutTx blockhashes shouldn't match")
  696. }
  697. // Good! (Bad validator!)
  698. _s.destroyValidator(accused)
  699. if evc != nil {
  700. evc.FireEvent(types.EventStringDupeout(), tx)
  701. }
  702. return nil
  703. default:
  704. // SANITY CHECK (binary decoding should catch bad tx types
  705. // before they get here
  706. panic("Unknown Tx type")
  707. }
  708. }
  709. //---------------------------------------------------------------
  710. // TODO: for debug log the failed accounts
  711. // Get permission on an account or fall back to global value
  712. func HasPermission(state AccountGetter, acc *account.Account, perm ptypes.PermFlag) bool {
  713. v, err := acc.Permissions.Base.Get(perm)
  714. fmt.Printf("has permission? %x %v %b %v %v\n", acc.Address, acc.Permissions, perm, v, err)
  715. if _, ok := err.(ptypes.ErrValueNotSet); ok {
  716. return HasPermission(state, state.GetAccount(ptypes.GlobalPermissionsAddress), perm)
  717. }
  718. return v
  719. }
  720. func hasSendPermission(state AccountGetter, accs map[string]*account.Account) bool {
  721. for _, acc := range accs {
  722. if !HasPermission(state, acc, ptypes.Send) {
  723. return false
  724. }
  725. }
  726. return true
  727. }
  728. func hasCallPermission(state AccountGetter, acc *account.Account) bool {
  729. if !HasPermission(state, acc, ptypes.Call) {
  730. return false
  731. }
  732. return true
  733. }
  734. func hasCreatePermission(state AccountGetter, acc *account.Account) bool {
  735. if !HasPermission(state, acc, ptypes.Create) {
  736. return false
  737. }
  738. return true
  739. }
  740. func hasBondPermission(state AccountGetter, accs map[string]*account.Account) bool {
  741. for _, acc := range accs {
  742. if !HasPermission(state, acc, ptypes.Bond) {
  743. return false
  744. }
  745. }
  746. return true
  747. }