bond perm and tests

This commit is contained in:
Ethan Buchman
2015-05-20 19:20:06 -04:00
committed by Jae Kwon
parent 8cdb0b91e6
commit 2ec3d0611f
6 changed files with 304 additions and 182 deletions

View File

@@ -634,7 +634,12 @@ func ExecTx(blockCache *BlockCache, tx_ types.Tx, runCall bool, evc events.Firea
return err
}
if !hasBondPermission(blockCache, accounts) {
bondAcc := blockCache.GetAccount(tx.PubKey.Address())
if !hasBondPermission(blockCache, bondAcc) {
return fmt.Errorf("The bonder does not have permission to bond")
}
if !hasBondOrSendPermission(blockCache, accounts) {
return fmt.Errorf("At least one input lacks permission to bond")
}
@@ -786,18 +791,23 @@ func ExecTx(blockCache *BlockCache, tx_ types.Tx, runCall bool, evc events.Firea
}
//---------------------------------------------------------------
// TODO: for debug log the failed accounts
// Get permission on an account or fall back to global value
func HasPermission(state AccountGetter, acc *account.Account, perm ptypes.PermFlag) bool {
if acc == nil {
// TODO
// this needs to fall back to global or do some other specific things
// eg. a bondAcc may be nil and so can only bond if global bonding is true
}
v, err := acc.Permissions.Base.Get(perm)
fmt.Printf("has permission? %x %v %b %v %v\n", acc.Address, acc.Permissions, perm, v, err)
if _, ok := err.(ptypes.ErrValueNotSet); ok {
return HasPermission(state, state.GetAccount(ptypes.GlobalPermissionsAddress), perm)
}
return v
}
// TODO: for debug log the failed accounts
func hasSendPermission(state AccountGetter, accs map[string]*account.Account) bool {
for _, acc := range accs {
if !HasPermission(state, acc, ptypes.Send) {
@@ -808,23 +818,23 @@ func hasSendPermission(state AccountGetter, accs map[string]*account.Account) bo
}
func hasCallPermission(state AccountGetter, acc *account.Account) bool {
if !HasPermission(state, acc, ptypes.Call) {
return false
}
return true
return HasPermission(state, acc, ptypes.Call)
}
func hasCreatePermission(state AccountGetter, acc *account.Account) bool {
if !HasPermission(state, acc, ptypes.Create) {
return false
}
return true
return HasPermission(state, acc, ptypes.CreateContract)
}
func hasBondPermission(state AccountGetter, accs map[string]*account.Account) bool {
func hasBondPermission(state AccountGetter, acc *account.Account) bool {
return HasPermission(state, acc, ptypes.Bond)
}
func hasBondOrSendPermission(state AccountGetter, accs map[string]*account.Account) bool {
for _, acc := range accs {
if !HasPermission(state, acc, ptypes.Bond) {
return false
if !HasPermission(state, acc, ptypes.Send) {
return false
}
}
}
return true

View File

@@ -81,3 +81,47 @@ func SignCallTx(tx *types.CallTx, privAccount *account.PrivAccount) {
tx.Input.PubKey = privAccount.PubKey
tx.Input.Signature = privAccount.Sign(tx)
}
//----------------------------------------------------------------------------
// BondTx interface for adding inputs/outputs and adding signatures
func NewBondTx() *types.BondTx {
return &types.BondTx{
Inputs: []*types.TxInput{},
UnbondTo: []*types.TxOutput{},
}
}
func BondTxAddInput(st AccountGetter, tx *types.BondTx, pubkey account.PubKey, amt uint64) error {
addr := pubkey.Address()
acc := st.GetAccount(addr)
if acc == nil {
return fmt.Errorf("Invalid address %X from pubkey %X", addr, pubkey)
}
tx.Inputs = append(tx.Inputs, &types.TxInput{
Address: addr,
Amount: amt,
Sequence: uint(acc.Sequence) + 1,
Signature: account.SignatureEd25519{},
PubKey: pubkey,
})
return nil
}
func BondTxAddOutput(tx *types.BondTx, addr []byte, amt uint64) error {
tx.UnbondTo = append(tx.UnbondTo, &types.TxOutput{
Address: addr,
Amount: amt,
})
return nil
}
func SignBondTx(tx *types.BondTx, i int, privAccount *account.PrivAccount) error {
if i >= len(tx.Inputs) {
return fmt.Errorf("Index %v is greater than number of inputs (%v)", i, len(tx.Inputs))
}
tx.Inputs[i].PubKey = privAccount.PubKey
tx.Inputs[i].Signature = privAccount.Sign(tx)
return nil
}

View File

@@ -39,9 +39,12 @@ x - contract runs create but has perm
x - contract runs call with empty address (has call and create perm)
- BondTx
- 1 input, no perm
- 1 input, perm
- 2 inputs, one with perm one without
x - 1 input, no perm
x - 1 input, perm
x - 1 bonder with perm, input without send or bond
x - 1 bonder with perm, input with send
x - 1 bonder with perm, input with bond
x - 2 inputs, one with perm one without
- SendTx for new account ? CALL for new account?
@@ -103,7 +106,7 @@ func TestSendFails(t *testing.T) {
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.Create, true)
genDoc.Accounts[3].Permissions.Base.Set(ptypes.CreateContract, true)
st := MakeGenesisState(stateDB, &genDoc)
blockCache := NewBlockCache(st)
@@ -111,12 +114,12 @@ func TestSendFails(t *testing.T) {
// send txs
// simple send tx should fail
tx := NewSendTx()
if err := SendTxAddInput(blockCache, tx, user[0].PubKey, 5); err != nil {
tx := types.NewSendTx()
if err := tx.AddInput(blockCache, user[0].PubKey, 5); err != nil {
t.Fatal(err)
}
SendTxAddOutput(tx, user[1].Address, 5)
SignSendTx(tx, 0, user[0])
tx.AddOutput(user[1].Address, 5)
tx.SignInput(0, user[0])
if err := ExecTx(blockCache, tx, true, nil); err == nil {
t.Fatal("Expected error")
} else {
@@ -124,12 +127,12 @@ func TestSendFails(t *testing.T) {
}
// simple send tx with call perm should fail
tx = NewSendTx()
if err := SendTxAddInput(blockCache, tx, user[2].PubKey, 5); err != nil {
tx = types.NewSendTx()
if err := tx.AddInput(blockCache, user[2].PubKey, 5); err != nil {
t.Fatal(err)
}
SendTxAddOutput(tx, user[4].Address, 5)
SignSendTx(tx, 0, user[2])
tx.AddOutput(user[4].Address, 5)
tx.SignInput(0, user[2])
if err := ExecTx(blockCache, tx, true, nil); err == nil {
t.Fatal("Expected error")
} else {
@@ -137,12 +140,12 @@ func TestSendFails(t *testing.T) {
}
// simple send tx with create perm should fail
tx = NewSendTx()
if err := SendTxAddInput(blockCache, tx, user[3].PubKey, 5); err != nil {
tx = types.NewSendTx()
if err := tx.AddInput(blockCache, user[3].PubKey, 5); err != nil {
t.Fatal(err)
}
SendTxAddOutput(tx, user[4].Address, 5)
SignSendTx(tx, 0, user[3])
tx.AddOutput(user[4].Address, 5)
tx.SignInput(0, user[3])
if err := ExecTx(blockCache, tx, true, nil); err == nil {
t.Fatal("Expected error")
} else {
@@ -155,7 +158,7 @@ func TestCallFails(t *testing.T) {
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.Create, true)
genDoc.Accounts[3].Permissions.Base.Set(ptypes.CreateContract, true)
st := MakeGenesisState(stateDB, &genDoc)
blockCache := NewBlockCache(st)
@@ -163,8 +166,8 @@ func TestCallFails(t *testing.T) {
// call txs
// simple call tx should fail
tx, _ := NewCallTx(blockCache, user[0].PubKey, user[4].Address, nil, 100, 100, 100)
SignCallTx(tx, user[0])
tx, _ := types.NewCallTx(blockCache, user[0].PubKey, user[4].Address, nil, 100, 100, 100)
tx.Sign(user[0])
if err := ExecTx(blockCache, tx, true, nil); err == nil {
t.Fatal("Expected error")
} else {
@@ -172,8 +175,8 @@ func TestCallFails(t *testing.T) {
}
// simple call tx with send permission should fail
tx, _ = NewCallTx(blockCache, user[1].PubKey, user[4].Address, nil, 100, 100, 100)
SignCallTx(tx, user[1])
tx, _ = types.NewCallTx(blockCache, user[1].PubKey, user[4].Address, nil, 100, 100, 100)
tx.Sign(user[1])
if err := ExecTx(blockCache, tx, true, nil); err == nil {
t.Fatal("Expected error")
} else {
@@ -181,8 +184,8 @@ func TestCallFails(t *testing.T) {
}
// simple call tx with create permission should fail
tx, _ = NewCallTx(blockCache, user[3].PubKey, user[4].Address, nil, 100, 100, 100)
SignCallTx(tx, user[3])
tx, _ = types.NewCallTx(blockCache, user[3].PubKey, user[4].Address, nil, 100, 100, 100)
tx.Sign(user[3])
if err := ExecTx(blockCache, tx, true, nil); err == nil {
t.Fatal("Expected error")
} else {
@@ -193,8 +196,8 @@ func TestCallFails(t *testing.T) {
// create txs
// simple call create tx should fail
tx, _ = NewCallTx(blockCache, user[0].PubKey, nil, nil, 100, 100, 100)
SignCallTx(tx, user[0])
tx, _ = types.NewCallTx(blockCache, user[0].PubKey, nil, nil, 100, 100, 100)
tx.Sign(user[0])
if err := ExecTx(blockCache, tx, true, nil); err == nil {
t.Fatal("Expected error")
} else {
@@ -202,8 +205,8 @@ func TestCallFails(t *testing.T) {
}
// simple call create tx with send perm should fail
tx, _ = NewCallTx(blockCache, user[1].PubKey, nil, nil, 100, 100, 100)
SignCallTx(tx, user[1])
tx, _ = types.NewCallTx(blockCache, user[1].PubKey, nil, nil, 100, 100, 100)
tx.Sign(user[1])
if err := ExecTx(blockCache, tx, true, nil); err == nil {
t.Fatal("Expected error")
} else {
@@ -211,8 +214,8 @@ func TestCallFails(t *testing.T) {
}
// simple call create tx with call perm should fail
tx, _ = NewCallTx(blockCache, user[2].PubKey, nil, nil, 100, 100, 100)
SignCallTx(tx, user[2])
tx, _ = types.NewCallTx(blockCache, user[2].PubKey, nil, nil, 100, 100, 100)
tx.Sign(user[2])
if err := ExecTx(blockCache, tx, true, nil); err == nil {
t.Fatal("Expected error")
} else {
@@ -280,8 +283,8 @@ func TestCallPermission(t *testing.T) {
st.UpdateAccount(simpleAcc)
// A single input, having the permission, should succeed
tx, _ := NewCallTx(blockCache, user[0].PubKey, simpleContractAddr, nil, 100, 100, 100)
SignCallTx(tx, user[0])
tx, _ := types.NewCallTx(blockCache, user[0].PubKey, simpleContractAddr, nil, 100, 100, 100)
tx.Sign(user[0])
if err := ExecTx(blockCache, tx, true, nil); err != nil {
t.Fatal("Transaction failed", err)
}
@@ -304,8 +307,8 @@ func TestCallPermission(t *testing.T) {
blockCache.UpdateAccount(caller1Acc)
// A single input, having the permission, but the contract doesn't have permission
tx, _ = NewCallTx(blockCache, user[0].PubKey, caller1ContractAddr, nil, 100, 10000, 100)
SignCallTx(tx, user[0])
tx, _ = types.NewCallTx(blockCache, user[0].PubKey, caller1ContractAddr, nil, 100, 10000, 100)
tx.Sign(user[0])
// we need to subscribe to the Receive event to detect the exception
_, exception := execTxWaitEvent(t, blockCache, tx, types.EventStringAccReceive(caller1ContractAddr)) //
@@ -320,8 +323,8 @@ func TestCallPermission(t *testing.T) {
// A single input, having the permission, and the contract has permission
caller1Acc.Permissions.Base.Set(ptypes.Call, true)
blockCache.UpdateAccount(caller1Acc)
tx, _ = NewCallTx(blockCache, user[0].PubKey, caller1ContractAddr, nil, 100, 10000, 100)
SignCallTx(tx, user[0])
tx, _ = types.NewCallTx(blockCache, user[0].PubKey, caller1ContractAddr, nil, 100, 10000, 100)
tx.Sign(user[0])
// we need to subscribe to the Receive event to detect the exception
_, exception = execTxWaitEvent(t, blockCache, tx, types.EventStringAccReceive(caller1ContractAddr)) //
@@ -350,8 +353,8 @@ func TestCallPermission(t *testing.T) {
blockCache.UpdateAccount(caller1Acc)
blockCache.UpdateAccount(caller2Acc)
tx, _ = NewCallTx(blockCache, user[0].PubKey, caller2ContractAddr, nil, 100, 10000, 100)
SignCallTx(tx, user[0])
tx, _ = types.NewCallTx(blockCache, user[0].PubKey, caller2ContractAddr, nil, 100, 10000, 100)
tx.Sign(user[0])
// we need to subscribe to the Receive event to detect the exception
_, exception = execTxWaitEvent(t, blockCache, tx, types.EventStringAccReceive(caller1ContractAddr)) //
@@ -368,8 +371,8 @@ func TestCallPermission(t *testing.T) {
caller1Acc.Permissions.Base.Set(ptypes.Call, true)
blockCache.UpdateAccount(caller1Acc)
tx, _ = NewCallTx(blockCache, user[0].PubKey, caller2ContractAddr, nil, 100, 10000, 100)
SignCallTx(tx, user[0])
tx, _ = types.NewCallTx(blockCache, user[0].PubKey, caller2ContractAddr, nil, 100, 10000, 100)
tx.Sign(user[0])
// we need to subscribe to the Receive event to detect the exception
_, exception = execTxWaitEvent(t, blockCache, tx, types.EventStringAccReceive(caller1ContractAddr)) //
@@ -381,8 +384,8 @@ func TestCallPermission(t *testing.T) {
func TestCreatePermission(t *testing.T) {
stateDB := dbm.GetDB("state")
genDoc := newBaseGenDoc(PermsAllFalse, PermsAllFalse)
genDoc.Accounts[0].Permissions.Base.Set(ptypes.Create, true) // give the 0 account permission
genDoc.Accounts[0].Permissions.Base.Set(ptypes.Call, true) // give the 0 account permission
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)
@@ -394,8 +397,8 @@ func TestCreatePermission(t *testing.T) {
createCode := wrapContractForCreate(contractCode)
// A single input, having the permission, should succeed
tx, _ := NewCallTx(blockCache, user[0].PubKey, nil, createCode, 100, 100, 100)
SignCallTx(tx, user[0])
tx, _ := types.NewCallTx(blockCache, user[0].PubKey, nil, createCode, 100, 100, 100)
tx.Sign(user[0])
if err := ExecTx(blockCache, tx, true, nil); err != nil {
t.Fatal("Transaction failed", err)
}
@@ -419,8 +422,8 @@ func TestCreatePermission(t *testing.T) {
createFactoryCode := wrapContractForCreate(factoryCode)
// A single input, having the permission, should succeed
tx, _ = NewCallTx(blockCache, user[0].PubKey, nil, createFactoryCode, 100, 100, 100)
SignCallTx(tx, user[0])
tx, _ = types.NewCallTx(blockCache, user[0].PubKey, nil, createFactoryCode, 100, 100, 100)
tx.Sign(user[0])
if err := ExecTx(blockCache, tx, true, nil); err != nil {
t.Fatal("Transaction failed", err)
}
@@ -439,8 +442,8 @@ func TestCreatePermission(t *testing.T) {
fmt.Println("###### CALL THE FACTORY (FAIL)")
// A single input, having the permission, should succeed
tx, _ = NewCallTx(blockCache, user[0].PubKey, contractAddr, createCode, 100, 100, 100)
SignCallTx(tx, user[0])
tx, _ = types.NewCallTx(blockCache, user[0].PubKey, contractAddr, createCode, 100, 100, 100)
tx.Sign(user[0])
// we need to subscribe to the Receive event to detect the exception
_, exception := execTxWaitEvent(t, blockCache, tx, types.EventStringAccReceive(contractAddr)) //
if exception == "" {
@@ -451,12 +454,12 @@ func TestCreatePermission(t *testing.T) {
// call the contract (should PASS)
fmt.Println("###### CALL THE FACTORY (PASS)")
contractAcc.Permissions.Base.Set(ptypes.Create, true)
contractAcc.Permissions.Base.Set(ptypes.CreateContract, true)
blockCache.UpdateAccount(contractAcc)
// A single input, having the permission, should succeed
tx, _ = NewCallTx(blockCache, user[0].PubKey, contractAddr, createCode, 100, 100, 100)
SignCallTx(tx, user[0])
tx, _ = types.NewCallTx(blockCache, user[0].PubKey, contractAddr, createCode, 100, 100, 100)
tx.Sign(user[0])
// we need to subscribe to the Receive event to detect the exception
_, exception = execTxWaitEvent(t, blockCache, tx, types.EventStringAccReceive(contractAddr)) //
if exception != "" {
@@ -478,12 +481,12 @@ func TestCreatePermission(t *testing.T) {
Permissions: ptypes.NewAccountPermissions(),
}
contractAcc.Permissions.Base.Set(ptypes.Call, true)
contractAcc.Permissions.Base.Set(ptypes.Create, true)
contractAcc.Permissions.Base.Set(ptypes.CreateContract, true)
blockCache.UpdateAccount(contractAcc)
// this should call the 0 address but not create ...
tx, _ = NewCallTx(blockCache, user[0].PubKey, contractAddr, createCode, 100, 10000, 100)
SignCallTx(tx, user[0])
tx, _ = types.NewCallTx(blockCache, user[0].PubKey, contractAddr, createCode, 100, 10000, 100)
tx.Sign(user[0])
// we need to subscribe to the Receive event to detect the exception
_, exception = execTxWaitEvent(t, blockCache, tx, types.EventStringAccReceive(zeroAddr)) //
if exception != "" {
@@ -500,109 +503,122 @@ func TestBondPermission(t *testing.T) {
genDoc := newBaseGenDoc(PermsAllFalse, PermsAllFalse)
st := MakeGenesisState(stateDB, &genDoc)
blockCache := NewBlockCache(st)
var bondAcc *account.Account
//------------------------------
// a bond tx from someone without bond perm should fail
tx, _ := NewCallTx(blockCache, user[0].PubKey, nil, createCode, 100, 100, 100)
SignCallTx(tx, user[0])
// 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(0, user[1])
tx.SignBond(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("Transaction failed", err)
}
// ensure the contract is there
contractAddr := NewContractAddress(tx.Input.Address, uint64(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)
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)
//------------------------------
// create contract that uses the CREATE op
fmt.Println("##### CREATE FACTORY")
// 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(0, user[2])
tx.SignBond(user[1])
if err := ExecTx(blockCache, tx, true, nil); err == nil {
t.Fatal("Expected error")
} else {
fmt.Println(err)
}
contractCode = []byte{0x60}
createCode = wrapContractForCreate(contractCode)
factoryCode := createContractCode()
createFactoryCode := wrapContractForCreate(factoryCode)
// A single input, having the permission, should succeed
tx, _ = NewCallTx(blockCache, user[0].PubKey, nil, createFactoryCode, 100, 100, 100)
SignCallTx(tx, user[0])
// 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(0, user[2])
tx.SignBond(user[1])
if err := ExecTx(blockCache, tx, true, nil); err != nil {
t.Fatal("Transaction failed", err)
}
// ensure the contract is there
contractAddr = NewContractAddress(tx.Input.Address, uint64(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)
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)
//------------------------------
// call the contract (should FAIL)
fmt.Println("###### CALL THE FACTORY (FAIL)")
// A single input, having the permission, should succeed
tx, _ = NewCallTx(blockCache, user[0].PubKey, contractAddr, createCode, 100, 100, 100)
SignCallTx(tx, user[0])
// we need to subscribe to the Receive event to detect the exception
_, exception := execTxWaitEvent(t, blockCache, tx, types.EventStringAccReceive(contractAddr)) //
if exception == "" {
t.Fatal("expected exception")
// 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(0, user[2])
tx.SignBond(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)
//------------------------------
// call the contract (should PASS)
fmt.Println("###### CALL THE FACTORY (PASS)")
contractAcc.Permissions.Base.Set(ptypes.Create, true)
blockCache.UpdateAccount(contractAcc)
// A single input, having the permission, should succeed
tx, _ = NewCallTx(blockCache, user[0].PubKey, contractAddr, createCode, 100, 100, 100)
SignCallTx(tx, user[0])
// we need to subscribe to the Receive event to detect the exception
_, exception = execTxWaitEvent(t, blockCache, tx, types.EventStringAccReceive(contractAddr)) //
if exception != "" {
t.Fatal("unexpected exception", exception)
// 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)
}
//--------------------------------
fmt.Println("##### CALL to empty address")
zeroAddr := LeftPadBytes([]byte{}, 20)
code := callContractCode(zeroAddr)
contractAddr = NewContractAddress(user[0].Address, 110)
contractAcc = &account.Account{
Address: contractAddr,
Balance: 1000,
Code: code,
Sequence: 0,
StorageRoot: Zero256.Bytes(),
Permissions: ptypes.NewAccountPermissions(),
if err := tx.AddInput(blockCache, user[2].PubKey, 5); err != nil {
t.Fatal(err)
}
contractAcc.Permissions.Base.Set(ptypes.Call, true)
contractAcc.Permissions.Base.Set(ptypes.Create, true)
blockCache.UpdateAccount(contractAcc)
// this should call the 0 address but not create ...
tx, _ = NewCallTx(blockCache, user[0].PubKey, contractAddr, createCode, 100, 10000, 100)
SignCallTx(tx, user[0])
// we need to subscribe to the Receive event to detect the exception
_, exception = execTxWaitEvent(t, blockCache, tx, types.EventStringAccReceive(zeroAddr)) //
if exception != "" {
t.Fatal("unexpected exception", exception)
tx.AddOutput(user[1].Address, 5)
tx.SignInput(0, user[1])
tx.SignInput(1, user[2])
tx.SignBond(user[1])
if err := ExecTx(blockCache, tx, true, nil); err == nil {
t.Fatal("Expected error")
}
zeroAcc := blockCache.GetAccount(zeroAddr)
if len(zeroAcc.Code) != 0 {
t.Fatal("the zero account was given code from a CALL!")
}
}
//-------------------------------------------------------------------------------------