func TestSendPermission(t *testing.T) {
	stateDB := dbm.GetDB("state")
	genDoc := newBaseGenDoc(PermsAllFalse, PermsAllFalse)
	genDoc.Accounts[0].Permissions.Base.Set(ptypes.Send, true) // give the 0 account permission
	st := MakeGenesisState(stateDB, &genDoc)
	blockCache := NewBlockCache(st)

	// A single input, having the permission, should succeed
	tx := types.NewSendTx()
	if err := tx.AddInput(blockCache, user[0].PubKey, 5); err != nil {
		t.Fatal(err)
	}
	tx.AddOutput(user[1].Address, 5)
	tx.SignInput(chainID, 0, user[0])
	if err := ExecTx(blockCache, tx, true, nil); err != nil {
		t.Fatal("Transaction failed", err)
	}

	// Two inputs, one with permission, one without, should fail
	tx = types.NewSendTx()
	if err := tx.AddInput(blockCache, user[0].PubKey, 5); err != nil {
		t.Fatal(err)
	}
	if err := tx.AddInput(blockCache, user[1].PubKey, 5); err != nil {
		t.Fatal(err)
	}
	tx.AddOutput(user[2].Address, 10)
	tx.SignInput(chainID, 0, user[0])
	tx.SignInput(chainID, 1, user[1])
	if err := ExecTx(blockCache, tx, true, nil); err == nil {
		t.Fatal("Expected error")
	} else {
		fmt.Println(err)
	}
}
func TestName(t *testing.T) {
	stateDB := dbm.GetDB("state")
	genDoc := newBaseGenDoc(PermsAllFalse, PermsAllFalse)
	genDoc.Accounts[0].Permissions.Base.Set(ptypes.Send, true)
	genDoc.Accounts[1].Permissions.Base.Set(ptypes.Name, true)
	st := MakeGenesisState(stateDB, &genDoc)
	blockCache := NewBlockCache(st)

	//-------------------
	// name txs

	// simple name tx without perm should fail
	tx, err := types.NewNameTx(st, user[0].PubKey, "somename", "somedata", 10000, 100)
	if err != nil {
		t.Fatal(err)
	}
	tx.Sign(chainID, user[0])
	if err := ExecTx(blockCache, tx, true, nil); err == nil {
		t.Fatal("Expected error")
	} else {
		fmt.Println(err)
	}

	// simple name tx with perm should pass
	tx, err = types.NewNameTx(st, user[1].PubKey, "somename", "somedata", 10000, 100)
	if err != nil {
		t.Fatal(err)
	}
	tx.Sign(chainID, user[1])
	if err := ExecTx(blockCache, tx, true, nil); err != nil {
		t.Fatal(err)
	}
}
Example #3
0
func gen_tx() {

	// Get State, which may be nil.
	stateDB := dbm.GetDB("state")
	state := sm.LoadState(stateDB)

	// Get source pubkey
	srcPubKeyBytes := getByteSliceFromHex("Enter source pubkey: ")
	r, n, err := bytes.NewReader(srcPubKeyBytes), new(int64), new(error)
	srcPubKey := binary.ReadBinary(struct{ account.PubKey }{}, r, n, err).(struct{ account.PubKey }).PubKey
	if *err != nil {
		Exit(Fmt("Invalid PubKey. Error: %v", err))
	}

	// Get the state of the account.
	var srcAccount *account.Account
	var srcAccountAddress = srcPubKey.Address()
	var srcAccountBalanceStr = "unknown"
	var srcAccountSequenceStr = "unknown"
	srcAddress := srcPubKey.Address()
	if state != nil {
		srcAccount = state.GetAccount(srcAddress)
		srcAccountBalanceStr = Fmt("%v", srcAccount.Balance)
		srcAccountSequenceStr = Fmt("%v", srcAccount.Sequence+1)
	}

	// Get the amount to send from src account
	srcSendAmount := getUint64(Fmt("Enter amount to send from %X (total: %v): ", srcAccountAddress, srcAccountBalanceStr))

	// Get the next sequence of src account
	srcSendSequence := uint(getUint64(Fmt("Enter next sequence for %X (guess: %v): ", srcAccountAddress, srcAccountSequenceStr)))

	// Get dest address
	dstAddress := getByteSliceFromHex("Enter destination address: ")

	// Get the amount to send to dst account
	dstSendAmount := getUint64(Fmt("Enter amount to send to %X: ", dstAddress))

	// Construct SendTx
	tx := &types.SendTx{
		Inputs: []*types.TxInput{
			&types.TxInput{
				Address:   srcAddress,
				Amount:    srcSendAmount,
				Sequence:  srcSendSequence,
				Signature: account.SignatureEd25519{},
				PubKey:    srcPubKey,
			},
		},
		Outputs: []*types.TxOutput{
			&types.TxOutput{
				Address: dstAddress,
				Amount:  dstSendAmount,
			},
		},
	}

	// Show the intermediate form.
	fmt.Printf("Generated tx: %X\n", binary.BinaryBytes(tx))

	// Get source privkey (for signing)
	srcPrivKeyBytes := getByteSliceFromHex("Enter source privkey (for signing): ")
	r, n, err = bytes.NewReader(srcPrivKeyBytes), new(int64), new(error)
	srcPrivKey := binary.ReadBinary(struct{ account.PrivKey }{}, r, n, err).(struct{ account.PrivKey }).PrivKey
	if *err != nil {
		Exit(Fmt("Invalid PrivKey. Error: %v", err))
	}

	// Sign
	tx.Inputs[0].Signature = srcPrivKey.Sign(account.SignBytes(tx))
	fmt.Printf("Signed tx: %X\n", binary.BinaryBytes(tx))
}
Example #4
0
// Handle messages from the poolReactor telling the reactor what to do.
func (bcR *BlockchainReactor) poolRoutine() {

	trySyncTicker := time.NewTicker(trySyncIntervalMS * time.Millisecond)
	statusUpdateTicker := time.NewTicker(statusUpdateIntervalSeconds * time.Second)
	switchToConsensusTicker := time.NewTicker(switchToConsensusIntervalSeconds * time.Second)

FOR_LOOP:
	for {
		select {
		case request := <-bcR.requestsCh: // chan BlockRequest
			peer := bcR.sw.Peers().Get(request.PeerId)
			if peer == nil {
				// We can't fulfill the request.
				continue FOR_LOOP
			}
			msg := &bcBlockRequestMessage{request.Height}
			queued := peer.TrySend(BlockchainChannel, msg)
			if !queued {
				// We couldn't queue the request.
				time.Sleep(defaultSleepIntervalMS * time.Millisecond)
				continue FOR_LOOP
			}
		case peerId := <-bcR.timeoutsCh: // chan string
			// Peer timed out.
			peer := bcR.sw.Peers().Get(peerId)
			if peer != nil {
				bcR.sw.StopPeerForError(peer, errors.New("BlockchainReactor Timeout"))
			}
		case _ = <-statusUpdateTicker.C:
			// ask for status updates
			go bcR.BroadcastStatusRequest()
		case _ = <-switchToConsensusTicker.C:
			// not thread safe access for peerless and numPending but should be fine
			log.Debug("Consensus ticker", "peerless", bcR.pool.peerless, "pending", bcR.pool.numPending, "total", bcR.pool.numTotal)
			// NOTE: this condition is very strict right now. may need to weaken
			// if the max amount of requests are pending and peerless
			// and we have some peers (say > 5), then we're caught up
			maxPending := bcR.pool.numPending == maxPendingRequests
			maxPeerless := bcR.pool.peerless == bcR.pool.numPending
			o, i, _ := bcR.sw.NumPeers()
			enoughPeers := o+i >= 5
			if maxPending && maxPeerless && enoughPeers {
				log.Warn("Time to switch to consensus reactor!", "height", bcR.pool.height)
				bcR.pool.Stop()
				stateDB := dbm.GetDB("state")
				state := sm.LoadState(stateDB)

				bcR.sw.Reactor("CONSENSUS").(consensusReactor).ResetToState(state)
				bcR.sw.Reactor("CONSENSUS").(consensusReactor).SetSyncing(false)

				break FOR_LOOP
			}
		case _ = <-trySyncTicker.C: // chan time
			//var lastValidatedBlock *types.Block
		SYNC_LOOP:
			for i := 0; i < 10; i++ {
				// See if there are any blocks to sync.
				first, second := bcR.pool.PeekTwoBlocks()
				//log.Debug("TrySync peeked", "first", first, "second", second)
				if first == nil || second == nil {
					// We need both to sync the first block.
					break SYNC_LOOP
				}
				firstParts := first.MakePartSet()
				firstPartsHeader := firstParts.Header()
				// Finally, verify the first block using the second's validation.
				err := bcR.state.BondedValidators.VerifyValidation(
					first.Hash(), firstPartsHeader, first.Height, second.Validation)
				if err != nil {
					log.Debug("error in validation", "error", err)
					bcR.pool.RedoRequest(first.Height)
					break SYNC_LOOP
				} else {
					bcR.pool.PopRequest()
					err := sm.ExecBlock(bcR.state, first, firstPartsHeader)
					if err != nil {
						// TODO This is bad, are we zombie?
						panic(Fmt("Failed to process committed block: %v", err))
					}
					bcR.store.SaveBlock(first, firstParts, second.Validation)
					bcR.state.Save()
					//lastValidatedBlock = first
				}
			}
			/*
				// We're done syncing for now (will do again shortly)
				// See if we want to stop syncing and turn on the
				// consensus reactor.
				// TODO: use other heuristics too besides blocktime.
				// It's not a security concern, as it only needs to happen
				// upon node sync, and there's also a second (slower)
				// this peer failed us
				// method of syncing in the consensus reactor.

				if lastValidatedBlock != nil && time.Now().Sub(lastValidatedBlock.Time) < stopSyncingDurationMinutes*time.Minute {
					go func() {
						log.Info("Stopping blockpool syncing, turning on consensus...")
						trySyncTicker.Stop() // Just stop the block requests.  Still serve blocks to others.
						conR := bcR.sw.Reactor("CONSENSUS")
						conR.(stateResetter).ResetToState(bcR.state)
						conR.Start(bcR.sw)
						for _, peer := range bcR.sw.Peers().List() {
							conR.AddPeer(peer)
						}
					}()
					break FOR_LOOP
				}
			*/
			continue FOR_LOOP
		case <-bcR.quit:
			break FOR_LOOP
		}
	}
}
Example #5
0
func NewNode() *Node {
	// Get BlockStore
	blockStoreDB := dbm.GetDB("blockstore")
	blockStore := bc.NewBlockStore(blockStoreDB)

	// Get State
	stateDB := dbm.GetDB("state")
	state := sm.LoadState(stateDB)
	if state == nil {
		state = sm.MakeGenesisStateFromFile(stateDB, config.GetString("genesis_file"))
		state.Save()
	}

	// Get PrivValidator
	var privValidator *sm.PrivValidator
	privValidatorFile := config.GetString("priv_validator_file")
	if _, err := os.Stat(privValidatorFile); err == nil {
		privValidator = sm.LoadPrivValidator(privValidatorFile)
		log.Info("Loaded PrivValidator",
			"file", privValidatorFile, "privValidator", privValidator)
	} else {
		privValidator = sm.GenPrivValidator()
		privValidator.SetFile(privValidatorFile)
		privValidator.Save()
		log.Info("Generated PrivValidator", "file", privValidatorFile)
	}

	eventSwitch := new(events.EventSwitch)
	eventSwitch.Start()

	// Get PEXReactor
	book := p2p.NewAddrBook(config.GetString("addrbook_file"))
	pexReactor := p2p.NewPEXReactor(book)

	// Get BlockchainReactor
	bcReactor := bc.NewBlockchainReactor(state, blockStore, config.GetBool("fast_sync"))

	// Get MempoolReactor
	mempool := mempl.NewMempool(state.Copy())
	mempoolReactor := mempl.NewMempoolReactor(mempool)

	// Get ConsensusReactor
	consensusState := consensus.NewConsensusState(state, blockStore, mempoolReactor)
	consensusReactor := consensus.NewConsensusReactor(consensusState, blockStore)
	if privValidator != nil {
		consensusReactor.SetPrivValidator(privValidator)
	}

	// so the consensus reactor won't do anything until we're synced
	if config.GetBool("fast_sync") {
		consensusReactor.SetSyncing(true)
	}

	sw := p2p.NewSwitch()
	sw.AddReactor("PEX", pexReactor)
	sw.AddReactor("MEMPOOL", mempoolReactor)
	sw.AddReactor("BLOCKCHAIN", bcReactor)
	sw.AddReactor("CONSENSUS", consensusReactor)

	// add the event switch to all services
	// they should all satisfy events.Eventable
	SetFireable(eventSwitch, pexReactor, bcReactor, mempoolReactor, consensusReactor)

	return &Node{
		sw:               sw,
		evsw:             eventSwitch,
		book:             book,
		blockStore:       blockStore,
		pexReactor:       pexReactor,
		bcReactor:        bcReactor,
		mempoolReactor:   mempoolReactor,
		consensusState:   consensusState,
		consensusReactor: consensusReactor,
		privValidator:    privValidator,
	}
}
Example #6
0
func NewNode() *Node {
	// Get BlockStore
	blockStoreDB := dbm.GetDB("blockstore")
	blockStore := bc.NewBlockStore(blockStoreDB)

	// Get State
	stateDB := dbm.GetDB("state")
	state := sm.LoadState(stateDB)
	var genDoc *stypes.GenesisDoc
	if state == nil {
		genDoc, state = sm.MakeGenesisStateFromFile(stateDB, config.GetString("genesis_file"))
		state.Save()
		// write the gendoc to db
		buf, n, err := new(bytes.Buffer), new(int64), new(error)
		wire.WriteJSON(genDoc, buf, n, err)
		stateDB.Set(stypes.GenDocKey, buf.Bytes())
		if *err != nil {
			Exit(Fmt("Unable to write gendoc to db: %v", err))
		}
	} else {
		genDocBytes := stateDB.Get(stypes.GenDocKey)
		err := new(error)
		wire.ReadJSONPtr(&genDoc, genDocBytes, err)
		if *err != nil {
			Exit(Fmt("Unable to read gendoc from db: %v", err))
		}
	}
	// add the chainid to the global config
	config.Set("chain_id", state.ChainID)

	// Get PrivValidator
	privValidatorFile := config.GetString("priv_validator_file")
	privValidator := types.LoadOrGenPrivValidator(privValidatorFile)

	// Generate node PrivKey
	privKey := acm.GenPrivKeyEd25519()

	// Make event switch
	eventSwitch := events.NewEventSwitch()
	_, err := eventSwitch.Start()
	if err != nil {
		Exit(Fmt("Failed to start switch: %v", err))
	}

	// Make PEXReactor
	book := p2p.NewAddrBook(config.GetString("addrbook_file"))
	pexReactor := p2p.NewPEXReactor(book)

	// Make BlockchainReactor
	bcReactor := bc.NewBlockchainReactor(state.Copy(), blockStore, config.GetBool("fast_sync"))

	// Make MempoolReactor
	mempool := mempl.NewMempool(state.Copy())
	mempoolReactor := mempl.NewMempoolReactor(mempool)

	// Make ConsensusReactor
	consensusState := consensus.NewConsensusState(state.Copy(), blockStore, mempoolReactor)
	consensusReactor := consensus.NewConsensusReactor(consensusState, blockStore, config.GetBool("fast_sync"))
	if privValidator != nil {
		consensusReactor.SetPrivValidator(privValidator)
	}

	// Make p2p network switch
	sw := p2p.NewSwitch()
	sw.AddReactor("PEX", pexReactor)
	sw.AddReactor("MEMPOOL", mempoolReactor)
	sw.AddReactor("BLOCKCHAIN", bcReactor)
	sw.AddReactor("CONSENSUS", consensusReactor)

	// add the event switch to all services
	// they should all satisfy events.Eventable
	SetFireable(eventSwitch, pexReactor, bcReactor, mempoolReactor, consensusReactor)

	// run the profile server
	profileHost := config.GetString("prof_laddr")
	if profileHost != "" {
		go func() {
			log.Warn("Profile server", "error", http.ListenAndServe(profileHost, nil))
		}()
	}

	// set vm log level
	vm.SetDebug(config.GetBool("vm_log"))

	return &Node{
		sw:               sw,
		evsw:             eventSwitch,
		book:             book,
		blockStore:       blockStore,
		pexReactor:       pexReactor,
		bcReactor:        bcReactor,
		mempoolReactor:   mempoolReactor,
		consensusState:   consensusState,
		consensusReactor: consensusReactor,
		privValidator:    privValidator,
		genDoc:           genDoc,
		privKey:          privKey,
	}
}
func TestSNativeTx(t *testing.T) {
	stateDB := dbm.GetDB("state")
	genDoc := newBaseGenDoc(PermsAllFalse, PermsAllFalse)
	genDoc.Accounts[0].Permissions.Base.Set(ptypes.Call, true) // give the 0 account permission
	genDoc.Accounts[3].Permissions.Base.Set(ptypes.Bond, true) // some arbitrary permission to play with
	genDoc.Accounts[3].Permissions.AddRole("bumble")
	genDoc.Accounts[3].Permissions.AddRole("bee")
	st := MakeGenesisState(stateDB, &genDoc)
	blockCache := NewBlockCache(st)

	//----------------------------------------------------------
	// Test SNativeTx

	fmt.Println("\n#### SetBase")
	// SetBase
	snativeArgs := snativePermTestInputTx("set_base", user[3], ptypes.Bond, false)
	testSNativeTxExpectFail(t, blockCache, snativeArgs)
	testSNativeTxExpectPass(t, blockCache, ptypes.SetBase, snativeArgs)
	acc := blockCache.GetAccount(user[3].Address)
	if v, _ := acc.Permissions.Base.Get(ptypes.Bond); v {
		t.Fatal("expected permission to be set false")
	}
	snativeArgs = snativePermTestInputTx("set_base", user[3], ptypes.CreateContract, true)
	testSNativeTxExpectPass(t, blockCache, ptypes.SetBase, snativeArgs)
	acc = blockCache.GetAccount(user[3].Address)
	if v, _ := acc.Permissions.Base.Get(ptypes.CreateContract); !v {
		t.Fatal("expected permission to be set true")
	}

	fmt.Println("\n#### UnsetBase")
	// UnsetBase
	snativeArgs = snativePermTestInputTx("unset_base", user[3], ptypes.CreateContract, false)
	testSNativeTxExpectFail(t, blockCache, snativeArgs)
	testSNativeTxExpectPass(t, blockCache, ptypes.UnsetBase, snativeArgs)
	acc = blockCache.GetAccount(user[3].Address)
	if v, _ := acc.Permissions.Base.Get(ptypes.CreateContract); v {
		t.Fatal("expected permission to be set false")
	}

	fmt.Println("\n#### SetGlobal")
	// SetGlobalPerm
	snativeArgs = snativePermTestInputTx("set_global", user[3], ptypes.CreateContract, true)
	testSNativeTxExpectFail(t, blockCache, snativeArgs)
	testSNativeTxExpectPass(t, blockCache, ptypes.SetGlobal, snativeArgs)
	acc = blockCache.GetAccount(ptypes.GlobalPermissionsAddress)
	if v, _ := acc.Permissions.Base.Get(ptypes.CreateContract); !v {
		t.Fatal("expected permission to be set true")
	}

	fmt.Println("\n#### AddRole")
	// AddRole
	snativeArgs = snativeRoleTestInputTx("add_role", user[3], "chuck")
	testSNativeTxExpectFail(t, blockCache, snativeArgs)
	testSNativeTxExpectPass(t, blockCache, ptypes.AddRole, snativeArgs)
	acc = blockCache.GetAccount(user[3].Address)
	if v := acc.Permissions.HasRole("chuck"); !v {
		t.Fatal("expected role to be added")
	}

	fmt.Println("\n#### RmRole")
	// RmRole
	snativeArgs = snativeRoleTestInputTx("rm_role", user[3], "chuck")
	testSNativeTxExpectFail(t, blockCache, snativeArgs)
	testSNativeTxExpectPass(t, blockCache, ptypes.RmRole, snativeArgs)
	acc = blockCache.GetAccount(user[3].Address)
	if v := acc.Permissions.HasRole("chuck"); v {
		t.Fatal("expected role to be removed")
	}
}
func TestSNativeCALL(t *testing.T) {
	stateDB := dbm.GetDB("state")
	genDoc := newBaseGenDoc(PermsAllFalse, PermsAllFalse)
	genDoc.Accounts[0].Permissions.Base.Set(ptypes.Call, true) // give the 0 account permission
	genDoc.Accounts[3].Permissions.Base.Set(ptypes.Bond, true) // some arbitrary permission to play with
	genDoc.Accounts[3].Permissions.AddRole("bumble")
	genDoc.Accounts[3].Permissions.AddRole("bee")
	st := MakeGenesisState(stateDB, &genDoc)
	blockCache := NewBlockCache(st)

	//----------------------------------------------------------
	// Test CALL to SNative contracts

	// make the main contract once
	doug := &acm.Account{
		Address:     DougAddress,
		Balance:     0,
		Code:        nil,
		Sequence:    0,
		StorageRoot: Zero256.Bytes(),
		Permissions: ptypes.ZeroAccountPermissions,
	}
	doug.Permissions.Base.Set(ptypes.Call, true)
	//doug.Permissions.Base.Set(ptypes.HasBase, true)
	blockCache.UpdateAccount(doug)

	fmt.Println("\n#### HasBase")
	// HasBase
	snativeAddress, data := snativePermTestInputCALL("has_base", user[3], ptypes.Bond, false)
	testSNativeCALLExpectFail(t, blockCache, doug, snativeAddress, data)
	testSNativeCALLExpectPass(t, blockCache, doug, snativeAddress, data, func(ret []byte) error {
		// return value should be true or false as a 32 byte array...
		if !IsZeros(ret[:31]) || ret[31] != byte(1) {
			return fmt.Errorf("Expected 1. Got %X", ret)
		}
		return nil
	})

	fmt.Println("\n#### SetBase")
	// SetBase
	snativeAddress, data = snativePermTestInputCALL("set_base", user[3], ptypes.Bond, false)
	testSNativeCALLExpectFail(t, blockCache, doug, snativeAddress, data)
	testSNativeCALLExpectPass(t, blockCache, doug, snativeAddress, data, func(ret []byte) error { return nil })
	snativeAddress, data = snativePermTestInputCALL("has_base", user[3], ptypes.Bond, false)
	testSNativeCALLExpectPass(t, blockCache, doug, snativeAddress, data, func(ret []byte) error {
		// return value should be true or false as a 32 byte array...
		if !IsZeros(ret) {
			return fmt.Errorf("Expected 0. Got %X", ret)
		}
		return nil
	})
	snativeAddress, data = snativePermTestInputCALL("set_base", user[3], ptypes.CreateContract, true)
	testSNativeCALLExpectPass(t, blockCache, doug, snativeAddress, data, func(ret []byte) error { return nil })
	snativeAddress, data = snativePermTestInputCALL("has_base", user[3], ptypes.CreateContract, false)
	testSNativeCALLExpectPass(t, blockCache, doug, snativeAddress, data, func(ret []byte) error {
		// return value should be true or false as a 32 byte array...
		if !IsZeros(ret[:31]) || ret[31] != byte(1) {
			return fmt.Errorf("Expected 1. Got %X", ret)
		}
		return nil
	})

	fmt.Println("\n#### UnsetBase")
	// UnsetBase
	snativeAddress, data = snativePermTestInputCALL("unset_base", user[3], ptypes.CreateContract, false)
	testSNativeCALLExpectFail(t, blockCache, doug, snativeAddress, data)
	testSNativeCALLExpectPass(t, blockCache, doug, snativeAddress, data, func(ret []byte) error { return nil })
	snativeAddress, data = snativePermTestInputCALL("has_base", user[3], ptypes.CreateContract, false)
	testSNativeCALLExpectPass(t, blockCache, doug, snativeAddress, data, func(ret []byte) error {
		if !IsZeros(ret) {
			return fmt.Errorf("Expected 0. Got %X", ret)
		}
		return nil
	})

	fmt.Println("\n#### SetGlobal")
	// SetGlobalPerm
	snativeAddress, data = snativePermTestInputCALL("set_global", user[3], ptypes.CreateContract, true)
	testSNativeCALLExpectFail(t, blockCache, doug, snativeAddress, data)
	testSNativeCALLExpectPass(t, blockCache, doug, snativeAddress, data, func(ret []byte) error { return nil })
	snativeAddress, data = snativePermTestInputCALL("has_base", user[3], ptypes.CreateContract, false)
	testSNativeCALLExpectPass(t, blockCache, doug, snativeAddress, data, func(ret []byte) error {
		// return value should be true or false as a 32 byte array...
		if !IsZeros(ret[:31]) || ret[31] != byte(1) {
			return fmt.Errorf("Expected 1. Got %X", ret)
		}
		return nil
	})

	fmt.Println("\n#### HasRole")
	// HasRole
	snativeAddress, data = snativeRoleTestInputCALL("has_role", user[3], "bumble")
	testSNativeCALLExpectFail(t, blockCache, doug, snativeAddress, data)
	testSNativeCALLExpectPass(t, blockCache, doug, snativeAddress, data, func(ret []byte) error {
		if !IsZeros(ret[:31]) || ret[31] != byte(1) {
			return fmt.Errorf("Expected 1. Got %X", ret)
		}
		return nil
	})

	fmt.Println("\n#### AddRole")
	// AddRole
	snativeAddress, data = snativeRoleTestInputCALL("has_role", user[3], "chuck")
	testSNativeCALLExpectPass(t, blockCache, doug, snativeAddress, data, func(ret []byte) error {
		if !IsZeros(ret) {
			return fmt.Errorf("Expected 0. Got %X", ret)
		}
		return nil
	})
	snativeAddress, data = snativeRoleTestInputCALL("add_role", user[3], "chuck")
	testSNativeCALLExpectFail(t, blockCache, doug, snativeAddress, data)
	testSNativeCALLExpectPass(t, blockCache, doug, snativeAddress, data, func(ret []byte) error { return nil })
	snativeAddress, data = snativeRoleTestInputCALL("has_role", user[3], "chuck")
	testSNativeCALLExpectPass(t, blockCache, doug, snativeAddress, data, func(ret []byte) error {
		if !IsZeros(ret[:31]) || ret[31] != byte(1) {
			return fmt.Errorf("Expected 1. Got %X", ret)
		}
		return nil
	})

	fmt.Println("\n#### RmRole")
	// RmRole
	snativeAddress, data = snativeRoleTestInputCALL("rm_role", user[3], "chuck")
	testSNativeCALLExpectFail(t, blockCache, doug, snativeAddress, data)
	testSNativeCALLExpectPass(t, blockCache, doug, snativeAddress, data, func(ret []byte) error { return nil })
	snativeAddress, data = snativeRoleTestInputCALL("has_role", user[3], "chuck")
	testSNativeCALLExpectPass(t, blockCache, doug, snativeAddress, data, func(ret []byte) error {
		if !IsZeros(ret) {
			return fmt.Errorf("Expected 0. Got %X", ret)
		}
		return nil
	})
}
func TestCreateAccountPermission(t *testing.T) {
	stateDB := dbm.GetDB("state")
	genDoc := newBaseGenDoc(PermsAllFalse, PermsAllFalse)
	genDoc.Accounts[0].Permissions.Base.Set(ptypes.Send, true)          // give the 0 account permission
	genDoc.Accounts[1].Permissions.Base.Set(ptypes.Send, true)          // give the 0 account permission
	genDoc.Accounts[0].Permissions.Base.Set(ptypes.CreateAccount, true) // give the 0 account permission
	st := MakeGenesisState(stateDB, &genDoc)
	blockCache := NewBlockCache(st)

	//----------------------------------------------------------
	// SendTx to unknown account

	// A single input, having the permission, should succeed
	tx := types.NewSendTx()
	if err := tx.AddInput(blockCache, user[0].PubKey, 5); err != nil {
		t.Fatal(err)
	}
	tx.AddOutput(user[6].Address, 5)
	tx.SignInput(chainID, 0, user[0])
	if err := ExecTx(blockCache, tx, true, nil); err != nil {
		t.Fatal("Transaction failed", err)
	}

	// Two inputs, both with send, one with create, one without, should fail
	tx = types.NewSendTx()
	if err := tx.AddInput(blockCache, user[0].PubKey, 5); err != nil {
		t.Fatal(err)
	}
	if err := tx.AddInput(blockCache, user[1].PubKey, 5); err != nil {
		t.Fatal(err)
	}
	tx.AddOutput(user[7].Address, 10)
	tx.SignInput(chainID, 0, user[0])
	tx.SignInput(chainID, 1, user[1])
	if err := ExecTx(blockCache, tx, true, nil); err == nil {
		t.Fatal("Expected error")
	} else {
		fmt.Println(err)
	}

	// Two inputs, both with send, one with create, one without, two ouputs (one known, one unknown) should fail
	tx = types.NewSendTx()
	if err := tx.AddInput(blockCache, user[0].PubKey, 5); err != nil {
		t.Fatal(err)
	}
	if err := tx.AddInput(blockCache, user[1].PubKey, 5); err != nil {
		t.Fatal(err)
	}
	tx.AddOutput(user[7].Address, 4)
	tx.AddOutput(user[4].Address, 6)
	tx.SignInput(chainID, 0, user[0])
	tx.SignInput(chainID, 1, user[1])
	if err := ExecTx(blockCache, tx, true, nil); err == nil {
		t.Fatal("Expected error")
	} else {
		fmt.Println(err)
	}

	// Two inputs, both with send, both with create, should pass
	acc := blockCache.GetAccount(user[1].Address)
	acc.Permissions.Base.Set(ptypes.CreateAccount, true)
	blockCache.UpdateAccount(acc)
	tx = types.NewSendTx()
	if err := tx.AddInput(blockCache, user[0].PubKey, 5); err != nil {
		t.Fatal(err)
	}
	if err := tx.AddInput(blockCache, user[1].PubKey, 5); err != nil {
		t.Fatal(err)
	}
	tx.AddOutput(user[7].Address, 10)
	tx.SignInput(chainID, 0, user[0])
	tx.SignInput(chainID, 1, user[1])
	if err := ExecTx(blockCache, tx, true, nil); err != nil {
		t.Fatal("Unexpected error", err)
	}

	// Two inputs, both with send, both with create, two outputs (one known, one unknown) should pass
	tx = types.NewSendTx()
	if err := tx.AddInput(blockCache, user[0].PubKey, 5); err != nil {
		t.Fatal(err)
	}
	if err := tx.AddInput(blockCache, user[1].PubKey, 5); err != nil {
		t.Fatal(err)
	}
	tx.AddOutput(user[7].Address, 7)
	tx.AddOutput(user[4].Address, 3)
	tx.SignInput(chainID, 0, user[0])
	tx.SignInput(chainID, 1, user[1])
	if err := ExecTx(blockCache, tx, true, nil); err != nil {
		t.Fatal("Unexpected error", err)
	}

	//----------------------------------------------------------
	// CALL to unknown account

	acc = blockCache.GetAccount(user[0].Address)
	acc.Permissions.Base.Set(ptypes.Call, true)
	blockCache.UpdateAccount(acc)

	// call to contract that calls unknown account - without create_account perm
	// create contract that calls the simple contract
	contractCode := callContractCode(user[9].Address)
	caller1ContractAddr := NewContractAddress(user[4].Address, 101)
	caller1Acc := &acm.Account{
		Address:     caller1ContractAddr,
		Balance:     0,
		Code:        contractCode,
		Sequence:    0,
		StorageRoot: Zero256.Bytes(),
		Permissions: ptypes.ZeroAccountPermissions,
	}
	blockCache.UpdateAccount(caller1Acc)

	// A single input, having the permission, but the contract doesn't have permission
	txCall, _ := types.NewCallTx(blockCache, user[0].PubKey, caller1ContractAddr, nil, 100, 10000, 100)
	txCall.Sign(chainID, user[0])

	// we need to subscribe to the Call event to detect the exception
	_, exception := execTxWaitEvent(t, blockCache, txCall, types.EventStringAccCall(caller1ContractAddr)) //
	if exception == "" {
		t.Fatal("Expected exception")
	}

	// NOTE: for a contract to be able to CreateAccount, it must be able to call
	// NOTE: for a user to be able to CreateAccount, it must be able to send!
	caller1Acc.Permissions.Base.Set(ptypes.CreateAccount, true)
	caller1Acc.Permissions.Base.Set(ptypes.Call, true)
	blockCache.UpdateAccount(caller1Acc)
	// A single input, having the permission, but the contract doesn't have permission
	txCall, _ = types.NewCallTx(blockCache, user[0].PubKey, caller1ContractAddr, nil, 100, 10000, 100)
	txCall.Sign(chainID, user[0])

	// we need to subscribe to the Call event to detect the exception
	_, exception = execTxWaitEvent(t, blockCache, txCall, types.EventStringAccCall(caller1ContractAddr)) //
	if exception != "" {
		t.Fatal("Unexpected exception", exception)
	}

}
func TestBondPermission(t *testing.T) {
	stateDB := dbm.GetDB("state")
	genDoc := newBaseGenDoc(PermsAllFalse, PermsAllFalse)
	st := MakeGenesisState(stateDB, &genDoc)
	blockCache := NewBlockCache(st)
	var bondAcc *acm.Account

	//------------------------------
	// one bonder without permission should fail
	tx, _ := types.NewBondTx(user[1].PubKey)
	if err := tx.AddInput(blockCache, user[1].PubKey, 5); err != nil {
		t.Fatal(err)
	}
	tx.AddOutput(user[1].Address, 5)
	tx.SignInput(chainID, 0, user[1])
	tx.SignBond(chainID, user[1])
	if err := ExecTx(blockCache, tx, true, nil); err == nil {
		t.Fatal("Expected error")
	} else {
		fmt.Println(err)
	}

	//------------------------------
	// one bonder with permission should pass
	bondAcc = blockCache.GetAccount(user[1].Address)
	bondAcc.Permissions.Base.Set(ptypes.Bond, true)
	blockCache.UpdateAccount(bondAcc)
	if err := ExecTx(blockCache, tx, true, nil); err != nil {
		t.Fatal("Unexpected error", err)
	}

	// reset state (we can only bond with an account once ..)
	genDoc = newBaseGenDoc(PermsAllFalse, PermsAllFalse)
	st = MakeGenesisState(stateDB, &genDoc)
	blockCache = NewBlockCache(st)
	bondAcc = blockCache.GetAccount(user[1].Address)
	bondAcc.Permissions.Base.Set(ptypes.Bond, true)
	blockCache.UpdateAccount(bondAcc)
	//------------------------------
	// one bonder with permission and an input without send should fail
	tx, _ = types.NewBondTx(user[1].PubKey)
	if err := tx.AddInput(blockCache, user[2].PubKey, 5); err != nil {
		t.Fatal(err)
	}
	tx.AddOutput(user[1].Address, 5)
	tx.SignInput(chainID, 0, user[2])
	tx.SignBond(chainID, user[1])
	if err := ExecTx(blockCache, tx, true, nil); err == nil {
		t.Fatal("Expected error")
	} else {
		fmt.Println(err)
	}

	// reset state (we can only bond with an account once ..)
	genDoc = newBaseGenDoc(PermsAllFalse, PermsAllFalse)
	st = MakeGenesisState(stateDB, &genDoc)
	blockCache = NewBlockCache(st)
	bondAcc = blockCache.GetAccount(user[1].Address)
	bondAcc.Permissions.Base.Set(ptypes.Bond, true)
	blockCache.UpdateAccount(bondAcc)
	//------------------------------
	// one bonder with permission and an input with send should pass
	sendAcc := blockCache.GetAccount(user[2].Address)
	sendAcc.Permissions.Base.Set(ptypes.Send, true)
	blockCache.UpdateAccount(sendAcc)
	tx, _ = types.NewBondTx(user[1].PubKey)
	if err := tx.AddInput(blockCache, user[2].PubKey, 5); err != nil {
		t.Fatal(err)
	}
	tx.AddOutput(user[1].Address, 5)
	tx.SignInput(chainID, 0, user[2])
	tx.SignBond(chainID, user[1])
	if err := ExecTx(blockCache, tx, true, nil); err != nil {
		t.Fatal("Unexpected error", err)
	}

	// reset state (we can only bond with an account once ..)
	genDoc = newBaseGenDoc(PermsAllFalse, PermsAllFalse)
	st = MakeGenesisState(stateDB, &genDoc)
	blockCache = NewBlockCache(st)
	bondAcc = blockCache.GetAccount(user[1].Address)
	bondAcc.Permissions.Base.Set(ptypes.Bond, true)
	blockCache.UpdateAccount(bondAcc)
	//------------------------------
	// one bonder with permission and an input with bond should pass
	sendAcc.Permissions.Base.Set(ptypes.Bond, true)
	blockCache.UpdateAccount(sendAcc)
	tx, _ = types.NewBondTx(user[1].PubKey)
	if err := tx.AddInput(blockCache, user[2].PubKey, 5); err != nil {
		t.Fatal(err)
	}
	tx.AddOutput(user[1].Address, 5)
	tx.SignInput(chainID, 0, user[2])
	tx.SignBond(chainID, user[1])
	if err := ExecTx(blockCache, tx, true, nil); err != nil {
		t.Fatal("Unexpected error", err)
	}

	// reset state (we can only bond with an account once ..)
	genDoc = newBaseGenDoc(PermsAllFalse, PermsAllFalse)
	st = MakeGenesisState(stateDB, &genDoc)
	blockCache = NewBlockCache(st)
	bondAcc = blockCache.GetAccount(user[1].Address)
	bondAcc.Permissions.Base.Set(ptypes.Bond, true)
	blockCache.UpdateAccount(bondAcc)
	//------------------------------
	// one bonder with permission and an input from that bonder and an input without send or bond should fail
	tx, _ = types.NewBondTx(user[1].PubKey)
	if err := tx.AddInput(blockCache, user[1].PubKey, 5); err != nil {
		t.Fatal(err)
	}
	if err := tx.AddInput(blockCache, user[2].PubKey, 5); err != nil {
		t.Fatal(err)
	}
	tx.AddOutput(user[1].Address, 5)
	tx.SignInput(chainID, 0, user[1])
	tx.SignInput(chainID, 1, user[2])
	tx.SignBond(chainID, user[1])
	if err := ExecTx(blockCache, tx, true, nil); err == nil {
		t.Fatal("Expected error")
	}
}
func TestCreatePermission(t *testing.T) {
	stateDB := dbm.GetDB("state")
	genDoc := newBaseGenDoc(PermsAllFalse, PermsAllFalse)
	genDoc.Accounts[0].Permissions.Base.Set(ptypes.CreateContract, true) // give the 0 account permission
	genDoc.Accounts[0].Permissions.Base.Set(ptypes.Call, true)           // give the 0 account permission
	st := MakeGenesisState(stateDB, &genDoc)
	blockCache := NewBlockCache(st)

	//------------------------------
	// create a simple contract
	fmt.Println("\n##### CREATE SIMPLE CONTRACT")

	contractCode := []byte{0x60}
	createCode := wrapContractForCreate(contractCode)

	// A single input, having the permission, should succeed
	tx, _ := types.NewCallTx(blockCache, user[0].PubKey, nil, createCode, 100, 100, 100)
	tx.Sign(chainID, user[0])
	if err := ExecTx(blockCache, tx, true, nil); err != nil {
		t.Fatal("Transaction failed", err)
	}
	// ensure the contract is there
	contractAddr := NewContractAddress(tx.Input.Address, tx.Input.Sequence)
	contractAcc := blockCache.GetAccount(contractAddr)
	if contractAcc == nil {
		t.Fatalf("failed to create contract %X", contractAddr)
	}
	if bytes.Compare(contractAcc.Code, contractCode) != 0 {
		t.Fatalf("contract does not have correct code. Got %X, expected %X", contractAcc.Code, contractCode)
	}

	//------------------------------
	// create contract that uses the CREATE op
	fmt.Println("\n##### CREATE FACTORY")

	contractCode = []byte{0x60}
	createCode = wrapContractForCreate(contractCode)
	factoryCode := createContractCode()
	createFactoryCode := wrapContractForCreate(factoryCode)

	// A single input, having the permission, should succeed
	tx, _ = types.NewCallTx(blockCache, user[0].PubKey, nil, createFactoryCode, 100, 100, 100)
	tx.Sign(chainID, user[0])
	if err := ExecTx(blockCache, tx, true, nil); err != nil {
		t.Fatal("Transaction failed", err)
	}
	// ensure the contract is there
	contractAddr = NewContractAddress(tx.Input.Address, tx.Input.Sequence)
	contractAcc = blockCache.GetAccount(contractAddr)
	if contractAcc == nil {
		t.Fatalf("failed to create contract %X", contractAddr)
	}
	if bytes.Compare(contractAcc.Code, factoryCode) != 0 {
		t.Fatalf("contract does not have correct code. Got %X, expected %X", contractAcc.Code, factoryCode)
	}

	//------------------------------
	// call the contract (should FAIL)
	fmt.Println("\n###### CALL THE FACTORY (FAIL)")

	// A single input, having the permission, should succeed
	tx, _ = types.NewCallTx(blockCache, user[0].PubKey, contractAddr, createCode, 100, 100, 100)
	tx.Sign(chainID, user[0])
	// we need to subscribe to the Call event to detect the exception
	_, exception := execTxWaitEvent(t, blockCache, tx, types.EventStringAccCall(contractAddr)) //
	if exception == "" {
		t.Fatal("expected exception")
	}

	//------------------------------
	// call the contract (should PASS)
	fmt.Println("\n###### CALL THE FACTORY (PASS)")

	contractAcc.Permissions.Base.Set(ptypes.CreateContract, true)
	blockCache.UpdateAccount(contractAcc)

	// A single input, having the permission, should succeed
	tx, _ = types.NewCallTx(blockCache, user[0].PubKey, contractAddr, createCode, 100, 100, 100)
	tx.Sign(chainID, user[0])
	// we need to subscribe to the Call event to detect the exception
	_, exception = execTxWaitEvent(t, blockCache, tx, types.EventStringAccCall(contractAddr)) //
	if exception != "" {
		t.Fatal("unexpected exception", exception)
	}

	//--------------------------------
	fmt.Println("\n##### CALL to empty address")
	zeroAddr := LeftPadBytes([]byte{}, 20)
	code := callContractCode(zeroAddr)

	contractAddr = NewContractAddress(user[0].Address, 110)
	contractAcc = &acm.Account{
		Address:     contractAddr,
		Balance:     1000,
		Code:        code,
		Sequence:    0,
		StorageRoot: Zero256.Bytes(),
		Permissions: ptypes.ZeroAccountPermissions,
	}
	contractAcc.Permissions.Base.Set(ptypes.Call, true)
	contractAcc.Permissions.Base.Set(ptypes.CreateContract, true)
	blockCache.UpdateAccount(contractAcc)

	// this should call the 0 address but not create ...
	tx, _ = types.NewCallTx(blockCache, user[0].PubKey, contractAddr, createCode, 100, 10000, 100)
	tx.Sign(chainID, user[0])
	// we need to subscribe to the Call event to detect the exception
	_, exception = execTxWaitEvent(t, blockCache, tx, types.EventStringAccCall(zeroAddr)) //
	if exception != "" {
		t.Fatal("unexpected exception", exception)
	}
	zeroAcc := blockCache.GetAccount(zeroAddr)
	if len(zeroAcc.Code) != 0 {
		t.Fatal("the zero account was given code from a CALL!")
	}
}
func TestCallPermission(t *testing.T) {
	stateDB := dbm.GetDB("state")
	genDoc := newBaseGenDoc(PermsAllFalse, PermsAllFalse)
	genDoc.Accounts[0].Permissions.Base.Set(ptypes.Call, true) // give the 0 account permission
	st := MakeGenesisState(stateDB, &genDoc)
	blockCache := NewBlockCache(st)

	//------------------------------
	// call to simple contract
	fmt.Println("\n##### SIMPLE CONTRACT")

	// create simple contract
	simpleContractAddr := NewContractAddress(user[0].Address, 100)
	simpleAcc := &acm.Account{
		Address:     simpleContractAddr,
		Balance:     0,
		Code:        []byte{0x60},
		Sequence:    0,
		StorageRoot: Zero256.Bytes(),
		Permissions: ptypes.ZeroAccountPermissions,
	}
	st.UpdateAccount(simpleAcc)

	// A single input, having the permission, should succeed
	tx, _ := types.NewCallTx(blockCache, user[0].PubKey, simpleContractAddr, nil, 100, 100, 100)
	tx.Sign(chainID, user[0])
	if err := ExecTx(blockCache, tx, true, nil); err != nil {
		t.Fatal("Transaction failed", err)
	}

	//----------------------------------------------------------
	// call to contract that calls simple contract - without perm
	fmt.Println("\n##### CALL TO SIMPLE CONTRACT (FAIL)")

	// create contract that calls the simple contract
	contractCode := callContractCode(simpleContractAddr)
	caller1ContractAddr := NewContractAddress(user[0].Address, 101)
	caller1Acc := &acm.Account{
		Address:     caller1ContractAddr,
		Balance:     10000,
		Code:        contractCode,
		Sequence:    0,
		StorageRoot: Zero256.Bytes(),
		Permissions: ptypes.ZeroAccountPermissions,
	}
	blockCache.UpdateAccount(caller1Acc)

	// A single input, having the permission, but the contract doesn't have permission
	tx, _ = types.NewCallTx(blockCache, user[0].PubKey, caller1ContractAddr, nil, 100, 10000, 100)
	tx.Sign(chainID, user[0])

	// we need to subscribe to the Call event to detect the exception
	_, exception := execTxWaitEvent(t, blockCache, tx, types.EventStringAccCall(caller1ContractAddr)) //
	if exception == "" {
		t.Fatal("Expected exception")
	}

	//----------------------------------------------------------
	// call to contract that calls simple contract - with perm
	fmt.Println("\n##### CALL TO SIMPLE CONTRACT (PASS)")

	// A single input, having the permission, and the contract has permission
	caller1Acc.Permissions.Base.Set(ptypes.Call, true)
	blockCache.UpdateAccount(caller1Acc)
	tx, _ = types.NewCallTx(blockCache, user[0].PubKey, caller1ContractAddr, nil, 100, 10000, 100)
	tx.Sign(chainID, user[0])

	// we need to subscribe to the Call event to detect the exception
	_, exception = execTxWaitEvent(t, blockCache, tx, types.EventStringAccCall(caller1ContractAddr)) //
	if exception != "" {
		t.Fatal("Unexpected exception:", exception)
	}

	//----------------------------------------------------------
	// call to contract that calls contract that calls simple contract - without perm
	// caller1Contract calls simpleContract. caller2Contract calls caller1Contract.
	// caller1Contract does not have call perms, but caller2Contract does.
	fmt.Println("\n##### CALL TO CONTRACT CALLING SIMPLE CONTRACT (FAIL)")

	contractCode2 := callContractCode(caller1ContractAddr)
	caller2ContractAddr := NewContractAddress(user[0].Address, 102)
	caller2Acc := &acm.Account{
		Address:     caller2ContractAddr,
		Balance:     1000,
		Code:        contractCode2,
		Sequence:    0,
		StorageRoot: Zero256.Bytes(),
		Permissions: ptypes.ZeroAccountPermissions,
	}
	caller1Acc.Permissions.Base.Set(ptypes.Call, false)
	caller2Acc.Permissions.Base.Set(ptypes.Call, true)
	blockCache.UpdateAccount(caller1Acc)
	blockCache.UpdateAccount(caller2Acc)

	tx, _ = types.NewCallTx(blockCache, user[0].PubKey, caller2ContractAddr, nil, 100, 10000, 100)
	tx.Sign(chainID, user[0])

	// we need to subscribe to the Call event to detect the exception
	_, exception = execTxWaitEvent(t, blockCache, tx, types.EventStringAccCall(caller1ContractAddr)) //
	if exception == "" {
		t.Fatal("Expected exception")
	}

	//----------------------------------------------------------
	// call to contract that calls contract that calls simple contract - without perm
	// caller1Contract calls simpleContract. caller2Contract calls caller1Contract.
	// both caller1 and caller2 have permission
	fmt.Println("\n##### CALL TO CONTRACT CALLING SIMPLE CONTRACT (PASS)")

	caller1Acc.Permissions.Base.Set(ptypes.Call, true)
	blockCache.UpdateAccount(caller1Acc)

	tx, _ = types.NewCallTx(blockCache, user[0].PubKey, caller2ContractAddr, nil, 100, 10000, 100)
	tx.Sign(chainID, user[0])

	// we need to subscribe to the Call event to detect the exception
	_, exception = execTxWaitEvent(t, blockCache, tx, types.EventStringAccCall(caller1ContractAddr)) //
	if exception != "" {
		t.Fatal("Unexpected exception", exception)
	}
}
func TestCallFails(t *testing.T) {
	stateDB := dbm.GetDB("state")
	genDoc := newBaseGenDoc(PermsAllFalse, PermsAllFalse)
	genDoc.Accounts[1].Permissions.Base.Set(ptypes.Send, true)
	genDoc.Accounts[2].Permissions.Base.Set(ptypes.Call, true)
	genDoc.Accounts[3].Permissions.Base.Set(ptypes.CreateContract, true)
	st := MakeGenesisState(stateDB, &genDoc)
	blockCache := NewBlockCache(st)

	//-------------------
	// call txs

	// simple call tx should fail
	tx, _ := types.NewCallTx(blockCache, user[0].PubKey, user[4].Address, nil, 100, 100, 100)
	tx.Sign(chainID, user[0])
	if err := ExecTx(blockCache, tx, true, nil); err == nil {
		t.Fatal("Expected error")
	} else {
		fmt.Println(err)
	}

	// simple call tx with send permission should fail
	tx, _ = types.NewCallTx(blockCache, user[1].PubKey, user[4].Address, nil, 100, 100, 100)
	tx.Sign(chainID, user[1])
	if err := ExecTx(blockCache, tx, true, nil); err == nil {
		t.Fatal("Expected error")
	} else {
		fmt.Println(err)
	}

	// simple call tx with create permission should fail
	tx, _ = types.NewCallTx(blockCache, user[3].PubKey, user[4].Address, nil, 100, 100, 100)
	tx.Sign(chainID, user[3])
	if err := ExecTx(blockCache, tx, true, nil); err == nil {
		t.Fatal("Expected error")
	} else {
		fmt.Println(err)
	}

	//-------------------
	// create txs

	// simple call create tx should fail
	tx, _ = types.NewCallTx(blockCache, user[0].PubKey, nil, nil, 100, 100, 100)
	tx.Sign(chainID, user[0])
	if err := ExecTx(blockCache, tx, true, nil); err == nil {
		t.Fatal("Expected error")
	} else {
		fmt.Println(err)
	}

	// simple call create tx with send perm should fail
	tx, _ = types.NewCallTx(blockCache, user[1].PubKey, nil, nil, 100, 100, 100)
	tx.Sign(chainID, user[1])
	if err := ExecTx(blockCache, tx, true, nil); err == nil {
		t.Fatal("Expected error")
	} else {
		fmt.Println(err)
	}

	// simple call create tx with call perm should fail
	tx, _ = types.NewCallTx(blockCache, user[2].PubKey, nil, nil, 100, 100, 100)
	tx.Sign(chainID, user[2])
	if err := ExecTx(blockCache, tx, true, nil); err == nil {
		t.Fatal("Expected error")
	} else {
		fmt.Println(err)
	}
}
func TestSendFails(t *testing.T) {
	stateDB := dbm.GetDB("state")
	genDoc := newBaseGenDoc(PermsAllFalse, PermsAllFalse)
	genDoc.Accounts[1].Permissions.Base.Set(ptypes.Send, true)
	genDoc.Accounts[2].Permissions.Base.Set(ptypes.Call, true)
	genDoc.Accounts[3].Permissions.Base.Set(ptypes.CreateContract, true)
	st := MakeGenesisState(stateDB, &genDoc)
	blockCache := NewBlockCache(st)

	//-------------------
	// send txs

	// simple send tx should fail
	tx := types.NewSendTx()
	if err := tx.AddInput(blockCache, user[0].PubKey, 5); err != nil {
		t.Fatal(err)
	}
	tx.AddOutput(user[1].Address, 5)
	tx.SignInput(chainID, 0, user[0])
	if err := ExecTx(blockCache, tx, true, nil); err == nil {
		t.Fatal("Expected error")
	} else {
		fmt.Println(err)
	}

	// simple send tx with call perm should fail
	tx = types.NewSendTx()
	if err := tx.AddInput(blockCache, user[2].PubKey, 5); err != nil {
		t.Fatal(err)
	}
	tx.AddOutput(user[4].Address, 5)
	tx.SignInput(chainID, 0, user[2])
	if err := ExecTx(blockCache, tx, true, nil); err == nil {
		t.Fatal("Expected error")
	} else {
		fmt.Println(err)
	}

	// simple send tx with create perm should fail
	tx = types.NewSendTx()
	if err := tx.AddInput(blockCache, user[3].PubKey, 5); err != nil {
		t.Fatal(err)
	}
	tx.AddOutput(user[4].Address, 5)
	tx.SignInput(chainID, 0, user[3])
	if err := ExecTx(blockCache, tx, true, nil); err == nil {
		t.Fatal("Expected error")
	} else {
		fmt.Println(err)
	}

	// simple send tx to unknown account without create_account perm should fail
	acc := blockCache.GetAccount(user[3].Address)
	acc.Permissions.Base.Set(ptypes.Send, true)
	blockCache.UpdateAccount(acc)
	tx = types.NewSendTx()
	if err := tx.AddInput(blockCache, user[3].PubKey, 5); err != nil {
		t.Fatal(err)
	}
	tx.AddOutput(user[6].Address, 5)
	tx.SignInput(chainID, 0, user[3])
	if err := ExecTx(blockCache, tx, true, nil); err == nil {
		t.Fatal("Expected error")
	} else {
		fmt.Println(err)
	}
}