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.

968 lines
30 KiB

10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
9 years ago
10 years ago
  1. package state
  2. import (
  3. "bytes"
  4. "errors"
  5. "fmt"
  6. acm "github.com/tendermint/tendermint/account"
  7. . "github.com/tendermint/tendermint/common"
  8. "github.com/tendermint/tendermint/events"
  9. ptypes "github.com/tendermint/tendermint/permission/types" // for GlobalPermissionAddress ...
  10. "github.com/tendermint/tendermint/types"
  11. "github.com/tendermint/tendermint/vm"
  12. )
  13. // NOTE: If an error occurs during block execution, state will be left
  14. // at an invalid state. Copy the state before calling ExecBlock!
  15. func ExecBlock(s *State, block *types.Block, blockPartsHeader types.PartSetHeader) error {
  16. err := execBlock(s, block, blockPartsHeader)
  17. if err != nil {
  18. return err
  19. }
  20. // State.Hash should match block.StateHash
  21. stateHash := s.Hash()
  22. if !bytes.Equal(stateHash, block.StateHash) {
  23. return errors.New(Fmt("Invalid state hash. Expected %X, got %X",
  24. stateHash, block.StateHash))
  25. }
  26. return nil
  27. }
  28. // executes transactions of a block, does not check block.StateHash
  29. // NOTE: If an error occurs during block execution, state will be left
  30. // at an invalid state. Copy the state before calling execBlock!
  31. func execBlock(s *State, block *types.Block, blockPartsHeader types.PartSetHeader) error {
  32. // Basic block validation.
  33. err := block.ValidateBasic(s.ChainID, s.LastBlockHeight, s.LastBlockHash, s.LastBlockParts, s.LastBlockTime)
  34. if err != nil {
  35. return err
  36. }
  37. // Validate block LastValidation.
  38. if block.Height == 1 {
  39. if len(block.LastValidation.Precommits) != 0 {
  40. return errors.New("Block at height 1 (first block) should have no LastValidation precommits")
  41. }
  42. } else {
  43. if len(block.LastValidation.Precommits) != s.LastBondedValidators.Size() {
  44. return errors.New(Fmt("Invalid block validation size. Expected %v, got %v",
  45. s.LastBondedValidators.Size(), len(block.LastValidation.Precommits)))
  46. }
  47. err := s.LastBondedValidators.VerifyValidation(
  48. s.ChainID, s.LastBlockHash, s.LastBlockParts, block.Height-1, block.LastValidation)
  49. if err != nil {
  50. return err
  51. }
  52. }
  53. // Update Validator.LastCommitHeight as necessary.
  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. PanicCrisis(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. PanicCrisis("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. PanicCrisis("Failed to update unbonding validator LastCommitHeight")
  73. }
  74. } else {
  75. PanicCrisis("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.Notice("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. // acm.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]*acm.Account, error) {
  130. accounts := map[string]*acm.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]*acm.Account, outs []*types.TxOutput) (map[string]*acm.Account, error) {
  149. if accounts == nil {
  150. accounts = make(map[string]*acm.Account)
  151. }
  152. // we should err if an account is being created but the inputs don't have permission
  153. var checkedCreatePerms bool
  154. for _, out := range outs {
  155. // Account shouldn't be duplicated
  156. if _, ok := accounts[string(out.Address)]; ok {
  157. return nil, types.ErrTxDuplicateAddress
  158. }
  159. acc := state.GetAccount(out.Address)
  160. // output account may be nil (new)
  161. if acc == nil {
  162. if !checkedCreatePerms {
  163. if !hasCreateAccountPermission(state, accounts) {
  164. return nil, fmt.Errorf("At least one input does not have permission to create accounts")
  165. }
  166. checkedCreatePerms = true
  167. }
  168. acc = &acm.Account{
  169. Address: out.Address,
  170. PubKey: nil,
  171. Sequence: 0,
  172. Balance: 0,
  173. Permissions: ptypes.ZeroAccountPermissions,
  174. }
  175. }
  176. accounts[string(out.Address)] = acc
  177. }
  178. return accounts, nil
  179. }
  180. func checkInputPubKey(acc *acm.Account, in *types.TxInput) error {
  181. if acc.PubKey == nil {
  182. if in.PubKey == nil {
  183. return types.ErrTxUnknownPubKey
  184. }
  185. if !bytes.Equal(in.PubKey.Address(), acc.Address) {
  186. return types.ErrTxInvalidPubKey
  187. }
  188. acc.PubKey = in.PubKey
  189. } else {
  190. in.PubKey = nil
  191. }
  192. return nil
  193. }
  194. func validateInputs(accounts map[string]*acm.Account, signBytes []byte, ins []*types.TxInput) (total int64, err error) {
  195. for _, in := range ins {
  196. acc := accounts[string(in.Address)]
  197. if acc == nil {
  198. PanicSanity("validateInputs() expects account in accounts")
  199. }
  200. err = validateInput(acc, signBytes, in)
  201. if err != nil {
  202. return
  203. }
  204. // Good. Add amount to total
  205. total += in.Amount
  206. }
  207. return total, nil
  208. }
  209. func validateInput(acc *acm.Account, signBytes []byte, in *types.TxInput) (err error) {
  210. // Check TxInput basic
  211. if err := in.ValidateBasic(); err != nil {
  212. return err
  213. }
  214. // Check signatures
  215. if !acc.PubKey.VerifyBytes(signBytes, in.Signature) {
  216. return types.ErrTxInvalidSignature
  217. }
  218. // Check sequences
  219. if acc.Sequence+1 != in.Sequence {
  220. return types.ErrTxInvalidSequence{
  221. Got: in.Sequence,
  222. Expected: acc.Sequence + 1,
  223. }
  224. }
  225. // Check amount
  226. if acc.Balance < in.Amount {
  227. return types.ErrTxInsufficientFunds
  228. }
  229. return nil
  230. }
  231. func validateOutputs(outs []*types.TxOutput) (total int64, err error) {
  232. for _, out := range outs {
  233. // Check TxOutput basic
  234. if err := out.ValidateBasic(); err != nil {
  235. return 0, err
  236. }
  237. // Good. Add amount to total
  238. total += out.Amount
  239. }
  240. return total, nil
  241. }
  242. func adjustByInputs(accounts map[string]*acm.Account, ins []*types.TxInput) {
  243. for _, in := range ins {
  244. acc := accounts[string(in.Address)]
  245. if acc == nil {
  246. PanicSanity("adjustByInputs() expects account in accounts")
  247. }
  248. if acc.Balance < in.Amount {
  249. PanicSanity("adjustByInputs() expects sufficient funds")
  250. }
  251. acc.Balance -= in.Amount
  252. acc.Sequence += 1
  253. }
  254. }
  255. func adjustByOutputs(accounts map[string]*acm.Account, outs []*types.TxOutput) {
  256. for _, out := range outs {
  257. acc := accounts[string(out.Address)]
  258. if acc == nil {
  259. PanicSanity("adjustByOutputs() expects account in accounts")
  260. }
  261. acc.Balance += out.Amount
  262. }
  263. }
  264. // If the tx is invalid, an error will be returned.
  265. // Unlike ExecBlock(), state will not be altered.
  266. func ExecTx(blockCache *BlockCache, tx types.Tx, runCall bool, evc events.Fireable) (err error) {
  267. // TODO: do something with fees
  268. fees := int64(0)
  269. _s := blockCache.State() // hack to access validators and block height
  270. // Exec tx
  271. switch tx := tx.(type) {
  272. case *types.SendTx:
  273. accounts, err := getInputs(blockCache, tx.Inputs)
  274. if err != nil {
  275. return err
  276. }
  277. // ensure all inputs have send permissions
  278. if !hasSendPermission(blockCache, accounts) {
  279. return fmt.Errorf("At least one input lacks permission for SendTx")
  280. }
  281. // add outputs to accounts map
  282. // if any outputs don't exist, all inputs must have CreateAccount perm
  283. accounts, err = getOrMakeOutputs(blockCache, accounts, tx.Outputs)
  284. if err != nil {
  285. return err
  286. }
  287. signBytes := acm.SignBytes(_s.ChainID, tx)
  288. inTotal, err := validateInputs(accounts, signBytes, tx.Inputs)
  289. if err != nil {
  290. return err
  291. }
  292. outTotal, err := validateOutputs(tx.Outputs)
  293. if err != nil {
  294. return err
  295. }
  296. if outTotal > inTotal {
  297. return types.ErrTxInsufficientFunds
  298. }
  299. fee := inTotal - outTotal
  300. fees += fee
  301. // Good! Adjust accounts
  302. adjustByInputs(accounts, tx.Inputs)
  303. adjustByOutputs(accounts, tx.Outputs)
  304. for _, acc := range accounts {
  305. blockCache.UpdateAccount(acc)
  306. }
  307. // if the evc is nil, nothing will happen
  308. if evc != nil {
  309. for _, i := range tx.Inputs {
  310. evc.FireEvent(types.EventStringAccInput(i.Address), tx)
  311. }
  312. for _, o := range tx.Outputs {
  313. evc.FireEvent(types.EventStringAccOutput(o.Address), tx)
  314. }
  315. }
  316. return nil
  317. case *types.CallTx:
  318. var inAcc, outAcc *acm.Account
  319. // Validate input
  320. inAcc = blockCache.GetAccount(tx.Input.Address)
  321. if inAcc == nil {
  322. log.Info(Fmt("Can't find in account %X", tx.Input.Address))
  323. return types.ErrTxInvalidAddress
  324. }
  325. createAccount := len(tx.Address) == 0
  326. if createAccount {
  327. if !hasCreateContractPermission(blockCache, inAcc) {
  328. return fmt.Errorf("Account %X does not have Create permission", tx.Input.Address)
  329. }
  330. } else {
  331. if !hasCallPermission(blockCache, inAcc) {
  332. return fmt.Errorf("Account %X does not have Call permission", tx.Input.Address)
  333. }
  334. }
  335. // pubKey should be present in either "inAcc" or "tx.Input"
  336. if err := checkInputPubKey(inAcc, tx.Input); err != nil {
  337. log.Info(Fmt("Can't find pubkey for %X", tx.Input.Address))
  338. return err
  339. }
  340. signBytes := acm.SignBytes(_s.ChainID, tx)
  341. err := validateInput(inAcc, signBytes, tx.Input)
  342. if err != nil {
  343. log.Info(Fmt("validateInput failed on %X: %v", tx.Input.Address, err))
  344. return err
  345. }
  346. if tx.Input.Amount < tx.Fee {
  347. log.Info(Fmt("Sender did not send enough to cover the fee %X", tx.Input.Address))
  348. return types.ErrTxInsufficientFunds
  349. }
  350. if !createAccount {
  351. // Validate output
  352. if len(tx.Address) != 20 {
  353. log.Info(Fmt("Destination address is not 20 bytes %X", tx.Address))
  354. return types.ErrTxInvalidAddress
  355. }
  356. // this may be nil if we are still in mempool and contract was created in same block as this tx
  357. // but that's fine, because the account will be created properly when the create tx runs in the block
  358. // and then this won't return nil. otherwise, we take their fee
  359. outAcc = blockCache.GetAccount(tx.Address)
  360. }
  361. log.Info(Fmt("Out account: %v", outAcc))
  362. // Good!
  363. value := tx.Input.Amount - tx.Fee
  364. inAcc.Sequence += 1
  365. if runCall {
  366. var (
  367. gas int64 = tx.GasLimit
  368. err error = nil
  369. caller *vm.Account = toVMAccount(inAcc)
  370. callee *vm.Account = nil
  371. code []byte = nil
  372. txCache = NewTxCache(blockCache)
  373. params = vm.Params{
  374. BlockHeight: int64(_s.LastBlockHeight),
  375. BlockHash: LeftPadWord256(_s.LastBlockHash),
  376. BlockTime: _s.LastBlockTime.Unix(),
  377. GasLimit: 10000000,
  378. }
  379. )
  380. // get or create callee
  381. if !createAccount {
  382. if outAcc == nil || len(outAcc.Code) == 0 {
  383. // check if its a native contract
  384. if vm.RegisteredNativeContract(LeftPadWord256(tx.Address)) {
  385. return fmt.Errorf("NativeContracts can not be called using CallTx. Use a contract or the appropriate tx type (eg. PermissionsTx, NameTx)")
  386. }
  387. // if you call an account that doesn't exist
  388. // or an account with no code then we take fees (sorry pal)
  389. // NOTE: it's fine to create a contract and call it within one
  390. // block (nonce will prevent re-ordering of those txs)
  391. // but to create with one account and call with another
  392. // you have to wait a block to avoid a re-ordering attack
  393. // that will take your fees
  394. inAcc.Balance -= tx.Fee
  395. blockCache.UpdateAccount(inAcc)
  396. if outAcc == nil {
  397. log.Info(Fmt("Cannot find destination address %X. Deducting fee from caller", tx.Address))
  398. } else {
  399. log.Info(Fmt("Attempting to call an account (%X) with no code. Deducting fee from caller", tx.Address))
  400. }
  401. return types.ErrTxInvalidAddress
  402. }
  403. callee = toVMAccount(outAcc)
  404. code = callee.Code
  405. log.Info(Fmt("Calling contract %X with code %X", callee.Address, callee.Code))
  406. } else {
  407. callee = txCache.CreateAccount(caller)
  408. log.Info(Fmt("Created new account %X", callee.Address))
  409. code = tx.Data
  410. }
  411. log.Info(Fmt("Code for this contract: %X", code))
  412. txCache.UpdateAccount(caller) // because we bumped nonce
  413. txCache.UpdateAccount(callee) // so the txCache knows about the callee and the create and/or transfer takes effect
  414. vmach := vm.NewVM(txCache, params, caller.Address, types.TxID(_s.ChainID, tx))
  415. vmach.SetFireable(evc)
  416. // NOTE: Call() transfers the value from caller to callee iff call succeeds.
  417. ret, err := vmach.Call(caller, callee, code, tx.Data, value, &gas)
  418. exception := ""
  419. if err != nil {
  420. exception = err.Error()
  421. // Failure. Charge the gas fee. The 'value' was otherwise not transferred.
  422. log.Info(Fmt("Error on execution: %v", err))
  423. inAcc.Balance -= tx.Fee
  424. blockCache.UpdateAccount(inAcc)
  425. // Throw away 'txCache' which holds incomplete updates (don't sync it).
  426. } else {
  427. log.Info("Successful execution")
  428. // Success
  429. if createAccount {
  430. callee.Code = ret
  431. }
  432. txCache.Sync()
  433. }
  434. // Create a receipt from the ret and whether errored.
  435. log.Notice("VM call complete", "caller", caller, "callee", callee, "return", ret, "err", err)
  436. // Fire Events for sender and receiver
  437. // a separate event will be fired from vm for each additional call
  438. if evc != nil {
  439. evc.FireEvent(types.EventStringAccInput(tx.Input.Address), types.EventMsgCallTx{tx, ret, exception})
  440. evc.FireEvent(types.EventStringAccOutput(tx.Address), types.EventMsgCallTx{tx, ret, exception})
  441. }
  442. } else {
  443. // The mempool does not call txs until
  444. // the proposer determines the order of txs.
  445. // So mempool will skip the actual .Call(),
  446. // and only deduct from the caller's balance.
  447. inAcc.Balance -= value
  448. if createAccount {
  449. inAcc.Sequence += 1
  450. }
  451. blockCache.UpdateAccount(inAcc)
  452. }
  453. return nil
  454. case *types.NameTx:
  455. var inAcc *acm.Account
  456. // Validate input
  457. inAcc = blockCache.GetAccount(tx.Input.Address)
  458. if inAcc == nil {
  459. log.Info(Fmt("Can't find in account %X", tx.Input.Address))
  460. return types.ErrTxInvalidAddress
  461. }
  462. // check permission
  463. if !hasNamePermission(blockCache, inAcc) {
  464. return fmt.Errorf("Account %X does not have Name permission", tx.Input.Address)
  465. }
  466. // pubKey should be present in either "inAcc" or "tx.Input"
  467. if err := checkInputPubKey(inAcc, tx.Input); err != nil {
  468. log.Info(Fmt("Can't find pubkey for %X", tx.Input.Address))
  469. return err
  470. }
  471. signBytes := acm.SignBytes(_s.ChainID, tx)
  472. err := validateInput(inAcc, signBytes, tx.Input)
  473. if err != nil {
  474. log.Info(Fmt("validateInput failed on %X: %v", tx.Input.Address, err))
  475. return err
  476. }
  477. // fee is in addition to the amount which is used to determine the TTL
  478. if tx.Input.Amount < tx.Fee {
  479. log.Info(Fmt("Sender did not send enough to cover the fee %X", tx.Input.Address))
  480. return types.ErrTxInsufficientFunds
  481. }
  482. // validate the input strings
  483. if err := tx.ValidateStrings(); err != nil {
  484. log.Info(err.Error())
  485. return types.ErrTxInvalidString
  486. }
  487. value := tx.Input.Amount - tx.Fee
  488. // let's say cost of a name for one block is len(data) + 32
  489. costPerBlock := types.NameCostPerBlock * types.NameCostPerByte * tx.BaseEntryCost()
  490. expiresIn := int(value / costPerBlock)
  491. lastBlockHeight := _s.LastBlockHeight
  492. log.Info("New NameTx", "value", value, "costPerBlock", costPerBlock, "expiresIn", expiresIn, "lastBlock", lastBlockHeight)
  493. // check if the name exists
  494. entry := blockCache.GetNameRegEntry(tx.Name)
  495. if entry != nil {
  496. var expired bool
  497. // if the entry already exists, and hasn't expired, we must be owner
  498. if entry.Expires > lastBlockHeight {
  499. // ensure we are owner
  500. if bytes.Compare(entry.Owner, tx.Input.Address) != 0 {
  501. log.Info(Fmt("Sender %X is trying to update a name (%s) for which he is not owner", tx.Input.Address, tx.Name))
  502. return types.ErrIncorrectOwner
  503. }
  504. } else {
  505. expired = true
  506. }
  507. // no value and empty data means delete the entry
  508. if value == 0 && len(tx.Data) == 0 {
  509. // maybe we reward you for telling us we can delete this crap
  510. // (owners if not expired, anyone if expired)
  511. log.Info("Removing namereg entry", "name", entry.Name)
  512. blockCache.RemoveNameRegEntry(entry.Name)
  513. } else {
  514. // update the entry by bumping the expiry
  515. // and changing the data
  516. if expired {
  517. if expiresIn < types.MinNameRegistrationPeriod {
  518. return errors.New(Fmt("Names must be registered for at least %d blocks", types.MinNameRegistrationPeriod))
  519. }
  520. entry.Expires = lastBlockHeight + expiresIn
  521. entry.Owner = tx.Input.Address
  522. log.Info("An old namereg entry has expired and been reclaimed", "name", entry.Name, "expiresIn", expiresIn, "owner", entry.Owner)
  523. } else {
  524. // since the size of the data may have changed
  525. // we use the total amount of "credit"
  526. oldCredit := int64(entry.Expires-lastBlockHeight) * types.BaseEntryCost(entry.Name, entry.Data)
  527. credit := oldCredit + value
  528. expiresIn = int(credit / costPerBlock)
  529. if expiresIn < types.MinNameRegistrationPeriod {
  530. return errors.New(Fmt("Names must be registered for at least %d blocks", types.MinNameRegistrationPeriod))
  531. }
  532. entry.Expires = lastBlockHeight + expiresIn
  533. log.Info("Updated namereg entry", "name", entry.Name, "expiresIn", expiresIn, "oldCredit", oldCredit, "value", value, "credit", credit)
  534. }
  535. entry.Data = tx.Data
  536. blockCache.UpdateNameRegEntry(entry)
  537. }
  538. } else {
  539. if expiresIn < types.MinNameRegistrationPeriod {
  540. return errors.New(Fmt("Names must be registered for at least %d blocks", types.MinNameRegistrationPeriod))
  541. }
  542. // entry does not exist, so create it
  543. entry = &types.NameRegEntry{
  544. Name: tx.Name,
  545. Owner: tx.Input.Address,
  546. Data: tx.Data,
  547. Expires: lastBlockHeight + expiresIn,
  548. }
  549. log.Info("Creating namereg entry", "name", entry.Name, "expiresIn", expiresIn)
  550. blockCache.UpdateNameRegEntry(entry)
  551. }
  552. // TODO: something with the value sent?
  553. // Good!
  554. inAcc.Sequence += 1
  555. inAcc.Balance -= value
  556. blockCache.UpdateAccount(inAcc)
  557. // TODO: maybe we want to take funds on error and allow txs in that don't do anythingi?
  558. return nil
  559. case *types.BondTx:
  560. valInfo := blockCache.State().GetValidatorInfo(tx.PubKey.Address())
  561. if valInfo != nil {
  562. // TODO: In the future, check that the validator wasn't destroyed,
  563. // add funds, merge UnbondTo outputs, and unbond validator.
  564. return errors.New("Adding coins to existing validators not yet supported")
  565. }
  566. accounts, err := getInputs(blockCache, tx.Inputs)
  567. if err != nil {
  568. return err
  569. }
  570. // add outputs to accounts map
  571. // if any outputs don't exist, all inputs must have CreateAccount perm
  572. // though outputs aren't created until unbonding/release time
  573. canCreate := hasCreateAccountPermission(blockCache, accounts)
  574. for _, out := range tx.UnbondTo {
  575. acc := blockCache.GetAccount(out.Address)
  576. if acc == nil && !canCreate {
  577. return fmt.Errorf("At least one input does not have permission to create accounts")
  578. }
  579. }
  580. bondAcc := blockCache.GetAccount(tx.PubKey.Address())
  581. if !hasBondPermission(blockCache, bondAcc) {
  582. return fmt.Errorf("The bonder does not have permission to bond")
  583. }
  584. if !hasBondOrSendPermission(blockCache, accounts) {
  585. return fmt.Errorf("At least one input lacks permission to bond")
  586. }
  587. signBytes := acm.SignBytes(_s.ChainID, tx)
  588. inTotal, err := validateInputs(accounts, signBytes, tx.Inputs)
  589. if err != nil {
  590. return err
  591. }
  592. if !tx.PubKey.VerifyBytes(signBytes, tx.Signature) {
  593. return types.ErrTxInvalidSignature
  594. }
  595. outTotal, err := validateOutputs(tx.UnbondTo)
  596. if err != nil {
  597. return err
  598. }
  599. if outTotal > inTotal {
  600. return types.ErrTxInsufficientFunds
  601. }
  602. fee := inTotal - outTotal
  603. fees += fee
  604. // Good! Adjust accounts
  605. adjustByInputs(accounts, tx.Inputs)
  606. for _, acc := range accounts {
  607. blockCache.UpdateAccount(acc)
  608. }
  609. // Add ValidatorInfo
  610. _s.SetValidatorInfo(&ValidatorInfo{
  611. Address: tx.PubKey.Address(),
  612. PubKey: tx.PubKey,
  613. UnbondTo: tx.UnbondTo,
  614. FirstBondHeight: _s.LastBlockHeight + 1,
  615. FirstBondAmount: outTotal,
  616. })
  617. // Add Validator
  618. added := _s.BondedValidators.Add(&Validator{
  619. Address: tx.PubKey.Address(),
  620. PubKey: tx.PubKey,
  621. BondHeight: _s.LastBlockHeight + 1,
  622. VotingPower: outTotal,
  623. Accum: 0,
  624. })
  625. if !added {
  626. PanicCrisis("Failed to add validator")
  627. }
  628. if evc != nil {
  629. // TODO: fire for all inputs
  630. evc.FireEvent(types.EventStringBond(), tx)
  631. }
  632. return nil
  633. case *types.UnbondTx:
  634. // The validator must be active
  635. _, val := _s.BondedValidators.GetByAddress(tx.Address)
  636. if val == nil {
  637. return types.ErrTxInvalidAddress
  638. }
  639. // Verify the signature
  640. signBytes := acm.SignBytes(_s.ChainID, tx)
  641. if !val.PubKey.VerifyBytes(signBytes, tx.Signature) {
  642. return types.ErrTxInvalidSignature
  643. }
  644. // tx.Height must be greater than val.LastCommitHeight
  645. if tx.Height <= val.LastCommitHeight {
  646. return errors.New("Invalid unbond height")
  647. }
  648. // Good!
  649. _s.unbondValidator(val)
  650. if evc != nil {
  651. evc.FireEvent(types.EventStringUnbond(), tx)
  652. }
  653. return nil
  654. case *types.RebondTx:
  655. // The validator must be inactive
  656. _, val := _s.UnbondingValidators.GetByAddress(tx.Address)
  657. if val == nil {
  658. return types.ErrTxInvalidAddress
  659. }
  660. // Verify the signature
  661. signBytes := acm.SignBytes(_s.ChainID, tx)
  662. if !val.PubKey.VerifyBytes(signBytes, tx.Signature) {
  663. return types.ErrTxInvalidSignature
  664. }
  665. // tx.Height must be in a suitable range
  666. minRebondHeight := _s.LastBlockHeight - (validatorTimeoutBlocks / 2)
  667. maxRebondHeight := _s.LastBlockHeight + 2
  668. if !((minRebondHeight <= tx.Height) && (tx.Height <= maxRebondHeight)) {
  669. return errors.New(Fmt("Rebond height not in range. Expected %v <= %v <= %v",
  670. minRebondHeight, tx.Height, maxRebondHeight))
  671. }
  672. // Good!
  673. _s.rebondValidator(val)
  674. if evc != nil {
  675. evc.FireEvent(types.EventStringRebond(), tx)
  676. }
  677. return nil
  678. case *types.DupeoutTx:
  679. // Verify the signatures
  680. _, accused := _s.BondedValidators.GetByAddress(tx.Address)
  681. if accused == nil {
  682. _, accused = _s.UnbondingValidators.GetByAddress(tx.Address)
  683. if accused == nil {
  684. return types.ErrTxInvalidAddress
  685. }
  686. }
  687. voteASignBytes := acm.SignBytes(_s.ChainID, &tx.VoteA)
  688. voteBSignBytes := acm.SignBytes(_s.ChainID, &tx.VoteB)
  689. if !accused.PubKey.VerifyBytes(voteASignBytes, tx.VoteA.Signature) ||
  690. !accused.PubKey.VerifyBytes(voteBSignBytes, tx.VoteB.Signature) {
  691. return types.ErrTxInvalidSignature
  692. }
  693. // Verify equivocation
  694. // TODO: in the future, just require one vote from a previous height that
  695. // doesn't exist on this chain.
  696. if tx.VoteA.Height != tx.VoteB.Height {
  697. return errors.New("DupeoutTx heights don't match")
  698. }
  699. if tx.VoteA.Round != tx.VoteB.Round {
  700. return errors.New("DupeoutTx rounds don't match")
  701. }
  702. if tx.VoteA.Type != tx.VoteB.Type {
  703. return errors.New("DupeoutTx types don't match")
  704. }
  705. if bytes.Equal(tx.VoteA.BlockHash, tx.VoteB.BlockHash) {
  706. return errors.New("DupeoutTx blockhashes shouldn't match")
  707. }
  708. // Good! (Bad validator!)
  709. _s.destroyValidator(accused)
  710. if evc != nil {
  711. evc.FireEvent(types.EventStringDupeout(), tx)
  712. }
  713. return nil
  714. case *types.PermissionsTx:
  715. var inAcc *acm.Account
  716. // Validate input
  717. inAcc = blockCache.GetAccount(tx.Input.Address)
  718. if inAcc == nil {
  719. log.Debug(Fmt("Can't find in account %X", tx.Input.Address))
  720. return types.ErrTxInvalidAddress
  721. }
  722. permFlag := tx.PermArgs.PermFlag()
  723. // check permission
  724. if !HasPermission(blockCache, inAcc, permFlag) {
  725. return fmt.Errorf("Account %X does not have moderator permission %s (%b)", tx.Input.Address, ptypes.PermFlagToString(permFlag), permFlag)
  726. }
  727. // pubKey should be present in either "inAcc" or "tx.Input"
  728. if err := checkInputPubKey(inAcc, tx.Input); err != nil {
  729. log.Debug(Fmt("Can't find pubkey for %X", tx.Input.Address))
  730. return err
  731. }
  732. signBytes := acm.SignBytes(_s.ChainID, tx)
  733. err := validateInput(inAcc, signBytes, tx.Input)
  734. if err != nil {
  735. log.Debug(Fmt("validateInput failed on %X: %v", tx.Input.Address, err))
  736. return err
  737. }
  738. value := tx.Input.Amount
  739. log.Debug("New PermissionsTx", "function", ptypes.PermFlagToString(permFlag), "args", tx.PermArgs)
  740. var permAcc *acm.Account
  741. switch args := tx.PermArgs.(type) {
  742. case *ptypes.HasBaseArgs:
  743. // this one doesn't make sense from txs
  744. return fmt.Errorf("HasBase is for contracts, not humans. Just look at the blockchain")
  745. case *ptypes.SetBaseArgs:
  746. if permAcc = blockCache.GetAccount(args.Address); permAcc == nil {
  747. return fmt.Errorf("Trying to update permissions for unknown account %X", args.Address)
  748. }
  749. err = permAcc.Permissions.Base.Set(args.Permission, args.Value)
  750. case *ptypes.UnsetBaseArgs:
  751. if permAcc = blockCache.GetAccount(args.Address); permAcc == nil {
  752. return fmt.Errorf("Trying to update permissions for unknown account %X", args.Address)
  753. }
  754. err = permAcc.Permissions.Base.Unset(args.Permission)
  755. case *ptypes.SetGlobalArgs:
  756. if permAcc = blockCache.GetAccount(ptypes.GlobalPermissionsAddress); permAcc == nil {
  757. PanicSanity("can't find global permissions account")
  758. }
  759. err = permAcc.Permissions.Base.Set(args.Permission, args.Value)
  760. case *ptypes.HasRoleArgs:
  761. return fmt.Errorf("HasRole is for contracts, not humans. Just look at the blockchain")
  762. case *ptypes.AddRoleArgs:
  763. if permAcc = blockCache.GetAccount(args.Address); permAcc == nil {
  764. return fmt.Errorf("Trying to update roles for unknown account %X", args.Address)
  765. }
  766. if !permAcc.Permissions.AddRole(args.Role) {
  767. return fmt.Errorf("Role (%s) already exists for account %X", args.Role, args.Address)
  768. }
  769. case *ptypes.RmRoleArgs:
  770. if permAcc = blockCache.GetAccount(args.Address); permAcc == nil {
  771. return fmt.Errorf("Trying to update roles for unknown account %X", args.Address)
  772. }
  773. if !permAcc.Permissions.RmRole(args.Role) {
  774. return fmt.Errorf("Role (%s) does not exist for account %X", args.Role, args.Address)
  775. }
  776. default:
  777. PanicSanity(Fmt("invalid permission function: %s", ptypes.PermFlagToString(permFlag)))
  778. }
  779. // TODO: maybe we want to take funds on error and allow txs in that don't do anythingi?
  780. if err != nil {
  781. return err
  782. }
  783. // Good!
  784. inAcc.Sequence += 1
  785. inAcc.Balance -= value
  786. blockCache.UpdateAccount(inAcc)
  787. if permAcc != nil {
  788. blockCache.UpdateAccount(permAcc)
  789. }
  790. if evc != nil {
  791. evc.FireEvent(types.EventStringAccInput(tx.Input.Address), tx)
  792. evc.FireEvent(types.EventStringPermissions(ptypes.PermFlagToString(permFlag)), tx)
  793. }
  794. return nil
  795. default:
  796. // binary decoding should not let this happen
  797. PanicSanity("Unknown Tx type")
  798. return nil
  799. }
  800. }
  801. //---------------------------------------------------------------
  802. // Get permission on an account or fall back to global value
  803. func HasPermission(state AccountGetter, acc *acm.Account, perm ptypes.PermFlag) bool {
  804. if perm > ptypes.AllPermFlags {
  805. PanicSanity("Checking an unknown permission in state should never happen")
  806. }
  807. if acc == nil {
  808. // TODO
  809. // this needs to fall back to global or do some other specific things
  810. // eg. a bondAcc may be nil and so can only bond if global bonding is true
  811. }
  812. permString := ptypes.PermFlagToString(perm)
  813. v, err := acc.Permissions.Base.Get(perm)
  814. if _, ok := err.(ptypes.ErrValueNotSet); ok {
  815. if state == nil {
  816. PanicSanity("All known global permissions should be set!")
  817. }
  818. log.Info("Permission for account is not set. Querying GlobalPermissionsAddress", "perm", permString)
  819. return HasPermission(nil, state.GetAccount(ptypes.GlobalPermissionsAddress), perm)
  820. } else if v {
  821. log.Info("Account has permission", "address", Fmt("%X", acc.Address), "perm", permString)
  822. } else {
  823. log.Info("Account does not have permission", "address", Fmt("%X", acc.Address), "perm", permString)
  824. }
  825. return v
  826. }
  827. // TODO: for debug log the failed accounts
  828. func hasSendPermission(state AccountGetter, accs map[string]*acm.Account) bool {
  829. for _, acc := range accs {
  830. if !HasPermission(state, acc, ptypes.Send) {
  831. return false
  832. }
  833. }
  834. return true
  835. }
  836. func hasNamePermission(state AccountGetter, acc *acm.Account) bool {
  837. return HasPermission(state, acc, ptypes.Name)
  838. }
  839. func hasCallPermission(state AccountGetter, acc *acm.Account) bool {
  840. return HasPermission(state, acc, ptypes.Call)
  841. }
  842. func hasCreateContractPermission(state AccountGetter, acc *acm.Account) bool {
  843. return HasPermission(state, acc, ptypes.CreateContract)
  844. }
  845. func hasCreateAccountPermission(state AccountGetter, accs map[string]*acm.Account) bool {
  846. for _, acc := range accs {
  847. if !HasPermission(state, acc, ptypes.CreateAccount) {
  848. return false
  849. }
  850. }
  851. return true
  852. }
  853. func hasBondPermission(state AccountGetter, acc *acm.Account) bool {
  854. return HasPermission(state, acc, ptypes.Bond)
  855. }
  856. func hasBondOrSendPermission(state AccountGetter, accs map[string]*acm.Account) bool {
  857. for _, acc := range accs {
  858. if !HasPermission(state, acc, ptypes.Bond) {
  859. if !HasPermission(state, acc, ptypes.Send) {
  860. return false
  861. }
  862. }
  863. }
  864. return true
  865. }