Repository: dusk-network/dusk-blockchain (go)

Issue:
Invalid state root after TX with empty payload
**Describe the bug**
After sending a tx with empty payload, dusk-blockchain panic and it's not able to restart anymore.

The "Accept"/"Finalize" calls still depend on the "persist" method to work properly.
In this case, while accepting a block, the `Finalize` method on rusk was called, but the block was not saved on the dusk-blockchain data due to an error while decoding the tx payload.

**To Reproduce**
Send an InterContractCall txs with empty `()` payload

**Expected behaviour**
Everything should work

**Logs/Screenshot**
dusk.err
```
panic: runtime error: index out of range [0] with length 0

goroutine 314620 [running]:
github.com/dusk-network/dusk-blockchain/pkg/core/data/ipc/transactions.shouldUpdateProvisioners(0xc0002beab0, {0xc001f4d5d0, 0x1, 0xc00179cb28})
        /home/runner/work/dusk-deployer/dusk-deployer/dusk-blockchain/pkg/core/data/ipc/transactions/provider.go:237 +0x105
github.com/dusk-network/dusk-blockchain/pkg/core/data/ipc/transactions.(*executor).Finalize(0xc001cf8ce8, {0x1037198, 0xc000296700}, {0xc001f4cb50, 0x1, 0x0}, {0x0, 0x0, 0x0}, 0xe9e0, ...)
        /home/runner/work/dusk-deployer/dusk-deployer/dusk-blockchain/pkg/core/data/ipc/transactions/provider.go:198 +0x1ce
github.com/dusk-network/dusk-blockchain/pkg/core/chain.(*Chain).runStateTransition(0xc0001e5440, {0xc000145440, {0x16a8200, 0xc00108b830, 0xc001fd7a40}}, {0xc001975200, {0xc001f4cb50, 0x1, 0x1}})
        /home/runner/work/dusk-deployer/dusk-deployer/dusk-blockchain/pkg/core/chain/chain.go:450 +0x80a
github.com/dusk-network/dusk-blockchain/pkg/core/chain.(*Chain).acceptBlock(0xc0001e5440, {0xc001975200, {0xc001f4cb50, 0x1, 0x1}}, 0xe0)
        /home/runner/work/dusk-deployer/dusk-deployer/dusk-blockchain/pkg/core/chain/chain.go:624 +0x5a6
github.com/dusk-network/dusk-blockchain/pkg/core/chain.(*Chain).acceptSuccessiveBlock(0xc0001e5440, {0xc001975200, {0xc001f4cb50, 0x20, 0x20}}, 0xc000fd4600)
        /home/runner/work/dusk-deployer/dusk-deployer/dusk-blockchain/pkg/core/chain/chain.go:402 +0x58f
github.com/dusk-network/dusk-blockchain/pkg/core/chain.(*Chain).TryNextConsecutiveBlockInSync(0x0, {0xc001975200, {0xc001f4cb50, 0x539b3e, 0xe9db}}, 0xc000277c4b)
        /home/runner/work/dusk-deployer/dusk-deployer/dusk-blockchain/pkg/core/chain/chain.go:337 +0x45
github.com/dusk-network/dusk-blockchain/pkg/core/chain.(*synchronizer).inSync(0x0, {0xc001630df8, 0x0}, 0x0, {0xc001975200, {0xc001f4cb50, 0x0, 0x0}}, 0x0)
        /home/runner/work/dusk-deployer/dusk-deployer/dusk-blockchain/pkg/core/chain/synchronizer.go:51 +0x286
github.com/dusk-network/dusk-blockchain/pkg/core/chain.(*synchronizer).processBlock(0xc0002aea00, {0xc001630df8, 0x12}, 0x5, {0xc001975200, {0xc001f4cb50, 0xc0011fb680, 0xc001974d80}}, 0x1037908)
        /home/runner/work/dusk-deployer/dusk-deployer/dusk-blockchain/pkg/core/chain/synchronizer.go:180 +0xc3
github.com/dusk-network/dusk-blockchain/pkg/core/chain.(*Chain).ProcessBlockFromNetwork(0xc0001e5440, {0xc001630df8, 0x12}, {0x103e200, 0xc0018d7380})
        /home/runner/work/dusk-deployer/dusk-deployer/dusk-blockchain/pkg/core/chain/chain.go:322 +0xb25
github.com/dusk-network/dusk-blockchain/pkg/p2p/peer.(*MessageProcessor).process(0xc0002be600, {0xc001630df8, 0x12}, {0x103e200, 0xc0018d7380}, 0x0, 0x203000)
        /home/runner/work/dusk-deployer/dusk-deployer/dusk-blockchain/pkg/p2p/peer/processor.go:123 +0x1ab
github.com/dusk-network/dusk-blockchain/pkg/p2p/peer.(*MessageProcessor).Collect(0xc0002be600, {0xc001630df8, 0x12}, {0xc001aeb804, 0x79a, 0x79a}, 0x0, 0xa98, 0xc00056c440)
        /home/runner/work/dusk-deployer/dusk-deployer/dusk-blockchain/pkg/p2p/peer/processor.go:66 +0x365
github.com/dusk-network/dusk-blockchain/pkg/p2p/kadcast.(*Reader).processMessage(0xc00037c800, 0xc000eeb360)
        /home/runner/work/dusk-deployer/dusk-deployer/dusk-blockchain/pkg/p2p/kadcast/reader.go:106 +0x3d7
created by github.com/dusk-network/dusk-blockchain/pkg/p2p/kadcast.(*Reader).Listen.func1
        /home/runner/work/dusk-deployer/dusk-deployer/dusk-blockchain/pkg/p2p/kadcast/reader.go:71 +0x3f
```

**Additional context**
See also #1530 

Pull request:
Fix acceptance of txs with empty payload
Resolves #1532

Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 6f7dd295..70f3fe22 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -13,10 +13,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 ### Changed
 - Change rusk-version compatibility to `0.6.0` [#1514]
 - Change TX decode to support new phoenix structure [#1529]
+- Use constant Committee Size [#1520]
 
 ### Removed
 - Remove `step` from block header certificate [#1500]
 
+### Fixed
+- Fix acceptance of txs with empty payload [#1532]
+
 ## [0.6.1] - 2022-12-21 
 
 ### Added
@@ -102,7 +106,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 
 <!-- Issues -->
 
-[#1529]: https://github.com/dusk-network/dusk-blockchain/issues/1520
+[#1532]: https://github.com/dusk-network/dusk-blockchain/issues/1532
+[#1529]: https://github.com/dusk-network/dusk-blockchain/issues/1529
+[#1520]: https://github.com/dusk-network/dusk-blockchain/issues/1520
 [#1514]: https://github.com/dusk-network/dusk-blockchain/issues/1514
 [#1500]: https://github.com/dusk-network/dusk-blockchain/issues/1500
 [#1499]: https://github.com/dusk-network/dusk-blockchain/issues/1499
diff --git a/pkg/core/data/ipc/transactions/provider.go b/pkg/core/data/ipc/transactions/provider.go
index 72d07872..7cb81b36 100644
--- a/pkg/core/data/ipc/transactions/provider.go
+++ b/pkg/core/data/ipc/transactions/provider.go
@@ -7,6 +7,7 @@
 package transactions
 
 import (
+	"bytes"
 	"context"
 	"encoding/hex"
 	"errors"
@@ -220,25 +221,36 @@ func (e *executor) Finalize(ctx context.Context, calls []ContractCall, stateRoot
 	return resCalls, *provisioners, res.StateRoot, nil
 }
 
+// STAKE_CONTRACT_ID is the byte representation of the ModuleID of the StakeContract.
+var STAKE_CONTRACT_ID = []byte{0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
+
+// TX_STAKE is the byte representation of the string `stake`.
+var TX_STAKE = []byte("stake")
+
+// TX_UNSTAKE is the byte representation of the string "unstake".
+var TX_UNSTAKE = []byte("unstake")
+
 func shouldUpdateProvisioners(blockHeight uint64, txs []ContractCall) bool {
 	if blockHeight%config.EPOCH == 0 {
 		return true
 	}
 
-	const TX_STAKE = byte(0x00)
-	const TX_UNSTAKE = byte(0x01)
-
 	for _, tx := range txs {
 		if tx.TxError() != nil {
 			continue
 		}
 
 		if payload, err := tx.Decode(); err == nil && payload.Call != nil {
-			switch payload.Call.CallData[0] {
-			case TX_STAKE, TX_UNSTAKE:
-				{
-					return true
-				}
+			if !bytes.Equal(payload.Call.ContractID, STAKE_CONTRACT_ID) {
+				continue
+			}
+
+			if !bytes.Equal(payload.Call.FnName, TX_STAKE) {
+				return true
+			}
+
+			if !bytes.Equal(payload.Call.FnName, TX_UNSTAKE) {
+				return true
 			}
 		}
 	}


Test patch:
diff --git a/pkg/p2p/wire/message/transactions_test.go b/pkg/p2p/wire/message/transactions_test.go
index da04c8ac..ea8fc2c5 100644
--- a/pkg/p2p/wire/message/transactions_test.go
+++ b/pkg/p2p/wire/message/transactions_test.go
@@ -148,6 +148,9 @@ func TestStakeTransaction(t *testing.T) {
 	assert.NotZero(decoded.Fee.GasPrice, "GasPrice should not be 0")
 	assert.NotEmpty(decoded.Nullifiers, "Nullifiers should be present")
 
+	assert.EqualValues(transactions.STAKE_CONTRACT_ID, decoded.Call.ContractID, "Contract id invalid")
+	assert.EqualValues(transactions.TX_STAKE, decoded.Call.FnName, "FnName id invalid")
+
 	hash, err := decoded.Hash(txdummy.TxType)
 	if err != nil {
 		t.Fatalf("Unable to calculate hash for staking: %v", err)