scripts: implement script for creating dumps

This is useful for creating dumps providing various load
to benchmark restore or check compatibility with C# nodes.

Related #1472.
This commit is contained in:
Evgenii Stratonikov 2020-11-23 14:09:45 +03:00
parent 6f7284906a
commit 67f26859a8
9 changed files with 312 additions and 76 deletions

View file

@ -0,0 +1,88 @@
package testchain
import (
"encoding/json"
gio "io"
"github.com/nspcc-dev/neo-go/pkg/compiler"
"github.com/nspcc-dev/neo-go/pkg/config/netmode"
"github.com/nspcc-dev/neo-go/pkg/core/blockchainer"
"github.com/nspcc-dev/neo-go/pkg/core/fee"
"github.com/nspcc-dev/neo-go/pkg/core/interop/interopnames"
"github.com/nspcc-dev/neo-go/pkg/core/native"
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
"github.com/nspcc-dev/neo-go/pkg/io"
"github.com/nspcc-dev/neo-go/pkg/util"
"github.com/nspcc-dev/neo-go/pkg/vm/emit"
"github.com/nspcc-dev/neo-go/pkg/vm/opcode"
)
var (
ownerHash = MultisigScriptHash()
ownerScript = MultisigVerificationScript()
)
// NewTransferFromOwner returns transaction transfering funds from NEO and GAS owner.
func NewTransferFromOwner(bc blockchainer.Blockchainer, contractHash, to util.Uint160, amount int64,
nonce, validUntil uint32) (*transaction.Transaction, error) {
w := io.NewBufBinWriter()
emit.AppCallWithOperationAndArgs(w.BinWriter, contractHash, "transfer", ownerHash, to, amount, nil)
emit.Opcodes(w.BinWriter, opcode.ASSERT)
if w.Err != nil {
return nil, w.Err
}
script := w.Bytes()
tx := transaction.New(netmode.UnitTestNet, script, 10000000)
tx.ValidUntilBlock = validUntil
tx.Nonce = nonce
tx.Signers = []transaction.Signer{{
Account: ownerHash,
Scopes: transaction.CalledByEntry,
AllowedContracts: nil,
AllowedGroups: nil,
}}
return tx, SignTx(bc, tx)
}
// NewDeployTx returns new deployment tx for contract with name with Go code read from r.
func NewDeployTx(name string, r gio.Reader) (*transaction.Transaction, []byte, error) {
avm, di, err := compiler.CompileWithDebugInfo(name, r)
if err != nil {
return nil, nil, err
}
w := io.NewBufBinWriter()
m, err := di.ConvertToManifest(name, nil)
if err != nil {
return nil, nil, err
}
bs, err := json.Marshal(m)
if err != nil {
return nil, nil, err
}
emit.Bytes(w.BinWriter, bs)
emit.Bytes(w.BinWriter, avm)
emit.Syscall(w.BinWriter, interopnames.SystemContractCreate)
if w.Err != nil {
return nil, nil, err
}
return transaction.New(Network(), w.Bytes(), 100*native.GASFactor), avm, nil
}
// SignTx signs provided transactions with validator keys.
func SignTx(bc blockchainer.Blockchainer, txs ...*transaction.Transaction) error {
for _, tx := range txs {
size := io.GetVarSize(tx)
netFee, sizeDelta := fee.Calculate(ownerScript)
tx.NetworkFee += netFee
size += sizeDelta
tx.NetworkFee += int64(size) * bc.FeePerByte()
data := tx.GetSignedPart()
tx.Scripts = []transaction.Witness{{
InvocationScript: Sign(data),
VerificationScript: ownerScript,
}}
}
return nil
}

View file

@ -133,7 +133,7 @@ func TestAddBlockStateRoot(t *testing.T) {
tx := newNEP17Transfer(bc.contracts.NEO.Hash, neoOwner, util.Uint160{}, 1)
tx.ValidUntilBlock = bc.BlockHeight() + 1
addSigners(tx)
require.NoError(t, signTx(bc, tx))
require.NoError(t, testchain.SignTx(bc, tx))
lastBlock := bc.topBlock.Load().(*block.Block)
b := newBlock(bc.config, lastBlock.Index+1, lastBlock.Hash(), tx)
@ -159,7 +159,7 @@ func TestAddBadBlock(t *testing.T) {
Account: testchain.MultisigScriptHash(),
Scopes: transaction.None,
}}
require.NoError(t, signTx(bc, tx))
require.NoError(t, testchain.SignTx(bc, tx))
b1 := bc.newBlock(tx)
require.Error(t, bc.AddBlock(b1))
@ -179,7 +179,7 @@ func TestAddBadBlock(t *testing.T) {
Account: testchain.MultisigScriptHash(),
Scopes: transaction.None,
}}
require.NoError(t, signTx(bc, tx))
require.NoError(t, testchain.SignTx(bc, tx))
require.NoError(t, bc.PoolTx(tx))
bc.config.VerifyTransactions = true
bc.config.VerifyBlocks = true
@ -192,7 +192,7 @@ func TestGetHeader(t *testing.T) {
tx := transaction.New(netmode.UnitTestNet, []byte{byte(opcode.PUSH1)}, 0)
tx.ValidUntilBlock = bc.BlockHeight() + 1
addSigners(tx)
assert.Nil(t, signTx(bc, tx))
assert.Nil(t, testchain.SignTx(bc, tx))
block := bc.newBlock(tx)
err := bc.AddBlock(block)
assert.Nil(t, err)
@ -277,7 +277,7 @@ func TestVerifyTx(t *testing.T) {
txMove := bc.newTestTx(neoOwner, w.Bytes())
txMove.SystemFee = 1_000_000_000
require.NoError(t, signTx(bc, txMove))
require.NoError(t, testchain.SignTx(bc, txMove))
b := bc.newBlock(txMove)
require.NoError(t, bc.AddBlock(b))
@ -805,12 +805,12 @@ func TestMemPoolRemoval(t *testing.T) {
notAddedTxes := make([]*transaction.Transaction, notAdded)
for i := range addedTxes {
addedTxes[i] = bc.newTestTx(testchain.MultisigScriptHash(), []byte{byte(opcode.PUSH1)})
require.NoError(t, signTx(bc, addedTxes[i]))
require.NoError(t, testchain.SignTx(bc, addedTxes[i]))
require.NoError(t, bc.PoolTx(addedTxes[i]))
}
for i := range notAddedTxes {
notAddedTxes[i] = bc.newTestTx(testchain.MultisigScriptHash(), []byte{byte(opcode.PUSH1)})
require.NoError(t, signTx(bc, notAddedTxes[i]))
require.NoError(t, testchain.SignTx(bc, notAddedTxes[i]))
require.NoError(t, bc.PoolTx(notAddedTxes[i]))
}
b := bc.newBlock(addedTxes...)
@ -854,7 +854,7 @@ func TestGetTransaction(t *testing.T) {
Account: testchain.MultisigScriptHash(),
Scopes: transaction.CalledByEntry,
}}
require.NoError(t, signTx(bc, tx1, tx2))
require.NoError(t, testchain.SignTx(bc, tx1, tx2))
b1 := bc.newBlock(tx1)
assert.Nil(t, bc.AddBlock(b1))
@ -955,7 +955,7 @@ func TestSubscriptions(t *testing.T) {
txGood1.Signers = []transaction.Signer{{Account: neoOwner}}
txGood1.Nonce = 1
txGood1.ValidUntilBlock = 1024
require.NoError(t, signTx(bc, txGood1))
require.NoError(t, testchain.SignTx(bc, txGood1))
// Reset() reuses the script buffer and we need to keep scripts.
script = io.NewBufBinWriter()
@ -967,7 +967,7 @@ func TestSubscriptions(t *testing.T) {
txBad.Signers = []transaction.Signer{{Account: neoOwner}}
txBad.Nonce = 2
txBad.ValidUntilBlock = 1024
require.NoError(t, signTx(bc, txBad))
require.NoError(t, testchain.SignTx(bc, txBad))
script = io.NewBufBinWriter()
emit.Bytes(script.BinWriter, []byte("yay! yay! yay!"))
@ -977,7 +977,7 @@ func TestSubscriptions(t *testing.T) {
txGood2.Signers = []transaction.Signer{{Account: neoOwner}}
txGood2.Nonce = 3
txGood2.ValidUntilBlock = 1024
require.NoError(t, signTx(bc, txGood2))
require.NoError(t, testchain.SignTx(bc, txGood2))
invBlock := newBlock(bc.config, bc.BlockHeight()+1, bc.CurrentHeaderHash(), txGood1, txBad, txGood2)
require.NoError(t, bc.AddBlock(invBlock))

View file

@ -13,12 +13,10 @@ import (
"github.com/nspcc-dev/neo-go/internal/testchain"
"github.com/nspcc-dev/neo-go/internal/testserdes"
"github.com/nspcc-dev/neo-go/pkg/compiler"
"github.com/nspcc-dev/neo-go/pkg/config"
"github.com/nspcc-dev/neo-go/pkg/core/block"
"github.com/nspcc-dev/neo-go/pkg/core/chaindump"
"github.com/nspcc-dev/neo-go/pkg/core/fee"
"github.com/nspcc-dev/neo-go/pkg/core/interop/interopnames"
"github.com/nspcc-dev/neo-go/pkg/core/native"
"github.com/nspcc-dev/neo-go/pkg/core/storage"
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
@ -239,27 +237,13 @@ func initBasicChain(t *testing.T, bc *Blockchain) {
require.Equal(t, big.NewInt(5000_0000), bc.GetUtilityTokenBalance(priv0ScriptHash)) // gas bounty
// Move some NEO to one simple account.
txMoveNeo := newNEP17Transfer(neoHash, neoOwner, priv0ScriptHash, neoAmount)
txMoveNeo.ValidUntilBlock = validUntilBlock
txMoveNeo.Nonce = getNextNonce()
txMoveNeo.Signers = []transaction.Signer{{
Account: neoOwner,
Scopes: transaction.CalledByEntry,
AllowedContracts: nil,
AllowedGroups: nil,
}}
require.NoError(t, signTx(bc, txMoveNeo))
txMoveNeo, err := testchain.NewTransferFromOwner(bc, neoHash, priv0ScriptHash, neoAmount, getNextNonce(), validUntilBlock)
require.NoError(t, err)
// Move some GAS to one simple account.
txMoveGas := newNEP17Transfer(gasHash, neoOwner, priv0ScriptHash, int64(util.Fixed8FromInt64(1000)))
txMoveGas.ValidUntilBlock = validUntilBlock
txMoveGas.Nonce = getNextNonce()
txMoveGas.Signers = []transaction.Signer{{
Account: neoOwner,
Scopes: transaction.CalledByEntry,
AllowedContracts: nil,
AllowedGroups: nil,
}}
require.NoError(t, signTx(bc, txMoveGas))
txMoveGas, err := testchain.NewTransferFromOwner(bc, gasHash, priv0ScriptHash, int64(util.Fixed8FromInt64(1000)),
getNextNonce(), validUntilBlock)
require.NoError(t, err)
b := bc.newBlock(txMoveNeo, txMoveGas)
require.NoError(t, bc.AddBlock(b))
t.Logf("Block1 hash: %s", b.Hash().StringLE())
@ -392,22 +376,12 @@ func newNEP17Transfer(sc, from, to util.Uint160, amount int64) *transaction.Tran
func newDeployTx(t *testing.T, name, ctrName string) (*transaction.Transaction, []byte) {
c, err := ioutil.ReadFile(name)
require.NoError(t, err)
avm, di, err := compiler.CompileWithDebugInfo(name, bytes.NewReader(c))
tx, avm, err := testchain.NewDeployTx(ctrName, bytes.NewReader(c))
require.NoError(t, err)
t.Logf("contractHash (%s): %s", name, hash.Hash160(avm).StringLE())
t.Logf("contractScript: %x", avm)
script := io.NewBufBinWriter()
m, err := di.ConvertToManifest(ctrName, nil)
require.NoError(t, err)
bs, err := json.Marshal(m)
require.NoError(t, err)
emit.Bytes(script.BinWriter, bs)
emit.Bytes(script.BinWriter, avm)
emit.Syscall(script.BinWriter, interopnames.SystemContractCreate)
txScript := script.Bytes()
return transaction.New(testchain.Network(), txScript, 100*native.GASFactor), avm
return tx, avm
}
func addSigners(txs ...*transaction.Transaction) {
@ -421,27 +395,6 @@ func addSigners(txs ...*transaction.Transaction) {
}
}
func signTx(bc *Blockchain, txs ...*transaction.Transaction) error {
validators := bc.GetStandByValidators()
rawScript, err := smartcontract.CreateDefaultMultiSigRedeemScript(validators)
if err != nil {
return fmt.Errorf("failed to sign tx: %w", err)
}
for _, tx := range txs {
size := io.GetVarSize(tx)
netFee, sizeDelta := fee.Calculate(rawScript)
tx.NetworkFee += netFee
size += sizeDelta
tx.NetworkFee += int64(size) * bc.FeePerByte()
data := tx.GetSignedPart()
tx.Scripts = []transaction.Witness{{
InvocationScript: testchain.Sign(data),
VerificationScript: rawScript,
}}
}
return nil
}
func addNetworkFee(bc *Blockchain, tx *transaction.Transaction, sender *wallet.Account) error {
size := io.GetVarSize(tx)
netFee, sizeDelta := fee.Calculate(sender.Contract.Script)

View file

@ -4,6 +4,7 @@ import (
"math/big"
"testing"
"github.com/nspcc-dev/neo-go/internal/testchain"
"github.com/nspcc-dev/neo-go/pkg/config/netmode"
"github.com/nspcc-dev/neo-go/pkg/core/dao"
"github.com/nspcc-dev/neo-go/pkg/core/interop"
@ -164,13 +165,13 @@ func TestNativeContract_Invoke(t *testing.T) {
validUntil := chain.blockHeight + 1
tx.ValidUntilBlock = validUntil
addSigners(tx)
require.NoError(t, signTx(chain, tx))
require.NoError(t, testchain.SignTx(chain, tx))
// Enough for Call and other opcodes, but not enough for "sum" call.
tx2 := transaction.New(chain.GetConfig().Magic, script, testSumPrice*2+8000)
tx2.ValidUntilBlock = chain.blockHeight + 1
addSigners(tx2)
require.NoError(t, signTx(chain, tx2))
require.NoError(t, testchain.SignTx(chain, tx2))
b := chain.newBlock(tx, tx2)
require.NoError(t, chain.AddBlock(b))
@ -262,7 +263,7 @@ func TestNativeContract_InvokeOtherContract(t *testing.T) {
validUntil := chain.blockHeight + 1
tx.ValidUntilBlock = validUntil
addSigners(tx)
require.NoError(t, signTx(chain, tx))
require.NoError(t, testchain.SignTx(chain, tx))
b := chain.newBlock(tx)
require.NoError(t, chain.AddBlock(b))
@ -289,7 +290,7 @@ func TestAllContractsHaveName(t *testing.T) {
tx := transaction.New(netmode.UnitTestNet, w.Bytes(), 1015570)
tx.ValidUntilBlock = bc.blockHeight + 1
addSigners(tx)
require.NoError(t, signTx(bc, tx))
require.NoError(t, testchain.SignTx(bc, tx))
require.NoError(t, bc.AddBlock(bc.newBlock(tx)))
aers, err := bc.GetAppExecResults(tx.Hash(), trigger.Application)

View file

@ -46,7 +46,7 @@ func (bc *Blockchain) setNodesByRole(t *testing.T, ok bool, r native.Role, nodes
Scopes: transaction.CalledByEntry,
},
}
require.NoError(t, signTx(bc, tx))
require.NoError(t, testchain.SignTx(bc, tx))
tx.Scripts = append(tx.Scripts, transaction.Witness{
InvocationScript: testchain.SignCommittee(tx.GetSignedPart()),
VerificationScript: testchain.CommitteeVerificationScript(),
@ -77,7 +77,7 @@ func (bc *Blockchain) getNodesByRole(t *testing.T, ok bool, r native.Role, index
Scopes: transaction.None,
},
}
require.NoError(t, signTx(bc, tx))
require.NoError(t, testchain.SignTx(bc, tx))
require.NoError(t, bc.AddBlock(bc.newBlock(tx)))
aer, err := bc.GetAppExecResults(tx.Hash(), trigger.Application)

View file

@ -87,7 +87,7 @@ func TestNEO_Vote(t *testing.T) {
tx := transaction.New(netmode.UnitTestNet, w.Bytes(), 1000_000_000)
tx.ValidUntilBlock = bc.BlockHeight() + 1
setSigner(tx, testchain.MultisigScriptHash())
require.NoError(t, signTx(bc, tx))
require.NoError(t, testchain.SignTx(bc, tx))
txs = append(txs, tx)
}
require.NoError(t, bc.AddBlock(bc.newBlock(txs...)))
@ -318,7 +318,7 @@ func TestNEO_TransferOnPayment(t *testing.T) {
tx.NetworkFee = 10_000_000
tx.ValidUntilBlock = bc.BlockHeight() + 1
addSigners(tx)
require.NoError(t, signTx(bc, tx))
require.NoError(t, testchain.SignTx(bc, tx))
require.NoError(t, bc.AddBlock(bc.newBlock(tx)))
aer, err := bc.GetAppExecResults(tx.Hash(), trigger.Application)

View file

@ -104,7 +104,7 @@ func putOracleRequest(t *testing.T, h util.Uint160, bc *Blockchain,
tx.ValidUntilBlock = bc.BlockHeight() + 1
tx.NetworkFee = 1_000_000
setSigner(tx, testchain.MultisigScriptHash())
require.NoError(t, signTx(bc, tx))
require.NoError(t, testchain.SignTx(bc, tx))
require.NoError(t, bc.AddBlock(bc.newBlock(tx)))
return tx.Hash()
}

View file

@ -5,6 +5,7 @@ import (
"testing"
"github.com/nspcc-dev/neo-go/internal/random"
"github.com/nspcc-dev/neo-go/internal/testchain"
"github.com/nspcc-dev/neo-go/pkg/core/block"
"github.com/nspcc-dev/neo-go/pkg/core/native"
"github.com/nspcc-dev/neo-go/pkg/core/state"
@ -231,7 +232,7 @@ func invokeNativePolicyMethod(chain *Blockchain, method string, args ...interfac
validUntil := chain.blockHeight + 1
tx.ValidUntilBlock = validUntil
addSigners(tx)
err := signTx(chain, tx)
err := testchain.SignTx(chain, tx)
if err != nil {
return nil, err
}

193
scripts/gendump/main.go Normal file
View file

@ -0,0 +1,193 @@
package main
import (
"crypto/rand"
"errors"
"flag"
"fmt"
"os"
"strings"
"time"
"github.com/nspcc-dev/neo-go/internal/testchain"
"github.com/nspcc-dev/neo-go/pkg/config"
"github.com/nspcc-dev/neo-go/pkg/config/netmode"
"github.com/nspcc-dev/neo-go/pkg/core"
"github.com/nspcc-dev/neo-go/pkg/core/block"
"github.com/nspcc-dev/neo-go/pkg/core/chaindump"
"github.com/nspcc-dev/neo-go/pkg/core/native"
"github.com/nspcc-dev/neo-go/pkg/core/storage"
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
"github.com/nspcc-dev/neo-go/pkg/crypto/hash"
"github.com/nspcc-dev/neo-go/pkg/io"
"github.com/nspcc-dev/neo-go/pkg/smartcontract"
"github.com/nspcc-dev/neo-go/pkg/vm/emit"
"github.com/nspcc-dev/neo-go/pkg/wallet"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
)
// Takes 1 minute for 100 tx per block and 5000 blocks.
const (
defaultBlockCount = 5000
defaultTxPerBlock = 100
)
var (
outFile = flag.String("out", "", "filename to write dump to")
blockCount = flag.Uint("blocks", defaultBlockCount, "number of blocks to generate")
txPerBlock = flag.Uint("txs", defaultTxPerBlock, "number of blocks to generate")
)
func main() {
flag.Parse()
if *outFile == "" {
handleError("", errors.New("output file is not provided"))
}
outStream, err := os.Create(*outFile) // fail early
handleError("can't open output file", err)
defer outStream.Close()
const contract = `
package contract
import "github.com/nspcc-dev/neo-go/pkg/interop/storage"
var ctx = storage.GetContext()
func Put(key, value []byte) {
storage.Put(ctx, key, value)
}`
acc, err := wallet.NewAccount()
handleError("can't create new account", err)
h := acc.Contract.ScriptHash()
bc, err := newChain()
handleError("can't initialize blockchain", err)
valScript, err := smartcontract.CreateDefaultMultiSigRedeemScript(bc.GetStandByValidators())
handleError("can't create verification script", err)
lastBlock, err := bc.GetBlock(bc.GetHeaderHash(int(bc.BlockHeight())))
handleError("can't fetch last block", err)
txMoveNeo, err := testchain.NewTransferFromOwner(bc, bc.GoverningTokenHash(), h, native.NEOTotalSupply, 0, 2)
handleError("can't transfer NEO", err)
txMoveGas, err := testchain.NewTransferFromOwner(bc, bc.UtilityTokenHash(), h, 2_000_000_000_000_000, 0, 2)
handleError("can't tranfser GAS", err)
lastBlock = addBlock(bc, lastBlock, valScript, txMoveNeo, txMoveGas)
tx, avm, err := testchain.NewDeployTx("DumpContract", strings.NewReader(contract))
handleError("can't create deploy tx", err)
tx.Signers = []transaction.Signer{{
Account: h,
Scopes: transaction.CalledByEntry,
}}
tx.NetworkFee = 10_000_000
tx.ValidUntilBlock = bc.BlockHeight() + 1
handleError("can't sign deploy tx", acc.SignTx(tx))
lastBlock = addBlock(bc, lastBlock, valScript, tx)
contractHash := hash.Hash160(avm)
key := make([]byte, 10)
value := make([]byte, 10)
nonce := uint32(0)
blocksNum := uint32(*blockCount)
txNum := int(*txPerBlock)
for i := bc.BlockHeight(); i < blocksNum; i++ {
txs := make([]*transaction.Transaction, txNum)
for j := 0; j < txNum; j++ {
nonce++
rand.Read(key)
rand.Read(value)
w := io.NewBufBinWriter()
emit.AppCallWithOperationAndArgs(w.BinWriter, contractHash, "put", key, value)
handleError("can't create transaction", w.Err)
tx := transaction.New(netmode.UnitTestNet, w.Bytes(), 4_000_000)
tx.ValidUntilBlock = i + 1
tx.NetworkFee = 4_000_000
tx.Nonce = nonce
tx.Signers = []transaction.Signer{{
Account: h,
Scopes: transaction.CalledByEntry,
}}
handleError("can't sign tx", acc.SignTx(tx))
txs[j] = tx
}
lastBlock = addBlock(bc, lastBlock, valScript, txs...)
}
w := io.NewBinWriterFromIO(outStream)
w.WriteU32LE(bc.BlockHeight() + 1)
handleError("error during dump", chaindump.Dump(bc, w, 0, bc.BlockHeight()+1))
}
func handleError(msg string, err error) {
if err != nil {
fmt.Printf("%s: %v\n", msg, err)
os.Exit(1)
}
}
func newChain() (*core.Blockchain, error) {
unitTestNetCfg, err := config.Load("./config", netmode.UnitTestNet)
if err != nil {
return nil, err
}
unitTestNetCfg.ProtocolConfiguration.VerifyBlocks = false
zapCfg := zap.NewDevelopmentConfig()
zapCfg.Level = zap.NewAtomicLevelAt(zapcore.InfoLevel)
log, err := zapCfg.Build()
if err != nil {
return nil, err
}
chain, err := core.NewBlockchain(storage.NewMemoryStore(), unitTestNetCfg.ProtocolConfiguration, log)
if err != nil {
return nil, err
}
go chain.Run()
return chain, nil
}
func addBlock(bc *core.Blockchain, lastBlock *block.Block, script []byte, txs ...*transaction.Transaction) *block.Block {
b, err := newBlock(bc, lastBlock, script, txs...)
if err != nil {
handleError("can't create block", err)
}
if err := bc.AddBlock(b); err != nil {
handleError("can't add block", err)
}
return b
}
func newBlock(bc *core.Blockchain, lastBlock *block.Block, script []byte, txs ...*transaction.Transaction) (*block.Block, error) {
witness := transaction.Witness{VerificationScript: script}
b := &block.Block{
Base: block.Base{
Network: netmode.UnitTestNet,
PrevHash: lastBlock.Hash(),
Timestamp: uint64(time.Now().UTC().Unix())*1000 + uint64(lastBlock.Index),
Index: lastBlock.Index + 1,
NextConsensus: witness.ScriptHash(),
Script: witness,
},
ConsensusData: block.ConsensusData{
PrimaryIndex: 0,
Nonce: 1111,
},
Transactions: txs,
}
if bc.GetConfig().StateRootInHeader {
sr, err := bc.GetStateRoot(bc.BlockHeight())
if err != nil {
return nil, err
}
b.StateRootEnabled = true
b.PrevStateRoot = sr.Root
}
b.RebuildMerkleRoot()
b.Script.InvocationScript = testchain.Sign(b.GetSignedPart())
return b, nil
}