diff --git a/cli/paramcontext/context.go b/cli/paramcontext/context.go index d9a0377c4..9df147fd0 100644 --- a/cli/paramcontext/context.go +++ b/cli/paramcontext/context.go @@ -5,6 +5,7 @@ import ( "fmt" "io/ioutil" + "github.com/nspcc-dev/neo-go/pkg/config/netmode" "github.com/nspcc-dev/neo-go/pkg/core/transaction" "github.com/nspcc-dev/neo-go/pkg/encoding/address" "github.com/nspcc-dev/neo-go/pkg/smartcontract/context" @@ -16,13 +17,13 @@ const validUntilBlockIncrement = 50 // InitAndSave creates incompletely signed transaction which can used // as input to `multisig sign`. -func InitAndSave(tx *transaction.Transaction, acc *wallet.Account, filename string) error { +func InitAndSave(net netmode.Magic, tx *transaction.Transaction, acc *wallet.Account, filename string) error { // avoid fast transaction expiration tx.ValidUntilBlock += validUntilBlockIncrement priv := acc.PrivateKey() pub := priv.PublicKey() - sign := priv.Sign(tx.GetSignedPart()) - scCtx := context.NewParameterContext("Neo.Core.ContractTransaction", tx.Network, tx) + sign := priv.SignHashable(uint32(net), tx) + scCtx := context.NewParameterContext("Neo.Core.ContractTransaction", net, tx) h, err := address.StringToUint160(acc.Address) if err != nil { return fmt.Errorf("invalid address: %s", acc.Address) diff --git a/cli/smartcontract/smart_contract.go b/cli/smartcontract/smart_contract.go index 7fb687e0a..65be26b3d 100644 --- a/cli/smartcontract/smart_contract.go +++ b/cli/smartcontract/smart_contract.go @@ -596,7 +596,7 @@ func invokeInternal(ctx *cli.Context, signAndPush bool) error { if err != nil { return cli.NewExitError(fmt.Errorf("failed to create tx: %w", err), 1) } - if err := paramcontext.InitAndSave(tx, acc, out); err != nil { + if err := paramcontext.InitAndSave(c.GetNetwork(), tx, acc, out); err != nil { return cli.NewExitError(err, 1) } fmt.Fprintln(ctx.App.Writer, tx.Hash().StringLE()) diff --git a/cli/wallet/multisig.go b/cli/wallet/multisig.go index 2a7955d28..0ff3d4349 100644 --- a/cli/wallet/multisig.go +++ b/cli/wallet/multisig.go @@ -52,7 +52,7 @@ func signStoredTransaction(ctx *cli.Context) error { } priv := acc.PrivateKey() - sign := priv.Sign(tx.GetSignedPart()) + sign := priv.SignHashable(uint32(c.Network), tx) if err := c.AddSignature(ch, acc.Contract, priv.PublicKey(), sign); err != nil { return cli.NewExitError(fmt.Errorf("can't add signature: %w", err), 1) } diff --git a/cli/wallet/nep17.go b/cli/wallet/nep17.go index 86440c3e9..76096bb94 100644 --- a/cli/wallet/nep17.go +++ b/cli/wallet/nep17.go @@ -474,11 +474,11 @@ func signAndSendTransfer(ctx *cli.Context, c *client.Client, acc *wallet.Account } if outFile := ctx.String("out"); outFile != "" { - if err := paramcontext.InitAndSave(tx, acc, outFile); err != nil { + if err := paramcontext.InitAndSave(c.GetNetwork(), tx, acc, outFile); err != nil { return cli.NewExitError(err, 1) } } else { - _ = acc.SignTx(tx) + _ = acc.SignTx(c.GetNetwork(), tx) res, err := c.SendRawTransaction(tx) if err != nil { return cli.NewExitError(err, 1) diff --git a/cli/wallet/validator.go b/cli/wallet/validator.go index 80e9bbbea..0b6e3a28b 100644 --- a/cli/wallet/validator.go +++ b/cli/wallet/validator.go @@ -119,7 +119,7 @@ func handleCandidate(ctx *cli.Context, method string, sysGas int64) error { }) if err != nil { return cli.NewExitError(err, 1) - } else if err = acc.SignTx(tx); err != nil { + } else if err = acc.SignTx(c.GetNetwork(), tx); err != nil { return cli.NewExitError(fmt.Errorf("can't sign tx: %v", err), 1) } @@ -187,7 +187,7 @@ func handleVote(ctx *cli.Context) error { return cli.NewExitError(err, 1) } - if err = acc.SignTx(tx); err != nil { + if err = acc.SignTx(c.GetNetwork(), tx); err != nil { return cli.NewExitError(fmt.Errorf("can't sign tx: %v", err), 1) } diff --git a/internal/fakechain/fakechain.go b/internal/fakechain/fakechain.go index 9fed4b11b..587a51c5d 100644 --- a/internal/fakechain/fakechain.go +++ b/internal/fakechain/fakechain.go @@ -6,6 +6,7 @@ import ( "sync/atomic" "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/block" "github.com/nspcc-dev/neo-go/pkg/core/blockchainer" "github.com/nspcc-dev/neo-go/pkg/core/blockchainer/services" @@ -14,7 +15,7 @@ import ( "github.com/nspcc-dev/neo-go/pkg/core/native" "github.com/nspcc-dev/neo-go/pkg/core/state" "github.com/nspcc-dev/neo-go/pkg/core/transaction" - "github.com/nspcc-dev/neo-go/pkg/crypto" + "github.com/nspcc-dev/neo-go/pkg/crypto/hash" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/smartcontract/trigger" "github.com/nspcc-dev/neo-go/pkg/util" @@ -49,7 +50,7 @@ func NewFakeChain() *FakeChain { blocks: make(map[util.Uint256]*block.Block), hdrHashes: make(map[uint32]util.Uint256), txs: make(map[util.Uint256]*transaction.Transaction), - ProtocolConfiguration: config.ProtocolConfiguration{P2PNotaryRequestPayloadPoolSize: 10}, + ProtocolConfiguration: config.ProtocolConfiguration{Magic: netmode.UnitTestNet, P2PNotaryRequestPayloadPoolSize: 10}, } } @@ -393,7 +394,7 @@ func (chain *FakeChain) VerifyTx(*transaction.Transaction) error { } // VerifyWitness implements Blockchainer interface. -func (chain *FakeChain) VerifyWitness(util.Uint160, crypto.Verifiable, *transaction.Witness, int64) error { +func (chain *FakeChain) VerifyWitness(util.Uint160, hash.Hashable, *transaction.Witness, int64) error { if chain.VerifyWitnessF != nil { return chain.VerifyWitnessF() } diff --git a/internal/testchain/address.go b/internal/testchain/address.go index d031adab3..8e18f86a1 100644 --- a/internal/testchain/address.go +++ b/internal/testchain/address.go @@ -127,11 +127,11 @@ func CommitteeAddress() string { } // Sign signs data by all consensus nodes and returns invocation script. -func Sign(data []byte) []byte { +func Sign(h hash.Hashable) []byte { buf := io.NewBufBinWriter() for i := 0; i < 3; i++ { pKey := PrivateKey(i) - sig := pKey.Sign(data) + sig := pKey.SignHashable(uint32(Network()), h) if len(sig) != 64 { panic("wrong signature length") } @@ -141,11 +141,11 @@ func Sign(data []byte) []byte { } // SignCommittee signs data by a majority of committee members. -func SignCommittee(data []byte) []byte { +func SignCommittee(h hash.Hashable) []byte { buf := io.NewBufBinWriter() for i := 0; i < CommitteeSize()/2+1; i++ { pKey := PrivateKey(i) - sig := pKey.Sign(data) + sig := pKey.SignHashable(uint32(Network()), h) if len(sig) != 64 { panic("wrong signature length") } @@ -170,12 +170,11 @@ func NewBlock(t *testing.T, bc blockchainer.Blockchainer, offset uint32, primary PrimaryIndex: byte(primary), NextConsensus: witness.ScriptHash(), Script: witness, - Network: bc.GetConfig().Magic, }, Transactions: txs, } b.RebuildMerkleRoot() - b.Script.InvocationScript = Sign(b.GetSignedPart()) + b.Script.InvocationScript = Sign(b) return b } diff --git a/internal/testchain/transaction.go b/internal/testchain/transaction.go index 13b0e9283..04363f7cd 100644 --- a/internal/testchain/transaction.go +++ b/internal/testchain/transaction.go @@ -8,12 +8,12 @@ import ( "github.com/nspcc-dev/neo-go/cli/smartcontract" "github.com/nspcc-dev/neo-go/pkg/compiler" "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/blockchainer" "github.com/nspcc-dev/neo-go/pkg/core/fee" "github.com/nspcc-dev/neo-go/pkg/core/native" "github.com/nspcc-dev/neo-go/pkg/core/state" "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/callflag" "github.com/nspcc-dev/neo-go/pkg/smartcontract/nef" @@ -38,7 +38,7 @@ func NewTransferFromOwner(bc blockchainer.Blockchainer, contractHash, to util.Ui } script := w.Bytes() - tx := transaction.New(netmode.UnitTestNet, script, 11000000) + tx := transaction.New(script, 11000000) tx.ValidUntilBlock = validUntil tx.Nonce = nonce tx.Signers = []transaction.Signer{{ @@ -100,7 +100,7 @@ func NewDeployTx(bc blockchainer.Blockchainer, name string, sender util.Uint160, return nil, util.Uint160{}, nil, buf.Err } - tx := transaction.New(Network(), buf.Bytes(), 100*native.GASFactor) + tx := transaction.New(buf.Bytes(), 100*native.GASFactor) tx.Signers = []transaction.Signer{{Account: sender}} h := state.CreateContractHash(tx.Sender(), ne.Checksum, name) @@ -119,16 +119,15 @@ func SignTxCommittee(bc blockchainer.Blockchainer, txs ...*transaction.Transacti return nil } -func signTxGeneric(bc blockchainer.Blockchainer, sign func([]byte) []byte, verif []byte, txs ...*transaction.Transaction) { +func signTxGeneric(bc blockchainer.Blockchainer, sign func(hash.Hashable) []byte, verif []byte, txs ...*transaction.Transaction) { for _, tx := range txs { size := io.GetVarSize(tx) netFee, sizeDelta := fee.Calculate(bc.GetPolicer().GetBaseExecFee(), verif) tx.NetworkFee += netFee size += sizeDelta tx.NetworkFee += int64(size) * bc.FeePerByte() - data := tx.GetSignedPart() tx.Scripts = []transaction.Witness{{ - InvocationScript: sign(data), + InvocationScript: sign(tx), VerificationScript: verif, }} } diff --git a/pkg/compiler/interop_test.go b/pkg/compiler/interop_test.go index 4fe4c25e0..d097be567 100644 --- a/pkg/compiler/interop_test.go +++ b/pkg/compiler/interop_test.go @@ -7,8 +7,8 @@ import ( "strings" "testing" + "github.com/nspcc-dev/neo-go/internal/fakechain" "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" "github.com/nspcc-dev/neo-go/pkg/core/dao" "github.com/nspcc-dev/neo-go/pkg/core/interop" @@ -186,7 +186,8 @@ func TestAppCall(t *testing.T) { return nil, errors.New("not found") } - ic := interop.NewContext(trigger.Application, nil, dao.NewSimple(storage.NewMemoryStore(), netmode.UnitTestNet, false), contractGetter, nil, nil, nil, zaptest.NewLogger(t)) + fc := fakechain.NewFakeChain() + ic := interop.NewContext(trigger.Application, fc, dao.NewSimple(storage.NewMemoryStore(), false), contractGetter, nil, nil, nil, zaptest.NewLogger(t)) t.Run("valid script", func(t *testing.T) { src := getAppCallScript(fmt.Sprintf("%#v", ih.BytesBE())) diff --git a/pkg/consensus/block.go b/pkg/consensus/block.go index dab9c3302..16c7d9ea6 100644 --- a/pkg/consensus/block.go +++ b/pkg/consensus/block.go @@ -1,8 +1,11 @@ package consensus import ( + "errors" + "github.com/nspcc-dev/dbft/block" "github.com/nspcc-dev/dbft/crypto" + "github.com/nspcc-dev/neo-go/pkg/config/netmode" coreb "github.com/nspcc-dev/neo-go/pkg/core/block" "github.com/nspcc-dev/neo-go/pkg/core/transaction" "github.com/nspcc-dev/neo-go/pkg/util" @@ -13,6 +16,7 @@ import ( type neoBlock struct { coreb.Block + network netmode.Magic signature []byte } @@ -20,21 +24,19 @@ var _ block.Block = (*neoBlock)(nil) // Sign implements block.Block interface. func (n *neoBlock) Sign(key crypto.PrivateKey) error { - data := n.Header.GetSignedPart() - sig, err := key.Sign(data[:]) - if err != nil { - return err - } - + k := key.(*privateKey) + sig := k.PrivateKey.SignHashable(uint32(n.network), &n.Block) n.signature = sig - return nil } // Verify implements block.Block interface. func (n *neoBlock) Verify(key crypto.PublicKey, sign []byte) error { - data := n.Header.GetSignedPart() - return key.Verify(data, sign) + k := key.(*publicKey) + if k.PublicKey.VerifyHashable(sign, uint32(n.network), &n.Block) { + return nil + } + return errors.New("verification failed") } // Transactions implements block.Block interface. diff --git a/pkg/consensus/block_test.go b/pkg/consensus/block_test.go index efed586e3..afa94a711 100644 --- a/pkg/consensus/block_test.go +++ b/pkg/consensus/block_test.go @@ -1,13 +1,11 @@ package consensus import ( - "crypto/rand" "testing" "github.com/nspcc-dev/dbft/block" - "github.com/nspcc-dev/dbft/crypto" - "github.com/nspcc-dev/neo-go/pkg/config/netmode" "github.com/nspcc-dev/neo-go/pkg/core/transaction" + "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/util" "github.com/nspcc-dev/neo-go/pkg/vm/opcode" "github.com/stretchr/testify/require" @@ -15,10 +13,10 @@ import ( func TestNeoBlock_Sign(t *testing.T) { b := new(neoBlock) - priv, pub := crypto.Generate(rand.Reader) + priv, _ := keys.NewPrivateKey() - require.NoError(t, b.Sign(priv)) - require.NoError(t, b.Verify(pub, b.Signature())) + require.NoError(t, b.Sign(&privateKey{PrivateKey: priv})) + require.NoError(t, b.Verify(&publicKey{PublicKey: priv.PublicKey()}, b.Signature())) } func TestNeoBlock_Setters(t *testing.T) { @@ -43,7 +41,7 @@ func TestNeoBlock_Setters(t *testing.T) { b.Block.PrevHash = util.Uint256{9, 8, 7} require.Equal(t, util.Uint256{9, 8, 7}, b.PrevHash()) - txx := []block.Transaction{transaction.New(netmode.UnitTestNet, []byte{byte(opcode.PUSH1)}, 1)} + txx := []block.Transaction{transaction.New([]byte{byte(opcode.PUSH1)}, 1)} b.SetTransactions(txx) require.Equal(t, txx, b.Transactions()) } diff --git a/pkg/consensus/consensus.go b/pkg/consensus/consensus.go index cff3c95da..2ced9fca8 100644 --- a/pkg/consensus/consensus.go +++ b/pkg/consensus/consensus.go @@ -201,12 +201,12 @@ var ( func NewPayload(m netmode.Magic, stateRootEnabled bool) *Payload { return &Payload{ Extensible: npayload.Extensible{ - Network: m, Category: Category, }, message: message{ stateRootEnabled: stateRootEnabled, }, + network: m, } } @@ -576,7 +576,7 @@ func (s *service) getBlock(h util.Uint256) block.Block { return nil } - return &neoBlock{Block: *b} + return &neoBlock{network: s.ProtocolConfiguration.Magic, Block: *b} } func (s *service) getVerifiedTx() []block.Transaction { @@ -647,9 +647,8 @@ func convertKeys(validators []crypto.PublicKey) (pubs []*keys.PublicKey) { } func (s *service) newBlockFromContext(ctx *dbft.Context) block.Block { - block := new(neoBlock) + block := &neoBlock{network: s.ProtocolConfiguration.Magic} - block.Block.Network = s.ProtocolConfiguration.Magic block.Block.Timestamp = ctx.Timestamp / nsInMs block.Block.Index = ctx.BlockIndex if s.ProtocolConfiguration.StateRootInHeader { diff --git a/pkg/consensus/consensus_test.go b/pkg/consensus/consensus_test.go index b448e4f56..747c47653 100644 --- a/pkg/consensus/consensus_test.go +++ b/pkg/consensus/consensus_test.go @@ -34,7 +34,7 @@ import ( func TestNewService(t *testing.T) { srv := newTestService(t) - tx := transaction.New(netmode.UnitTestNet, []byte{byte(opcode.PUSH1)}, 100000) + tx := transaction.New([]byte{byte(opcode.PUSH1)}, 100000) tx.ValidUntilBlock = 1 addSender(t, tx) signTx(t, srv.Chain, tx) @@ -65,11 +65,11 @@ func initServiceNextConsensus(t *testing.T, newAcc *wallet.Account, offset uint3 emit.Opcodes(w.BinWriter, opcode.ASSERT) require.NoError(t, w.Err) - tx := transaction.New(netmode.UnitTestNet, w.Bytes(), 21_000_000) + tx := transaction.New(w.Bytes(), 21_000_000) tx.ValidUntilBlock = bc.BlockHeight() + 1 tx.NetworkFee = 10_000_000 tx.Signers = []transaction.Signer{{Scopes: transaction.Global, Account: acc.Contract.ScriptHash()}} - require.NoError(t, acc.SignTx(tx)) + require.NoError(t, acc.SignTx(netmode.UnitTestNet, tx)) require.NoError(t, bc.PoolTx(tx)) srv := newTestServiceWithChain(t, bc) @@ -80,11 +80,11 @@ func initServiceNextConsensus(t *testing.T, newAcc *wallet.Account, offset uint3 emit.AppCall(w.BinWriter, bc.GoverningTokenHash(), "registerCandidate", callflag.All, newPriv.PublicKey().Bytes()) require.NoError(t, w.Err) - tx = transaction.New(netmode.UnitTestNet, w.Bytes(), 1001_00000000) + tx = transaction.New(w.Bytes(), 1001_00000000) tx.ValidUntilBlock = bc.BlockHeight() + 1 tx.NetworkFee = 20_000_000 tx.Signers = []transaction.Signer{{Scopes: transaction.Global, Account: newPriv.GetScriptHash()}} - require.NoError(t, newAcc.SignTx(tx)) + require.NoError(t, newAcc.SignTx(netmode.UnitTestNet, tx)) require.NoError(t, bc.PoolTx(tx)) srv.dbft.OnTimeout(timer.HV{Height: srv.dbft.Context.BlockIndex}) @@ -100,11 +100,11 @@ func initServiceNextConsensus(t *testing.T, newAcc *wallet.Account, offset uint3 emit.Opcodes(w.BinWriter, opcode.ASSERT) require.NoError(t, w.Err) - tx = transaction.New(netmode.UnitTestNet, w.Bytes(), 20_000_000) + tx = transaction.New(w.Bytes(), 20_000_000) tx.ValidUntilBlock = bc.BlockHeight() + 1 tx.NetworkFee = 20_000_000 tx.Signers = []transaction.Signer{{Scopes: transaction.Global, Account: newPriv.GetScriptHash()}} - require.NoError(t, newAcc.SignTx(tx)) + require.NoError(t, newAcc.SignTx(netmode.UnitTestNet, tx)) require.NoError(t, bc.PoolTx(tx)) srv.dbft.OnTimeout(timer.HV{Height: srv.dbft.BlockIndex}) @@ -167,7 +167,7 @@ func TestService_GetVerified(t *testing.T) { srv.dbft.Start() var txs []*transaction.Transaction for i := 0; i < 4; i++ { - tx := transaction.New(netmode.UnitTestNet, []byte{byte(opcode.PUSH1)}, 100000) + tx := transaction.New([]byte{byte(opcode.PUSH1)}, 100000) tx.Nonce = 123 + uint32(i) tx.ValidUntilBlock = 1 txs = append(txs, tx) @@ -260,7 +260,7 @@ func TestService_getTx(t *testing.T) { srv := newTestService(t) t.Run("transaction in mempool", func(t *testing.T) { - tx := transaction.New(netmode.UnitTestNet, []byte{byte(opcode.PUSH1)}, 0) + tx := transaction.New([]byte{byte(opcode.PUSH1)}, 0) tx.Nonce = 1234 tx.ValidUntilBlock = 1 addSender(t, tx) @@ -277,7 +277,7 @@ func TestService_getTx(t *testing.T) { }) t.Run("transaction in local cache", func(t *testing.T) { - tx := transaction.New(netmode.UnitTestNet, []byte{byte(opcode.PUSH1)}, 0) + tx := transaction.New([]byte{byte(opcode.PUSH1)}, 0) tx.Nonce = 4321 tx.ValidUntilBlock = 1 h := tx.Hash() @@ -372,7 +372,7 @@ func TestVerifyBlock(t *testing.T) { require.True(t, srv.verifyBlock(&neoBlock{Block: *b})) }) t.Run("good pooled tx", func(t *testing.T) { - tx := transaction.New(netmode.UnitTestNet, []byte{byte(opcode.RET)}, 100000) + tx := transaction.New([]byte{byte(opcode.RET)}, 100000) tx.ValidUntilBlock = 1 addSender(t, tx) signTx(t, srv.Chain, tx) @@ -381,7 +381,7 @@ func TestVerifyBlock(t *testing.T) { require.True(t, srv.verifyBlock(&neoBlock{Block: *b})) }) t.Run("good non-pooled tx", func(t *testing.T) { - tx := transaction.New(netmode.UnitTestNet, []byte{byte(opcode.RET)}, 100000) + tx := transaction.New([]byte{byte(opcode.RET)}, 100000) tx.ValidUntilBlock = 1 addSender(t, tx) signTx(t, srv.Chain, tx) @@ -389,12 +389,12 @@ func TestVerifyBlock(t *testing.T) { require.True(t, srv.verifyBlock(&neoBlock{Block: *b})) }) t.Run("good conflicting tx", func(t *testing.T) { - tx1 := transaction.New(netmode.UnitTestNet, []byte{byte(opcode.RET)}, 100000) + tx1 := transaction.New([]byte{byte(opcode.RET)}, 100000) tx1.NetworkFee = 20_000_000 * native.GASFactor tx1.ValidUntilBlock = 1 addSender(t, tx1) signTx(t, srv.Chain, tx1) - tx2 := transaction.New(netmode.UnitTestNet, []byte{byte(opcode.RET)}, 100000) + tx2 := transaction.New([]byte{byte(opcode.RET)}, 100000) tx2.NetworkFee = 20_000_000 * native.GASFactor tx2.ValidUntilBlock = 1 addSender(t, tx2) @@ -412,7 +412,7 @@ func TestVerifyBlock(t *testing.T) { t.Run("bad big size", func(t *testing.T) { script := make([]byte, int(srv.ProtocolConfiguration.MaxBlockSize)) script[0] = byte(opcode.RET) - tx := transaction.New(netmode.UnitTestNet, script, 100000) + tx := transaction.New(script, 100000) tx.ValidUntilBlock = 1 addSender(t, tx) signTx(t, srv.Chain, tx) @@ -425,7 +425,7 @@ func TestVerifyBlock(t *testing.T) { require.False(t, srv.verifyBlock(&neoBlock{Block: *b})) }) t.Run("bad tx", func(t *testing.T) { - tx := transaction.New(netmode.UnitTestNet, []byte{byte(opcode.RET)}, 100000) + tx := transaction.New([]byte{byte(opcode.RET)}, 100000) tx.ValidUntilBlock = 1 addSender(t, tx) signTx(t, srv.Chain, tx) @@ -436,7 +436,7 @@ func TestVerifyBlock(t *testing.T) { t.Run("bad big sys fee", func(t *testing.T) { txes := make([]*transaction.Transaction, 2) for i := range txes { - txes[i] = transaction.New(netmode.UnitTestNet, []byte{byte(opcode.RET)}, srv.ProtocolConfiguration.MaxBlockSystemFee/2+1) + txes[i] = transaction.New([]byte{byte(opcode.RET)}, srv.ProtocolConfiguration.MaxBlockSystemFee/2+1) txes[i].ValidUntilBlock = 1 addSender(t, txes[i]) signTx(t, srv.Chain, txes[i]) @@ -547,11 +547,10 @@ func signTx(t *testing.T, bc blockchainer.Blockchainer, txs ...*transaction.Tran tx.NetworkFee += +netFee size += sizeDelta tx.NetworkFee += int64(size) * bc.FeePerByte() - data := tx.GetSignedPart() buf := io.NewBufBinWriter() for _, key := range privNetKeys { - signature := key.Sign(data) + signature := key.SignHashable(uint32(testchain.Network()), tx) emit.Bytes(buf.BinWriter, signature) } diff --git a/pkg/consensus/payload.go b/pkg/consensus/payload.go index ffcaf24fc..f06d0a54c 100644 --- a/pkg/consensus/payload.go +++ b/pkg/consensus/payload.go @@ -4,6 +4,7 @@ import ( "fmt" "github.com/nspcc-dev/dbft/payload" + "github.com/nspcc-dev/neo-go/pkg/config/netmode" "github.com/nspcc-dev/neo-go/pkg/io" npayload "github.com/nspcc-dev/neo-go/pkg/network/payload" "github.com/nspcc-dev/neo-go/pkg/util" @@ -28,6 +29,7 @@ type ( Payload struct { npayload.Extensible message + network netmode.Magic } ) @@ -128,7 +130,7 @@ func (p *Payload) EncodeBinary(w *io.BinWriter) { // It also sets corresponding verification and invocation scripts. func (p *Payload) Sign(key *privateKey) error { p.encodeData() - sig := key.SignHash(p.GetSignedHash()) + sig := key.PrivateKey.SignHashable(uint32(p.network), &p.Extensible) buf := io.NewBufBinWriter() emit.Bytes(buf.BinWriter, sig) @@ -138,22 +140,6 @@ func (p *Payload) Sign(key *privateKey) error { return nil } -// GetSignedPart implements crypto.Verifiable interface. -func (p *Payload) GetSignedPart() []byte { - if p.Extensible.Data == nil { - p.encodeData() - } - return p.Extensible.GetSignedPart() -} - -// GetSignedHash returns a hash of the payload used to verify it. -func (p *Payload) GetSignedHash() util.Uint256 { - if p.Extensible.Data == nil { - p.encodeData() - } - return p.Extensible.GetSignedHash() -} - // Hash implements payload.ConsensusPayload interface. func (p *Payload) Hash() util.Uint256 { if p.Extensible.Data == nil { diff --git a/pkg/consensus/payload_test.go b/pkg/consensus/payload_test.go index 2b24c9985..f5d6175b9 100644 --- a/pkg/consensus/payload_test.go +++ b/pkg/consensus/payload_test.go @@ -79,7 +79,7 @@ func TestConsensusPayload_Setters(t *testing.T) { func TestConsensusPayload_Serializable(t *testing.T) { for _, mt := range messageTypes { p := randomPayload(t, mt) - actual := new(Payload) + actual := &Payload{Extensible: npayload.Extensible{}, network: netmode.UnitTestNet} data, err := testserdes.EncodeBinary(p) require.NoError(t, err) require.NoError(t, testserdes.DecodeBinary(data, &actual.Extensible)) @@ -163,6 +163,7 @@ func randomPayload(t *testing.T, mt messageType) *Payload { VerificationScript: []byte{byte(opcode.PUSH0)}, }, }, + network: netmode.UnitTestNet, } if mt == changeViewType { diff --git a/pkg/consensus/recovery_message.go b/pkg/consensus/recovery_message.go index f24376cb8..6f8b66f2d 100644 --- a/pkg/consensus/recovery_message.go +++ b/pkg/consensus/recovery_message.go @@ -298,7 +298,6 @@ func fromPayload(t messageType, recovery *Payload, p io.Serializable) *Payload { return &Payload{ Extensible: npayload.Extensible{ Category: Category, - Network: recovery.Network, ValidBlockEnd: recovery.BlockIndex, }, message: message{ @@ -308,5 +307,6 @@ func fromPayload(t messageType, recovery *Payload, p io.Serializable) *Payload { payload: p, stateRootEnabled: recovery.stateRootEnabled, }, + network: recovery.network, } } diff --git a/pkg/core/block/block.go b/pkg/core/block/block.go index 9291b3482..8feff8942 100644 --- a/pkg/core/block/block.go +++ b/pkg/core/block/block.go @@ -6,7 +6,6 @@ import ( "math" "github.com/Workiva/go-datastructures/queue" - "github.com/nspcc-dev/neo-go/pkg/config/netmode" "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" @@ -68,10 +67,9 @@ func (b *Block) RebuildMerkleRoot() { // This is commonly used to create a block from stored data. // Blocks created from trimmed data will have their Trimmed field // set to true. -func NewBlockFromTrimmedBytes(network netmode.Magic, stateRootEnabled bool, b []byte) (*Block, error) { +func NewBlockFromTrimmedBytes(stateRootEnabled bool, b []byte) (*Block, error) { block := &Block{ Header: Header{ - Network: network, StateRootEnabled: stateRootEnabled, }, Trimmed: true, @@ -95,11 +93,10 @@ func NewBlockFromTrimmedBytes(network netmode.Magic, stateRootEnabled bool, b [] return block, br.Err } -// New creates a new blank block tied to the specific network. -func New(network netmode.Magic, stateRootEnabled bool) *Block { +// New creates a new blank block with proper state root setting. +func New(stateRootEnabled bool) *Block { return &Block{ Header: Header{ - Network: network, StateRootEnabled: stateRootEnabled, }, } @@ -136,7 +133,7 @@ func (b *Block) DecodeBinary(br *io.BinReader) { } txes := make([]*transaction.Transaction, contentsCount) for i := 0; i < int(contentsCount); i++ { - tx := &transaction.Transaction{Network: b.Network} + tx := &transaction.Transaction{} tx.DecodeBinary(br) txes[i] = tx } @@ -207,7 +204,7 @@ func (b *Block) UnmarshalJSON(data []byte) error { if len(auxb.Transactions) != 0 { b.Transactions = make([]*transaction.Transaction, 0, len(auxb.Transactions)) for _, txBytes := range auxb.Transactions { - tx := &transaction.Transaction{Network: b.Network} + tx := &transaction.Transaction{} err = tx.UnmarshalJSON(txBytes) if err != nil { return err diff --git a/pkg/core/block/block_test.go b/pkg/core/block/block_test.go index 65a8f1ec7..b8042f3ef 100644 --- a/pkg/core/block/block_test.go +++ b/pkg/core/block/block_test.go @@ -8,7 +8,6 @@ import ( "testing" "github.com/nspcc-dev/neo-go/internal/testserdes" - "github.com/nspcc-dev/neo-go/pkg/config/netmode" "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/encoding/address" @@ -32,7 +31,7 @@ func TestDecodeBlock1(t *testing.T) { b, err := hex.DecodeString(data["raw"].(string)) require.NoError(t, err) - block := New(netmode.TestNet, false) + block := New(false) assert.NoError(t, testserdes.DecodeBinary(b, block)) assert.Equal(t, uint32(data["index"].(float64)), block.Index) @@ -59,7 +58,7 @@ func TestTrimmedBlock(t *testing.T) { b, err := block.Trim() require.NoError(t, err) - trimmedBlock, err := NewBlockFromTrimmedBytes(netmode.TestNet, false, b) + trimmedBlock, err := NewBlockFromTrimmedBytes(false, b) require.NoError(t, err) assert.True(t, trimmedBlock.Trimmed) @@ -93,7 +92,7 @@ func newDumbBlock() *Block { }, }, Transactions: []*transaction.Transaction{ - transaction.New(netmode.UnitTestNet, []byte{byte(opcode.PUSH1)}, 0), + transaction.New([]byte{byte(opcode.PUSH1)}, 0), }, } } @@ -109,7 +108,7 @@ func TestBinBlockDecodeEncode(t *testing.T) { rawblock := "AAAAAAwIVa2D6Yha3tArd5XnwkAf7deJBsdyyvpYb2xMZGBbkOUNHAsfre0rKA/F+Ox05/bQSXmcRZnzK3M6Z+/TxJUh0MNFeAEAAAEAAAAA3u55wYnzAJiwumouuQs6klimx/8BxgxA4MAnF5HGhcOTBjqdXKZIAKcw019v0cSpZj3l04FmLXxAPIPbL1Em2QOE3qBslr1/C4jdLSSq82o3TBr01RqlZgxA6ejwZmZkcfQsbMLS4beqFmtlKuK5eXYj7C7al2XmXqTJcVEm2gnZRUwe4lkBvcil1keYXNLEnHr77lcMLFGHZQxA8JYcGaz9OxOXxECrbVTGAIi+3nXf3ltsqDBmXukPeYO8l0OvXnVR30G+tXwcNw4wqTA2eZbMadwYM14JScDEipMTDCECEDp/fdAWVYWX95YNJ8UWpDlP2Wi55lFV60sBPkBAQG4MIQKnvFX+hoTgEZdo0QS6MHlb3MhmGehkrdJhVnI+0YXNYgwhArNiK/QBe9/jF8WK7V9MdT8ga324lgRvp9d0u8S/f43CDCED2QwH32PmkM53kS4Qq1GsyUS2aGAje2CMT4+DCece5pkUQXvObKUCAFjQuwvA2KcAAAAAACCqRAAAAAAA6AMAAAHe7nnBifMAmLC6ai65CzqSWKbH/wEAWwsCAOH1BQwUgM7HtvW1b1BXj3N/Fi06sU1GZQ0MFN7uecGJ8wCYsLpqLrkLOpJYpsf/FMAfDAh0cmFuc2ZlcgwU9WPqQLwoPU0OBcSOowWz8qBzQO9BYn1bUjkBxgxAuFCM0+tRmD8dC3ZLKxegtoqGGoun28KY79wRgKosmoMYqJmBmUS3l2cg+uzuRSfOqV0RbUm1WLtmAxvk+SAiIAxA85v8JfgZx70F2h0Naxi7XVDHONcDeiOPJDzzOxdt4C/bFcRs4kCDES56U21h6582lPUstH15LyK3SctSgAZEkAxAwcLgblSvp7Gb59aALHD4+ndxSYlBivcYh6V/SKaf+Y0510QQMs8hnPCGTAVapeFkvJMBXuqIwP/QbxW+Xll5xJMTDCECEDp/fdAWVYWX95YNJ8UWpDlP2Wi55lFV60sBPkBAQG4MIQKnvFX+hoTgEZdo0QS6MHlb3MhmGehkrdJhVnI+0YXNYgwhArNiK/QBe9/jF8WK7V9MdT8ga324lgRvp9d0u8S/f43CDCED2QwH32PmkM53kS4Qq1GsyUS2aGAje2CMT4+DCece5pkUQXvObKUA2CS8GcDYpwAAAAAAIKpEAAAAAADoAwAAAd7uecGJ8wCYsLpqLrkLOpJYpsf/AQBfCwMAQNndiE0KAAwUgM7HtvW1b1BXj3N/Fi06sU1GZQ0MFN7uecGJ8wCYsLpqLrkLOpJYpsf/FMAfDAh0cmFuc2ZlcgwUz3bii9AGLEpHjuNVYQETGfPPpNJBYn1bUjkBxgxA1p9A+89hC6qTfIIXDPz7XxcKOevwXxGrHx7kihAiTGMb1OO69mbUooYOfZRsUmcx7L8U8up7MrydtsnDYSDXSQxApetXIPd+zfx7oyrCzLtsCTEuwueG8yd6ttgs6pZb8N2KfNPVEoCg7Plvt0A+6yPkhbNDoSJ9IKKAlFOn/9d1owxA6/V3Xk+QhkzvAi9CYoM3E3LnLNBgXKh7PH06Dusz7rgn0u1oencsUgoo0+AOEvuwVHVt3bDu/NvJHtX4/KDcZpMTDCECEDp/fdAWVYWX95YNJ8UWpDlP2Wi55lFV60sBPkBAQG4MIQKnvFX+hoTgEZdo0QS6MHlb3MhmGehkrdJhVnI+0YXNYgwhArNiK/QBe9/jF8WK7V9MdT8ga324lgRvp9d0u8S/f43CDCED2QwH32PmkM53kS4Qq1GsyUS2aGAje2CMT4+DCece5pkUQXvObKU=" rawblockBytes, _ := base64.StdEncoding.DecodeString(rawblock) - b := New(netmode.PrivNet, false) + b := New(false) assert.NoError(t, testserdes.DecodeBinary(rawblockBytes, b)) expected := map[string]bool{ // 1 trans @@ -143,7 +142,7 @@ func TestBinBlockDecodeEncode(t *testing.T) { assert.NoError(t, err) assert.Equal(t, rawblock, base64.StdEncoding.EncodeToString(data)) - testserdes.MarshalUnmarshalJSON(t, b, New(netmode.PrivNet, false)) + testserdes.MarshalUnmarshalJSON(t, b, New(false)) } func TestBlockSizeCalculation(t *testing.T) { @@ -156,7 +155,7 @@ func TestBlockSizeCalculation(t *testing.T) { rawBlock := "AAAAAAwIVa2D6Yha3tArd5XnwkAf7deJBsdyyvpYb2xMZGBbkOUNHAsfre0rKA/F+Ox05/bQSXmcRZnzK3M6Z+/TxJUh0MNFeAEAAAEAAAAA3u55wYnzAJiwumouuQs6klimx/8BxgxA4MAnF5HGhcOTBjqdXKZIAKcw019v0cSpZj3l04FmLXxAPIPbL1Em2QOE3qBslr1/C4jdLSSq82o3TBr01RqlZgxA6ejwZmZkcfQsbMLS4beqFmtlKuK5eXYj7C7al2XmXqTJcVEm2gnZRUwe4lkBvcil1keYXNLEnHr77lcMLFGHZQxA8JYcGaz9OxOXxECrbVTGAIi+3nXf3ltsqDBmXukPeYO8l0OvXnVR30G+tXwcNw4wqTA2eZbMadwYM14JScDEipMTDCECEDp/fdAWVYWX95YNJ8UWpDlP2Wi55lFV60sBPkBAQG4MIQKnvFX+hoTgEZdo0QS6MHlb3MhmGehkrdJhVnI+0YXNYgwhArNiK/QBe9/jF8WK7V9MdT8ga324lgRvp9d0u8S/f43CDCED2QwH32PmkM53kS4Qq1GsyUS2aGAje2CMT4+DCece5pkUQXvObKUCAFjQuwvA2KcAAAAAACCqRAAAAAAA6AMAAAHe7nnBifMAmLC6ai65CzqSWKbH/wEAWwsCAOH1BQwUgM7HtvW1b1BXj3N/Fi06sU1GZQ0MFN7uecGJ8wCYsLpqLrkLOpJYpsf/FMAfDAh0cmFuc2ZlcgwU9WPqQLwoPU0OBcSOowWz8qBzQO9BYn1bUjkBxgxAuFCM0+tRmD8dC3ZLKxegtoqGGoun28KY79wRgKosmoMYqJmBmUS3l2cg+uzuRSfOqV0RbUm1WLtmAxvk+SAiIAxA85v8JfgZx70F2h0Naxi7XVDHONcDeiOPJDzzOxdt4C/bFcRs4kCDES56U21h6582lPUstH15LyK3SctSgAZEkAxAwcLgblSvp7Gb59aALHD4+ndxSYlBivcYh6V/SKaf+Y0510QQMs8hnPCGTAVapeFkvJMBXuqIwP/QbxW+Xll5xJMTDCECEDp/fdAWVYWX95YNJ8UWpDlP2Wi55lFV60sBPkBAQG4MIQKnvFX+hoTgEZdo0QS6MHlb3MhmGehkrdJhVnI+0YXNYgwhArNiK/QBe9/jF8WK7V9MdT8ga324lgRvp9d0u8S/f43CDCED2QwH32PmkM53kS4Qq1GsyUS2aGAje2CMT4+DCece5pkUQXvObKUA2CS8GcDYpwAAAAAAIKpEAAAAAADoAwAAAd7uecGJ8wCYsLpqLrkLOpJYpsf/AQBfCwMAQNndiE0KAAwUgM7HtvW1b1BXj3N/Fi06sU1GZQ0MFN7uecGJ8wCYsLpqLrkLOpJYpsf/FMAfDAh0cmFuc2ZlcgwUz3bii9AGLEpHjuNVYQETGfPPpNJBYn1bUjkBxgxA1p9A+89hC6qTfIIXDPz7XxcKOevwXxGrHx7kihAiTGMb1OO69mbUooYOfZRsUmcx7L8U8up7MrydtsnDYSDXSQxApetXIPd+zfx7oyrCzLtsCTEuwueG8yd6ttgs6pZb8N2KfNPVEoCg7Plvt0A+6yPkhbNDoSJ9IKKAlFOn/9d1owxA6/V3Xk+QhkzvAi9CYoM3E3LnLNBgXKh7PH06Dusz7rgn0u1oencsUgoo0+AOEvuwVHVt3bDu/NvJHtX4/KDcZpMTDCECEDp/fdAWVYWX95YNJ8UWpDlP2Wi55lFV60sBPkBAQG4MIQKnvFX+hoTgEZdo0QS6MHlb3MhmGehkrdJhVnI+0YXNYgwhArNiK/QBe9/jF8WK7V9MdT8ga324lgRvp9d0u8S/f43CDCED2QwH32PmkM53kS4Qq1GsyUS2aGAje2CMT4+DCece5pkUQXvObKU=" rawBlockBytes, _ := base64.StdEncoding.DecodeString(rawBlock) - b := New(netmode.TestNet, false) + b := New(false) assert.NoError(t, testserdes.DecodeBinary(rawBlockBytes, b)) expected := []struct { @@ -260,7 +259,7 @@ func TestGetExpectedBlockSize(t *testing.T) { b.StateRootEnabled = stateRootEnabled b.Transactions = make([]*transaction.Transaction, 123) for i := range b.Transactions { - tx := transaction.New(netmode.UnitTestNet, []byte{byte(opcode.RET)}, int64(i)) + tx := transaction.New([]byte{byte(opcode.RET)}, int64(i)) tx.Signers = []transaction.Signer{{Account: util.Uint160{1, 2, 3}}} tx.Scripts = []transaction.Witness{{}} b.Transactions[i] = tx diff --git a/pkg/core/block/header.go b/pkg/core/block/header.go index 39ecf4b7a..e7515dcab 100644 --- a/pkg/core/block/header.go +++ b/pkg/core/block/header.go @@ -4,7 +4,6 @@ import ( "encoding/json" "errors" - "github.com/nspcc-dev/neo-go/pkg/config/netmode" "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/encoding/address" @@ -38,11 +37,6 @@ type Header struct { // Script used to validate the block Script transaction.Witness - // Network magic number this block belongs to. This one actually is not - // a part of the wire-representation of Block, but it's absolutely - // necessary for correct signing/verification. - Network netmode.Magic - // StateRootEnabled specifies if header contains state root. StateRootEnabled bool // PrevStateRoot is state root of the previous block. @@ -52,9 +46,6 @@ type Header struct { // Hash of this block, created when binary encoded (double SHA256). hash util.Uint256 - - // Hash of the block used to verify it (single SHA256). - verificationHash util.Uint256 } // baseAux is used to marshal/unmarshal to/from JSON, it's almost the same @@ -81,14 +72,6 @@ func (b *Header) Hash() util.Uint256 { return b.hash } -// GetSignedHash returns a hash of the block used to verify it. -func (b *Header) GetSignedHash() util.Uint256 { - if b.verificationHash.Equals(util.Uint256{}) { - b.createHash() - } - return b.verificationHash -} - // DecodeBinary implements Serializable interface. func (b *Header) DecodeBinary(br *io.BinReader) { b.decodeHashableFields(br) @@ -108,21 +91,6 @@ func (b *Header) EncodeBinary(bw *io.BinWriter) { b.Script.EncodeBinary(bw) } -// GetSignedPart returns serialized hashable data of the block. -func (b *Header) GetSignedPart() []byte { - if b.hash.Equals(util.Uint256{}) { - b.createHash() - } - buf := io.NewBufBinWriter() - b.writeSignedPart(buf) - return buf.Bytes() -} - -func (b *Header) writeSignedPart(buf *io.BufBinWriter) { - buf.WriteU32LE(uint32(b.Network)) - buf.WriteBytes(b.hash[:]) -} - // createHash creates the hash of the block. // When calculating the hash value of the block, instead of calculating the entire block, // only first seven fields in the block head will be calculated, which are @@ -135,9 +103,6 @@ func (b *Header) createHash() { b.encodeHashableFields(buf.BinWriter) b.hash = hash.Sha256(buf.Bytes()) - buf.Reset() - b.writeSignedPart(buf) - b.verificationHash = hash.Sha256(buf.Bytes()) } // encodeHashableFields will only encode the fields used for hashing. diff --git a/pkg/core/block/helper_test.go b/pkg/core/block/helper_test.go index c52a39a94..b73b50de2 100644 --- a/pkg/core/block/helper_test.go +++ b/pkg/core/block/helper_test.go @@ -8,7 +8,6 @@ import ( "testing" "github.com/nspcc-dev/neo-go/internal/testserdes" - "github.com/nspcc-dev/neo-go/pkg/config/netmode" "github.com/stretchr/testify/require" ) @@ -19,7 +18,7 @@ func getDecodedBlock(t *testing.T, i int) *Block { b, err := hex.DecodeString(data["raw"].(string)) require.NoError(t, err) - block := New(netmode.TestNet, false) + block := New(false) require.NoError(t, testserdes.DecodeBinary(b, block)) return block diff --git a/pkg/core/blockchain.go b/pkg/core/blockchain.go index f09d77cf6..face98d17 100644 --- a/pkg/core/blockchain.go +++ b/pkg/core/blockchain.go @@ -25,7 +25,6 @@ import ( "github.com/nspcc-dev/neo-go/pkg/core/stateroot" "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" "github.com/nspcc-dev/neo-go/pkg/crypto/hash" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/encoding/bigint" @@ -201,7 +200,7 @@ func NewBlockchain(s storage.Store, cfg config.ProtocolConfiguration, log *zap.L } bc := &Blockchain{ config: cfg, - dao: dao.NewSimple(s, cfg.Magic, cfg.StateRootInHeader), + dao: dao.NewSimple(s, cfg.StateRootInHeader), stopCh: make(chan struct{}), runToExitCh: make(chan struct{}), memPool: mempool.New(cfg.MemPoolSize, 0, false), @@ -1742,7 +1741,7 @@ func (bc *Blockchain) InitVerificationVM(v *vm.VM, getContract func(util.Uint160 } // VerifyWitness checks that w is a correct witness for c signed by h. -func (bc *Blockchain) VerifyWitness(h util.Uint160, c crypto.Verifiable, w *transaction.Witness, gas int64) error { +func (bc *Blockchain) VerifyWitness(h util.Uint160, c hash.Hashable, w *transaction.Witness, gas int64) error { ic := bc.newInteropContext(trigger.Verification, bc.dao, nil, nil) ic.Container = c _, err := bc.verifyHashAgainstScript(h, w, ic, gas) diff --git a/pkg/core/blockchain_test.go b/pkg/core/blockchain_test.go index f5d77bfcf..bec2d4a47 100644 --- a/pkg/core/blockchain_test.go +++ b/pkg/core/blockchain_test.go @@ -161,7 +161,7 @@ func TestAddBlockStateRoot(t *testing.T) { func TestAddBadBlock(t *testing.T) { bc := newTestChain(t) // It has ValidUntilBlock == 0, which is wrong - tx := transaction.New(netmode.UnitTestNet, []byte{byte(opcode.PUSH1)}, 0) + tx := transaction.New([]byte{byte(opcode.PUSH1)}, 0) tx.Signers = []transaction.Signer{{ Account: testchain.MultisigScriptHash(), Scopes: transaction.None, @@ -180,7 +180,7 @@ func TestAddBadBlock(t *testing.T) { bc.config.VerifyBlocks = false require.NoError(t, bc.AddBlock(b2)) - tx = transaction.New(netmode.UnitTestNet, []byte{byte(opcode.PUSH1)}, 0) + tx = transaction.New([]byte{byte(opcode.PUSH1)}, 0) tx.ValidUntilBlock = 128 tx.Signers = []transaction.Signer{{ Account: testchain.MultisigScriptHash(), @@ -196,7 +196,7 @@ func TestAddBadBlock(t *testing.T) { func TestGetHeader(t *testing.T) { bc := newTestChain(t) - tx := transaction.New(netmode.UnitTestNet, []byte{byte(opcode.PUSH1)}, 0) + tx := transaction.New([]byte{byte(opcode.PUSH1)}, 0) tx.ValidUntilBlock = bc.BlockHeight() + 1 addSigners(neoOwner, tx) assert.Nil(t, testchain.SignTx(bc, tx)) @@ -263,7 +263,7 @@ func TestGetBlock(t *testing.T) { } func (bc *Blockchain) newTestTx(h util.Uint160, script []byte) *transaction.Transaction { - tx := transaction.New(testchain.Network(), script, 1_000_000) + tx := transaction.New(script, 1_000_000) tx.Nonce = rand.Uint32() tx.ValidUntilBlock = 100 tx.Signers = []transaction.Signer{{ @@ -333,12 +333,12 @@ func TestVerifyTx(t *testing.T) { t.Run("Expired", func(t *testing.T) { tx := bc.newTestTx(h, testScript) tx.ValidUntilBlock = 1 - require.NoError(t, accs[0].SignTx(tx)) + require.NoError(t, accs[0].SignTx(netmode.UnitTestNet, tx)) checkErr(t, ErrTxExpired, tx) }) t.Run("BlockedAccount", func(t *testing.T) { tx := bc.newTestTx(accs[1].PrivateKey().GetScriptHash(), testScript) - require.NoError(t, accs[1].SignTx(tx)) + require.NoError(t, accs[1].SignTx(netmode.UnitTestNet, tx)) err := bc.VerifyTx(tx) require.True(t, errors.Is(err, ErrPolicy)) }) @@ -346,20 +346,20 @@ func TestVerifyTx(t *testing.T) { balance := bc.GetUtilityTokenBalance(h) tx := bc.newTestTx(h, testScript) tx.SystemFee = balance.Int64() + 1 - require.NoError(t, accs[0].SignTx(tx)) + require.NoError(t, accs[0].SignTx(netmode.UnitTestNet, tx)) checkErr(t, ErrInsufficientFunds, tx) }) t.Run("TooBigTx", func(t *testing.T) { script := make([]byte, transaction.MaxTransactionSize) tx := bc.newTestTx(h, script) - require.NoError(t, accs[0].SignTx(tx)) + require.NoError(t, accs[0].SignTx(netmode.UnitTestNet, tx)) checkErr(t, ErrTxTooBig, tx) }) t.Run("NetworkFee", func(t *testing.T) { t.Run("SmallNetworkFee", func(t *testing.T) { tx := bc.newTestTx(h, testScript) tx.NetworkFee = 1 - require.NoError(t, accs[0].SignTx(tx)) + require.NoError(t, accs[0].SignTx(netmode.UnitTestNet, tx)) checkErr(t, ErrTxSmallNetworkFee, tx) }) t.Run("AlmostEnoughNetworkFee", func(t *testing.T) { @@ -368,7 +368,7 @@ func TestVerifyTx(t *testing.T) { expectedSize := io.GetVarSize(tx) + calcultedScriptSize calculatedNetFee := verificationNetFee + int64(expectedSize)*bc.FeePerByte() tx.NetworkFee = calculatedNetFee - 1 - require.NoError(t, accs[0].SignTx(tx)) + require.NoError(t, accs[0].SignTx(netmode.UnitTestNet, tx)) require.Equal(t, expectedSize, io.GetVarSize(tx)) checkErr(t, ErrVerificationFailed, tx) }) @@ -378,7 +378,7 @@ func TestVerifyTx(t *testing.T) { expectedSize := io.GetVarSize(tx) + calcultedScriptSize calculatedNetFee := verificationNetFee + int64(expectedSize)*bc.FeePerByte() tx.NetworkFee = calculatedNetFee - require.NoError(t, accs[0].SignTx(tx)) + require.NoError(t, accs[0].SignTx(netmode.UnitTestNet, tx)) require.Equal(t, expectedSize, io.GetVarSize(tx)) require.NoError(t, bc.VerifyTx(tx)) }) @@ -389,7 +389,7 @@ func TestVerifyTx(t *testing.T) { expectedSize += calculatedScriptSize expectedNetFee := verificationNetFee + int64(expectedSize)*bc.FeePerByte() tx.NetworkFee = expectedNetFee - require.NoError(t, accs[0].SignTx(tx)) + require.NoError(t, accs[0].SignTx(netmode.UnitTestNet, tx)) actualSize := io.GetVarSize(tx) require.Equal(t, expectedSize, actualSize) interopCtx := bc.newInteropContext(trigger.Verification, bc.dao, nil, tx) @@ -408,7 +408,7 @@ func TestVerifyTx(t *testing.T) { expectedSize := io.GetVarSize(tx) + calculatedScriptSize expectedNetFee := verificationNetFee + int64(expectedSize)*bc.FeePerByte() tx.NetworkFee = expectedNetFee - require.NoError(t, multisigAcc.SignTx(tx)) + require.NoError(t, multisigAcc.SignTx(netmode.UnitTestNet, tx)) actualSize := io.GetVarSize(tx) require.Equal(t, expectedSize, actualSize) interopCtx := bc.newInteropContext(trigger.Verification, bc.dao, nil, tx) @@ -421,7 +421,7 @@ func TestVerifyTx(t *testing.T) { t.Run("InvalidTxScript", func(t *testing.T) { tx := bc.newTestTx(h, testScript) tx.Script = append(tx.Script, 0xff) - require.NoError(t, accs[0].SignTx(tx)) + require.NoError(t, accs[0].SignTx(netmode.UnitTestNet, tx)) checkErr(t, ErrInvalidScript, tx) }) t.Run("InvalidVerificationScript", func(t *testing.T) { @@ -432,7 +432,7 @@ func TestVerifyTx(t *testing.T) { Scopes: transaction.Global, }) tx.NetworkFee += 1000000 - require.NoError(t, accs[0].SignTx(tx)) + require.NoError(t, accs[0].SignTx(netmode.UnitTestNet, tx)) tx.Scripts = append(tx.Scripts, transaction.Witness{ InvocationScript: []byte{}, VerificationScript: verif, @@ -447,7 +447,7 @@ func TestVerifyTx(t *testing.T) { Scopes: transaction.Global, }) tx.NetworkFee += 1000000 - require.NoError(t, accs[0].SignTx(tx)) + require.NoError(t, accs[0].SignTx(netmode.UnitTestNet, tx)) tx.Scripts = append(tx.Scripts, transaction.Witness{ InvocationScript: []byte{byte(opcode.JMP), 3, 0xff}, VerificationScript: verif, @@ -458,24 +458,24 @@ func TestVerifyTx(t *testing.T) { balance := bc.GetUtilityTokenBalance(h).Int64() tx := bc.newTestTx(h, testScript) tx.NetworkFee = balance / 2 - require.NoError(t, accs[0].SignTx(tx)) + require.NoError(t, accs[0].SignTx(netmode.UnitTestNet, tx)) require.NoError(t, bc.PoolTx(tx)) tx2 := bc.newTestTx(h, testScript) tx2.NetworkFee = balance / 2 - require.NoError(t, accs[0].SignTx(tx2)) + require.NoError(t, accs[0].SignTx(netmode.UnitTestNet, tx2)) err := bc.PoolTx(tx2) require.True(t, errors.Is(err, ErrMemPoolConflict)) }) t.Run("InvalidWitnessHash", func(t *testing.T) { tx := bc.newTestTx(h, testScript) - require.NoError(t, accs[0].SignTx(tx)) + require.NoError(t, accs[0].SignTx(netmode.UnitTestNet, tx)) tx.Scripts[0].VerificationScript = []byte{byte(opcode.PUSHT)} checkErr(t, ErrWitnessHashMismatch, tx) }) t.Run("InvalidWitnessSignature", func(t *testing.T) { tx := bc.newTestTx(h, testScript) - require.NoError(t, accs[0].SignTx(tx)) + require.NoError(t, accs[0].SignTx(netmode.UnitTestNet, tx)) tx.Scripts[0].InvocationScript[10] = ^tx.Scripts[0].InvocationScript[10] checkErr(t, ErrVerificationFailed, tx) }) @@ -485,13 +485,13 @@ func TestVerifyTx(t *testing.T) { Account: accs[3].PrivateKey().GetScriptHash(), Scopes: transaction.Global, }) - require.NoError(t, accs[0].SignTx(tx)) - require.NoError(t, accs[3].SignTx(tx)) + require.NoError(t, accs[0].SignTx(netmode.UnitTestNet, tx)) + require.NoError(t, accs[3].SignTx(netmode.UnitTestNet, tx)) checkErr(t, ErrVerificationFailed, tx) }) t.Run("OldTX", func(t *testing.T) { tx := bc.newTestTx(h, testScript) - require.NoError(t, accs[0].SignTx(tx)) + require.NoError(t, accs[0].SignTx(netmode.UnitTestNet, tx)) b := bc.newBlock(tx) require.NoError(t, bc.AddBlock(b)) @@ -500,7 +500,7 @@ func TestVerifyTx(t *testing.T) { }) t.Run("MemPooledTX", func(t *testing.T) { tx := bc.newTestTx(h, testScript) - require.NoError(t, accs[0].SignTx(tx)) + require.NoError(t, accs[0].SignTx(netmode.UnitTestNet, tx)) require.NoError(t, bc.PoolTx(tx)) err := bc.PoolTx(tx) @@ -510,11 +510,11 @@ func TestVerifyTx(t *testing.T) { bc.memPool = mempool.New(1, 0, false) tx1 := bc.newTestTx(h, testScript) tx1.NetworkFee += 10000 // Give it more priority. - require.NoError(t, accs[0].SignTx(tx1)) + require.NoError(t, accs[0].SignTx(netmode.UnitTestNet, tx1)) require.NoError(t, bc.PoolTx(tx1)) tx2 := bc.newTestTx(h, testScript) - require.NoError(t, accs[0].SignTx(tx2)) + require.NoError(t, accs[0].SignTx(netmode.UnitTestNet, tx2)) err := bc.PoolTx(tx2) require.True(t, errors.Is(err, ErrOOM)) }) @@ -522,7 +522,7 @@ func TestVerifyTx(t *testing.T) { t.Run("InvalidHighPriority", func(t *testing.T) { tx := bc.newTestTx(h, testScript) tx.Attributes = append(tx.Attributes, transaction.Attribute{Type: transaction.HighPriority}) - require.NoError(t, accs[0].SignTx(tx)) + require.NoError(t, accs[0].SignTx(netmode.UnitTestNet, tx)) checkErr(t, ErrInvalidAttribute, tx) }) t.Run("ValidHighPriority", func(t *testing.T) { @@ -539,9 +539,8 @@ func TestVerifyTx(t *testing.T) { netFee, sizeDelta := fee.Calculate(bc.GetBaseExecFee(), rawScript) tx.NetworkFee += netFee tx.NetworkFee += int64(size+sizeDelta) * bc.FeePerByte() - data := tx.GetSignedPart() tx.Scripts = []transaction.Witness{{ - InvocationScript: testchain.SignCommittee(data), + InvocationScript: testchain.SignCommittee(tx), VerificationScript: rawScript, }} require.NoError(t, bc.VerifyTx(tx)) @@ -583,17 +582,17 @@ func TestVerifyTx(t *testing.T) { t.Run("NoOracleNodes", func(t *testing.T) { tx := getOracleTx(t) - require.NoError(t, oracleAcc.SignTx(tx)) + require.NoError(t, oracleAcc.SignTx(netmode.UnitTestNet, tx)) checkErr(t, ErrInvalidAttribute, tx) }) - txSetOracle := transaction.New(netmode.UnitTestNet, []byte{byte(opcode.RET)}, 0) // it's a hack, so we don't need a real script + txSetOracle := transaction.New([]byte{byte(opcode.RET)}, 0) // it's a hack, so we don't need a real script setSigner(txSetOracle, testchain.CommitteeScriptHash()) txSetOracle.Scripts = []transaction.Witness{{ - InvocationScript: testchain.SignCommittee(txSetOracle.GetSignedPart()), + InvocationScript: testchain.SignCommittee(txSetOracle), VerificationScript: testchain.CommitteeVerificationScript(), }} - bl := block.New(netmode.UnitTestNet, bc.config.StateRootInHeader) + bl := block.New(bc.config.StateRootInHeader) bl.Index = bc.BlockHeight() + 1 ic := bc.newInteropContext(trigger.All, bc.dao, bl, txSetOracle) ic.SpawnVM() @@ -604,7 +603,7 @@ func TestVerifyTx(t *testing.T) { t.Run("Valid", func(t *testing.T) { tx := getOracleTx(t) - require.NoError(t, oracleAcc.SignTx(tx)) + require.NoError(t, oracleAcc.SignTx(netmode.UnitTestNet, tx)) require.NoError(t, bc.VerifyTx(tx)) t.Run("NativeVerify", func(t *testing.T) { @@ -632,31 +631,31 @@ func TestVerifyTx(t *testing.T) { t.Run("InvalidRequestID", func(t *testing.T) { tx := getOracleTx(t) tx.Attributes[0].Value.(*transaction.OracleResponse).ID = 2 - require.NoError(t, oracleAcc.SignTx(tx)) + require.NoError(t, oracleAcc.SignTx(netmode.UnitTestNet, tx)) checkErr(t, ErrInvalidAttribute, tx) }) t.Run("InvalidScope", func(t *testing.T) { tx := getOracleTx(t) tx.Signers[0].Scopes = transaction.Global - require.NoError(t, oracleAcc.SignTx(tx)) + require.NoError(t, oracleAcc.SignTx(netmode.UnitTestNet, tx)) checkErr(t, ErrInvalidAttribute, tx) }) t.Run("InvalidScript", func(t *testing.T) { tx := getOracleTx(t) tx.Script = append(tx.Script, byte(opcode.NOP)) - require.NoError(t, oracleAcc.SignTx(tx)) + require.NoError(t, oracleAcc.SignTx(netmode.UnitTestNet, tx)) checkErr(t, ErrInvalidAttribute, tx) }) t.Run("InvalidSigner", func(t *testing.T) { tx := getOracleTx(t) tx.Signers[0].Account = accs[0].Contract.ScriptHash() - require.NoError(t, accs[0].SignTx(tx)) + require.NoError(t, accs[0].SignTx(netmode.UnitTestNet, tx)) checkErr(t, ErrInvalidAttribute, tx) }) t.Run("SmallFee", func(t *testing.T) { tx := getOracleTx(t) tx.SystemFee = 0 - require.NoError(t, oracleAcc.SignTx(tx)) + require.NoError(t, oracleAcc.SignTx(netmode.UnitTestNet, tx)) checkErr(t, ErrInvalidAttribute, tx) }) }) @@ -675,9 +674,8 @@ func TestVerifyTx(t *testing.T) { netFee, sizeDelta := fee.Calculate(bc.GetBaseExecFee(), rawScript) tx.NetworkFee += netFee tx.NetworkFee += int64(size+sizeDelta) * bc.FeePerByte() - data := tx.GetSignedPart() tx.Scripts = []transaction.Witness{{ - InvocationScript: testchain.SignCommittee(data), + InvocationScript: testchain.SignCommittee(tx), VerificationScript: rawScript, }} return tx @@ -713,9 +711,8 @@ func TestVerifyTx(t *testing.T) { netFee, sizeDelta := fee.Calculate(bc.GetBaseExecFee(), rawScript) tx.NetworkFee += netFee tx.NetworkFee += int64(size+sizeDelta) * bc.FeePerByte() - data := tx.GetSignedPart() tx.Scripts = []transaction.Witness{{ - InvocationScript: testchain.SignCommittee(data), + InvocationScript: testchain.SignCommittee(tx), VerificationScript: rawScript, }} return tx @@ -753,9 +750,8 @@ func TestVerifyTx(t *testing.T) { netFee, sizeDelta := fee.Calculate(bc.GetBaseExecFee(), rawScript) tx.NetworkFee += netFee tx.NetworkFee += int64(size+sizeDelta) * bc.FeePerByte() - data := tx.GetSignedPart() tx.Scripts = []transaction.Witness{{ - InvocationScript: testchain.SignCommittee(data), + InvocationScript: testchain.SignCommittee(tx), VerificationScript: rawScript, }} return tx @@ -769,14 +765,14 @@ func TestVerifyTx(t *testing.T) { bc.config.P2PSigExtensions = true t.Run("dummy on-chain conflict", func(t *testing.T) { tx := bc.newTestTx(h, testScript) - require.NoError(t, accs[0].SignTx(tx)) + require.NoError(t, accs[0].SignTx(netmode.UnitTestNet, tx)) dummyTx := transaction.NewTrimmedTX(tx.Hash()) dummyTx.Version = transaction.DummyVersion require.NoError(t, bc.dao.StoreAsTransaction(dummyTx, bc.blockHeight, nil)) require.True(t, errors.Is(bc.VerifyTx(tx), ErrHasConflicts)) }) t.Run("attribute on-chain conflict", func(t *testing.T) { - tx := transaction.New(netmode.UnitTestNet, []byte{byte(opcode.PUSH1)}, 0) + tx := transaction.New([]byte{byte(opcode.PUSH1)}, 0) tx.ValidUntilBlock = 4242 tx.Signers = []transaction.Signer{{ Account: testchain.MultisigScriptHash(), @@ -798,13 +794,13 @@ func TestVerifyTx(t *testing.T) { t.Run("NotaryAssisted", func(t *testing.T) { notary, err := wallet.NewAccount() require.NoError(t, err) - txSetNotary := transaction.New(netmode.UnitTestNet, []byte{byte(opcode.RET)}, 0) + txSetNotary := transaction.New([]byte{byte(opcode.RET)}, 0) setSigner(txSetNotary, testchain.CommitteeScriptHash()) txSetNotary.Scripts = []transaction.Witness{{ - InvocationScript: testchain.SignCommittee(txSetNotary.GetSignedPart()), + InvocationScript: testchain.SignCommittee(txSetNotary), VerificationScript: testchain.CommitteeVerificationScript(), }} - bl := block.New(netmode.UnitTestNet, false) + bl := block.New(false) bl.Index = bc.BlockHeight() + 1 ic := bc.newInteropContext(trigger.All, bc.dao, bl, txSetNotary) ic.SpawnVM() @@ -833,14 +829,13 @@ func TestVerifyTx(t *testing.T) { netFee, sizeDelta := fee.Calculate(bc.GetBaseExecFee(), rawScript) tx.NetworkFee += netFee tx.NetworkFee += int64(size+sizeDelta) * bc.FeePerByte() - data := tx.GetSignedPart() tx.Scripts = []transaction.Witness{ { - InvocationScript: testchain.SignCommittee(data), + InvocationScript: testchain.SignCommittee(tx), VerificationScript: rawScript, }, { - InvocationScript: append([]byte{byte(opcode.PUSHDATA1), 64}, notary.PrivateKey().Sign(data)...), + InvocationScript: append([]byte{byte(opcode.PUSHDATA1), 64}, notary.PrivateKey().SignHashable(uint32(testchain.Network()), tx)...), }, } return tx @@ -870,14 +865,13 @@ func TestVerifyTx(t *testing.T) { Scopes: transaction.None, }, } - data := tx.GetSignedPart() tx.Scripts = []transaction.Witness{ { - InvocationScript: testchain.SignCommittee(data), + InvocationScript: testchain.SignCommittee(tx), VerificationScript: testchain.CommitteeVerificationScript(), }, { - InvocationScript: append([]byte{byte(opcode.PUSHDATA1), 64}, notary.PrivateKey().Sign(data)...), + InvocationScript: append([]byte{byte(opcode.PUSHDATA1), 64}, notary.PrivateKey().SignHashable(uint32(testchain.Network()), tx)...), }, } require.Error(t, bc.VerifyTx(tx)) @@ -894,13 +888,12 @@ func TestVerifyTx(t *testing.T) { Scopes: transaction.None, }, } - data := tx.GetSignedPart() tx.Scripts = []transaction.Witness{ { - InvocationScript: append([]byte{byte(opcode.PUSHDATA1), 64}, notary.PrivateKey().Sign(data)...), + InvocationScript: append([]byte{byte(opcode.PUSHDATA1), 64}, notary.PrivateKey().SignHashable(uint32(testchain.Network()), tx)...), }, { - InvocationScript: testchain.SignCommittee(data), + InvocationScript: testchain.SignCommittee(tx), VerificationScript: testchain.CommitteeVerificationScript(), }, } @@ -918,14 +911,13 @@ func TestVerifyTx(t *testing.T) { Scopes: transaction.CalledByEntry, }, } - data := tx.GetSignedPart() tx.Scripts = []transaction.Witness{ { - InvocationScript: testchain.SignCommittee(data), + InvocationScript: testchain.SignCommittee(tx), VerificationScript: testchain.CommitteeVerificationScript(), }, { - InvocationScript: append([]byte{byte(opcode.PUSHDATA1), 64}, notary.PrivateKey().Sign(data)...), + InvocationScript: append([]byte{byte(opcode.PUSHDATA1), 64}, notary.PrivateKey().SignHashable(uint32(testchain.Network()), tx)...), }, } require.Error(t, bc.VerifyTx(tx)) @@ -938,10 +930,9 @@ func TestVerifyTx(t *testing.T) { Scopes: transaction.None, }, } - data := tx.GetSignedPart() tx.Scripts = []transaction.Witness{ { - InvocationScript: testchain.SignCommittee(data), + InvocationScript: testchain.SignCommittee(tx), VerificationScript: testchain.CommitteeVerificationScript(), }, } @@ -959,16 +950,15 @@ func TestVerifyTx(t *testing.T) { Scopes: transaction.None, }, } - data := tx.GetSignedPart() acc, err := keys.NewPrivateKey() require.NoError(t, err) tx.Scripts = []transaction.Witness{ { - InvocationScript: testchain.SignCommittee(data), + InvocationScript: testchain.SignCommittee(tx), VerificationScript: testchain.CommitteeVerificationScript(), }, { - InvocationScript: append([]byte{byte(opcode.PUSHDATA1), 64}, acc.Sign(data)...), + InvocationScript: append([]byte{byte(opcode.PUSHDATA1), 64}, acc.SignHashable(uint32(testchain.Network()), tx)...), }, } require.Error(t, bc.VerifyTx(tx)) @@ -981,10 +971,9 @@ func TestVerifyTx(t *testing.T) { Scopes: transaction.None, }, } - data := tx.GetSignedPart() tx.Scripts = []transaction.Witness{ { - InvocationScript: append([]byte{byte(opcode.PUSHDATA1), 64}, notary.PrivateKey().Sign(data)...), + InvocationScript: append([]byte{byte(opcode.PUSHDATA1), 64}, notary.PrivateKey().SignHashable(uint32(testchain.Network()), tx)...), }, } require.Error(t, bc.VerifyTx(tx)) @@ -1039,7 +1028,7 @@ func TestVerifyTx(t *testing.T) { VerificationScript: []byte{}, }, { - InvocationScript: testchain.Sign(tx.GetSignedPart()), + InvocationScript: testchain.Sign(tx), VerificationScript: testchain.MultisigVerificationScript(), }, } @@ -1066,7 +1055,7 @@ func TestVerifyTx(t *testing.T) { VerificationScript: []byte{}, }, { - InvocationScript: testchain.Sign(tx.GetSignedPart()), + InvocationScript: testchain.Sign(tx), VerificationScript: testchain.MultisigVerificationScript(), }, } @@ -1165,7 +1154,7 @@ func TestIsTxStillRelevant(t *testing.T) { mp := bc.GetMemPool() newTx := func(t *testing.T) *transaction.Transaction { - tx := transaction.New(netmode.UnitTestNet, []byte{byte(opcode.RET)}, 100) + tx := transaction.New([]byte{byte(opcode.RET)}, 100) tx.ValidUntilBlock = bc.BlockHeight() + 1 tx.Signers = []transaction.Signer{{ Account: neoOwner, @@ -1299,13 +1288,13 @@ func TestHasBlock(t *testing.T) { func TestGetTransaction(t *testing.T) { bc := newTestChain(t) - tx1 := transaction.New(netmode.UnitTestNet, []byte{byte(opcode.PUSH1)}, 0) + tx1 := transaction.New([]byte{byte(opcode.PUSH1)}, 0) tx1.ValidUntilBlock = 16 tx1.Signers = []transaction.Signer{{ Account: testchain.MultisigScriptHash(), Scopes: transaction.CalledByEntry, }} - tx2 := transaction.New(netmode.UnitTestNet, []byte{byte(opcode.PUSH2)}, 0) + tx2 := transaction.New([]byte{byte(opcode.PUSH2)}, 0) tx2.ValidUntilBlock = 16 tx2.Signers = []transaction.Signer{{ Account: testchain.MultisigScriptHash(), @@ -1407,7 +1396,7 @@ func TestSubscriptions(t *testing.T) { emit.Bytes(script.BinWriter, []byte("yay!")) emit.Syscall(script.BinWriter, interopnames.SystemRuntimeNotify) require.NoError(t, script.Err) - txGood1 := transaction.New(netmode.UnitTestNet, script.Bytes(), 0) + txGood1 := transaction.New(script.Bytes(), 0) txGood1.Signers = []transaction.Signer{{Account: neoOwner}} txGood1.Nonce = 1 txGood1.ValidUntilBlock = 1024 @@ -1419,7 +1408,7 @@ func TestSubscriptions(t *testing.T) { emit.Syscall(script.BinWriter, interopnames.SystemRuntimeNotify) emit.Opcodes(script.BinWriter, opcode.THROW) require.NoError(t, script.Err) - txBad := transaction.New(netmode.UnitTestNet, script.Bytes(), 0) + txBad := transaction.New(script.Bytes(), 0) txBad.Signers = []transaction.Signer{{Account: neoOwner}} txBad.Nonce = 2 txBad.ValidUntilBlock = 1024 @@ -1429,7 +1418,7 @@ func TestSubscriptions(t *testing.T) { emit.Bytes(script.BinWriter, []byte("yay! yay! yay!")) emit.Syscall(script.BinWriter, interopnames.SystemRuntimeNotify) require.NoError(t, script.Err) - txGood2 := transaction.New(netmode.UnitTestNet, script.Bytes(), 0) + txGood2 := transaction.New(script.Bytes(), 0) txGood2.Signers = []transaction.Signer{{Account: neoOwner}} txGood2.Nonce = 3 txGood2.ValidUntilBlock = 1024 diff --git a/pkg/core/blockchainer/blockchainer.go b/pkg/core/blockchainer/blockchainer.go index c9936e9d0..9ea0ad873 100644 --- a/pkg/core/blockchainer/blockchainer.go +++ b/pkg/core/blockchainer/blockchainer.go @@ -9,7 +9,7 @@ import ( "github.com/nspcc-dev/neo-go/pkg/core/mempool" "github.com/nspcc-dev/neo-go/pkg/core/state" "github.com/nspcc-dev/neo-go/pkg/core/transaction" - "github.com/nspcc-dev/neo-go/pkg/crypto" + "github.com/nspcc-dev/neo-go/pkg/crypto/hash" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/smartcontract/trigger" "github.com/nspcc-dev/neo-go/pkg/util" @@ -71,7 +71,7 @@ type Blockchainer interface { SubscribeForNotifications(ch chan<- *state.NotificationEvent) SubscribeForTransactions(ch chan<- *transaction.Transaction) VerifyTx(*transaction.Transaction) error - VerifyWitness(util.Uint160, crypto.Verifiable, *transaction.Witness, int64) error + VerifyWitness(util.Uint160, hash.Hashable, *transaction.Witness, int64) error GetMemPool() *mempool.Pool UnsubscribeFromBlocks(ch chan<- *block.Block) UnsubscribeFromExecutions(ch chan<- *state.AppExecResult) diff --git a/pkg/core/chaindump/dump.go b/pkg/core/chaindump/dump.go index 9fc9e6649..6f5cd7259 100644 --- a/pkg/core/chaindump/dump.go +++ b/pkg/core/chaindump/dump.go @@ -47,7 +47,6 @@ func Restore(bc blockchainer.Blockchainer, r *io.BinReader, skip, count uint32, } } - magic := bc.GetConfig().Magic stateRootInHeader := bc.GetConfig().StateRootInHeader for ; i < skip+count; i++ { @@ -55,7 +54,7 @@ func Restore(bc blockchainer.Blockchainer, r *io.BinReader, skip, count uint32, if err != nil { return err } - b := block.New(magic, stateRootInHeader) + b := block.New(stateRootInHeader) r := io.NewBinReaderFromBuf(buf) b.DecodeBinary(r) if r.Err != nil { diff --git a/pkg/core/dao/cacheddao_test.go b/pkg/core/dao/cacheddao_test.go index db45c7cb1..d1c99bd71 100644 --- a/pkg/core/dao/cacheddao_test.go +++ b/pkg/core/dao/cacheddao_test.go @@ -4,7 +4,6 @@ import ( "testing" "github.com/nspcc-dev/neo-go/internal/random" - "github.com/nspcc-dev/neo-go/pkg/config/netmode" "github.com/nspcc-dev/neo-go/pkg/core/state" "github.com/nspcc-dev/neo-go/pkg/core/storage" "github.com/stretchr/testify/assert" @@ -14,7 +13,7 @@ import ( func TestCachedCachedDao(t *testing.T) { store := storage.NewMemoryStore() // Persistent DAO to check for backing storage. - pdao := NewSimple(store, netmode.UnitTestNet, false) + pdao := NewSimple(store, false) assert.NotEqual(t, store, pdao.Store) // Cached DAO. cdao := NewCached(pdao) diff --git a/pkg/core/dao/dao.go b/pkg/core/dao/dao.go index 85289656a..9e1f371f7 100644 --- a/pkg/core/dao/dao.go +++ b/pkg/core/dao/dao.go @@ -7,7 +7,6 @@ import ( iocore "io" "sort" - "github.com/nspcc-dev/neo-go/pkg/config/netmode" "github.com/nspcc-dev/neo-go/pkg/core/block" "github.com/nspcc-dev/neo-go/pkg/core/mpt" "github.com/nspcc-dev/neo-go/pkg/core/state" @@ -68,16 +67,15 @@ type DAO interface { // Simple is memCached wrapper around DB, simple DAO implementation. type Simple struct { - Store *storage.MemCachedStore - network netmode.Magic + Store *storage.MemCachedStore // stateRootInHeader specifies if block header contains state root. stateRootInHeader bool } // NewSimple creates new simple dao using provided backend store. -func NewSimple(backend storage.Store, network netmode.Magic, stateRootInHeader bool) *Simple { +func NewSimple(backend storage.Store, stateRootInHeader bool) *Simple { st := storage.NewMemCachedStore(backend) - return &Simple{Store: st, network: network, stateRootInHeader: stateRootInHeader} + return &Simple{Store: st, stateRootInHeader: stateRootInHeader} } // GetBatch returns currently accumulated DB changeset. @@ -88,7 +86,7 @@ func (dao *Simple) GetBatch() *storage.MemBatch { // GetWrapped returns new DAO instance with another layer of wrapped // MemCachedStore around the current DAO Store. func (dao *Simple) GetWrapped() DAO { - d := NewSimple(dao.Store, dao.network, dao.stateRootInHeader) + d := NewSimple(dao.Store, dao.stateRootInHeader) return d } @@ -363,7 +361,7 @@ func (dao *Simple) GetBlock(hash util.Uint256) (*block.Block, error) { return nil, err } - block, err := block.NewBlockFromTrimmedBytes(dao.network, dao.stateRootInHeader, b) + block, err := block.NewBlockFromTrimmedBytes(dao.stateRootInHeader, b) if err != nil { return nil, err } @@ -448,7 +446,7 @@ func (dao *Simple) GetTransaction(hash util.Uint256) (*transaction.Transaction, var height = r.ReadU32LE() - tx := &transaction.Transaction{Network: dao.network} + tx := &transaction.Transaction{} tx.DecodeBinary(r) if r.Err != nil { return nil, 0, r.Err @@ -530,7 +528,7 @@ func (dao *Simple) DeleteBlock(h util.Uint256, w *io.BufBinWriter) error { return err } - b, err := block.NewBlockFromTrimmedBytes(dao.network, dao.stateRootInHeader, bs) + b, err := block.NewBlockFromTrimmedBytes(dao.stateRootInHeader, bs) if err != nil { return err } diff --git a/pkg/core/dao/dao_test.go b/pkg/core/dao/dao_test.go index e5eedbfcf..fb8bb0960 100644 --- a/pkg/core/dao/dao_test.go +++ b/pkg/core/dao/dao_test.go @@ -5,7 +5,6 @@ import ( "testing" "github.com/nspcc-dev/neo-go/internal/random" - "github.com/nspcc-dev/neo-go/pkg/config/netmode" "github.com/nspcc-dev/neo-go/pkg/core/block" "github.com/nspcc-dev/neo-go/pkg/core/state" "github.com/nspcc-dev/neo-go/pkg/core/storage" @@ -18,7 +17,7 @@ import ( ) func TestPutGetAndDecode(t *testing.T) { - dao := NewSimple(storage.NewMemoryStore(), netmode.UnitTestNet, false) + dao := NewSimple(storage.NewMemoryStore(), false) serializable := &TestSerializable{field: random.String(4)} hash := []byte{1} err := dao.Put(serializable, hash) @@ -43,7 +42,7 @@ func (t *TestSerializable) DecodeBinary(reader *io.BinReader) { } func TestPutGetAppExecResult(t *testing.T) { - dao := NewSimple(storage.NewMemoryStore(), netmode.UnitTestNet, false) + dao := NewSimple(storage.NewMemoryStore(), false) hash := random.Uint256() appExecResult := &state.AppExecResult{ Container: hash, @@ -61,7 +60,7 @@ func TestPutGetAppExecResult(t *testing.T) { } func TestPutGetStorageItem(t *testing.T) { - dao := NewSimple(storage.NewMemoryStore(), netmode.UnitTestNet, false) + dao := NewSimple(storage.NewMemoryStore(), false) id := int32(random.Int(0, 1024)) key := []byte{0} storageItem := state.StorageItem{} @@ -72,7 +71,7 @@ func TestPutGetStorageItem(t *testing.T) { } func TestDeleteStorageItem(t *testing.T) { - dao := NewSimple(storage.NewMemoryStore(), netmode.UnitTestNet, false) + dao := NewSimple(storage.NewMemoryStore(), false) id := int32(random.Int(0, 1024)) key := []byte{0} storageItem := state.StorageItem{} @@ -85,7 +84,7 @@ func TestDeleteStorageItem(t *testing.T) { } func TestGetBlock_NotExists(t *testing.T) { - dao := NewSimple(storage.NewMemoryStore(), netmode.UnitTestNet, false) + dao := NewSimple(storage.NewMemoryStore(), false) hash := random.Uint256() block, err := dao.GetBlock(hash) require.Error(t, err) @@ -93,7 +92,7 @@ func TestGetBlock_NotExists(t *testing.T) { } func TestPutGetBlock(t *testing.T) { - dao := NewSimple(storage.NewMemoryStore(), netmode.UnitTestNet, false) + dao := NewSimple(storage.NewMemoryStore(), false) b := &block.Block{ Header: block.Header{ Script: transaction.Witness{ @@ -111,14 +110,14 @@ func TestPutGetBlock(t *testing.T) { } func TestGetVersion_NoVersion(t *testing.T) { - dao := NewSimple(storage.NewMemoryStore(), netmode.UnitTestNet, false) + dao := NewSimple(storage.NewMemoryStore(), false) version, err := dao.GetVersion() require.Error(t, err) require.Equal(t, "", version) } func TestGetVersion(t *testing.T) { - dao := NewSimple(storage.NewMemoryStore(), netmode.UnitTestNet, false) + dao := NewSimple(storage.NewMemoryStore(), false) err := dao.PutVersion("testVersion") require.NoError(t, err) version, err := dao.GetVersion() @@ -127,14 +126,14 @@ func TestGetVersion(t *testing.T) { } func TestGetCurrentHeaderHeight_NoHeader(t *testing.T) { - dao := NewSimple(storage.NewMemoryStore(), netmode.UnitTestNet, false) + dao := NewSimple(storage.NewMemoryStore(), false) height, err := dao.GetCurrentBlockHeight() require.Error(t, err) require.Equal(t, uint32(0), height) } func TestGetCurrentHeaderHeight_Store(t *testing.T) { - dao := NewSimple(storage.NewMemoryStore(), netmode.UnitTestNet, false) + dao := NewSimple(storage.NewMemoryStore(), false) b := &block.Block{ Header: block.Header{ Script: transaction.Witness{ @@ -151,8 +150,8 @@ func TestGetCurrentHeaderHeight_Store(t *testing.T) { } func TestStoreAsTransaction(t *testing.T) { - dao := NewSimple(storage.NewMemoryStore(), netmode.UnitTestNet, false) - tx := transaction.New(netmode.UnitTestNet, []byte{byte(opcode.PUSH1)}, 1) + dao := NewSimple(storage.NewMemoryStore(), false) + tx := transaction.New([]byte{byte(opcode.PUSH1)}, 1) hash := tx.Hash() err := dao.StoreAsTransaction(tx, 0, nil) require.NoError(t, err) diff --git a/pkg/core/helper_test.go b/pkg/core/helper_test.go index 21c46c920..447975817 100644 --- a/pkg/core/helper_test.go +++ b/pkg/core/helper_test.go @@ -111,7 +111,6 @@ func newBlockCustom(cfg config.ProtocolConfiguration, f func(b *block.Block), } b := &block.Block{ Header: block.Header{ - Network: testchain.Network(), NextConsensus: witness.ScriptHash(), Script: witness, }, @@ -120,7 +119,7 @@ func newBlockCustom(cfg config.ProtocolConfiguration, f func(b *block.Block), f(b) b.RebuildMerkleRoot() - b.Script.InvocationScript = testchain.Sign(b.GetSignedPart()) + b.Script.InvocationScript = testchain.Sign(b) return b } @@ -187,7 +186,7 @@ func getDecodedBlock(t *testing.T, i int) *block.Block { b, err := hex.DecodeString(data["raw"].(string)) require.NoError(t, err) - block := block.New(testchain.Network(), false) + block := block.New(false) require.NoError(t, testserdes.DecodeBinary(b, block)) return block @@ -208,7 +207,6 @@ func getBlockData(i int) (map[string]interface{}, error) { func newDumbBlock() *block.Block { return &block.Block{ Header: block.Header{ - Network: testchain.Network(), Version: 0, PrevHash: hash.Sha256([]byte("a")), MerkleRoot: hash.Sha256([]byte("b")), @@ -221,7 +219,7 @@ func newDumbBlock() *block.Block { }, }, Transactions: []*transaction.Transaction{ - transaction.New(testchain.Network(), []byte{byte(opcode.PUSH1)}, 0), + transaction.New([]byte{byte(opcode.PUSH1)}, 0), }, } } @@ -267,7 +265,7 @@ func TestCreateBasicChain(t *testing.T) { AllowedGroups: nil, }} require.NoError(t, addNetworkFee(bc, txSendRaw, acc0)) - require.NoError(t, acc0.SignTx(txSendRaw)) + require.NoError(t, acc0.SignTx(testchain.Network(), txSendRaw)) bw := io.NewBufBinWriter() txSendRaw.EncodeBinary(bw.BinWriter) t.Logf("sendrawtransaction: %s", base64.StdEncoding.EncodeToString(bw.Bytes())) @@ -353,7 +351,7 @@ func initBasicChain(t *testing.T, bc *Blockchain) { txDeploy.Nonce = getNextNonce() txDeploy.ValidUntilBlock = validUntilBlock require.NoError(t, addNetworkFee(bc, txDeploy, acc0)) - require.NoError(t, acc0.SignTx(txDeploy)) + require.NoError(t, acc0.SignTx(testchain.Network(), txDeploy)) b = bc.newBlock(txDeploy) require.NoError(t, bc.AddBlock(b)) checkTxHalt(t, bc, txDeploy.Hash()) @@ -364,12 +362,12 @@ func initBasicChain(t *testing.T, bc *Blockchain) { script := io.NewBufBinWriter() emit.AppCall(script.BinWriter, cHash, "putValue", callflag.All, "testkey", "testvalue") - txInv := transaction.New(testchain.Network(), script.Bytes(), 1*native.GASFactor) + txInv := transaction.New(script.Bytes(), 1*native.GASFactor) txInv.Nonce = getNextNonce() txInv.ValidUntilBlock = validUntilBlock txInv.Signers = []transaction.Signer{{Account: priv0ScriptHash}} require.NoError(t, addNetworkFee(bc, txInv, acc0)) - require.NoError(t, acc0.SignTx(txInv)) + require.NoError(t, acc0.SignTx(testchain.Network(), txInv)) b = bc.newBlock(txInv) require.NoError(t, bc.AddBlock(b)) checkTxHalt(t, bc, txInv.Hash()) @@ -388,19 +386,19 @@ func initBasicChain(t *testing.T, bc *Blockchain) { }, } require.NoError(t, addNetworkFee(bc, txNeo0to1, acc0)) - require.NoError(t, acc0.SignTx(txNeo0to1)) + require.NoError(t, acc0.SignTx(testchain.Network(), txNeo0to1)) b = bc.newBlock(txNeo0to1) require.NoError(t, bc.AddBlock(b)) checkTxHalt(t, bc, txNeo0to1.Hash()) w := io.NewBufBinWriter() emit.AppCall(w.BinWriter, cHash, "init", callflag.All) - initTx := transaction.New(testchain.Network(), w.Bytes(), 1*native.GASFactor) + initTx := transaction.New(w.Bytes(), 1*native.GASFactor) initTx.Nonce = getNextNonce() initTx.ValidUntilBlock = validUntilBlock initTx.Signers = []transaction.Signer{{Account: priv0ScriptHash}} require.NoError(t, addNetworkFee(bc, initTx, acc0)) - require.NoError(t, acc0.SignTx(initTx)) + require.NoError(t, acc0.SignTx(testchain.Network(), initTx)) transferTx := newNEP17Transfer(cHash, cHash, priv0.GetScriptHash(), 1000) transferTx.Nonce = getNextNonce() transferTx.ValidUntilBlock = validUntilBlock @@ -413,7 +411,7 @@ func initBasicChain(t *testing.T, bc *Blockchain) { }, } require.NoError(t, addNetworkFee(bc, transferTx, acc0)) - require.NoError(t, acc0.SignTx(transferTx)) + require.NoError(t, acc0.SignTx(testchain.Network(), transferTx)) b = bc.newBlock(initTx, transferTx) require.NoError(t, bc.AddBlock(b)) @@ -433,7 +431,7 @@ func initBasicChain(t *testing.T, bc *Blockchain) { }, } require.NoError(t, addNetworkFee(bc, transferTx, acc0)) - require.NoError(t, acc0.SignTx(transferTx)) + require.NoError(t, acc0.SignTx(testchain.Network(), transferTx)) b = bc.newBlock(transferTx) require.NoError(t, bc.AddBlock(b)) @@ -445,7 +443,7 @@ func initBasicChain(t *testing.T, bc *Blockchain) { txDeploy2.Nonce = getNextNonce() txDeploy2.ValidUntilBlock = validUntilBlock require.NoError(t, addNetworkFee(bc, txDeploy2, acc0)) - require.NoError(t, acc0.SignTx(txDeploy2)) + require.NoError(t, acc0.SignTx(testchain.Network(), txDeploy2)) b = bc.newBlock(txDeploy2) require.NoError(t, bc.AddBlock(b)) checkTxHalt(t, bc, txDeploy2.Hash()) @@ -462,7 +460,7 @@ func initBasicChain(t *testing.T, bc *Blockchain) { } require.NoError(t, addNetworkFee(bc, transferTx, acc0)) transferTx.SystemFee += 10_0000 - require.NoError(t, acc0.SignTx(transferTx)) + require.NoError(t, acc0.SignTx(testchain.Network(), transferTx)) b = bc.newBlock(transferTx) require.NoError(t, bc.AddBlock(b)) @@ -481,7 +479,7 @@ func initBasicChain(t *testing.T, bc *Blockchain) { txDeploy3.Nonce = getNextNonce() txDeploy3.ValidUntilBlock = validUntilBlock require.NoError(t, addNetworkFee(bc, txDeploy3, acc0)) - require.NoError(t, acc0.SignTx(txDeploy3)) + require.NoError(t, acc0.SignTx(testchain.Network(), txDeploy3)) b = bc.newBlock(txDeploy3) require.NoError(t, bc.AddBlock(b)) checkTxHalt(t, bc, txDeploy3.Hash()) @@ -499,7 +497,7 @@ func newNEP17Transfer(sc, from, to util.Uint160, amount int64, additionalArgs .. } script := w.Bytes() - return transaction.New(testchain.Network(), script, 11000000) + return transaction.New(script, 11000000) } func newDeployTx(t *testing.T, bc *Blockchain, sender util.Uint160, name, ctrName string, cfgName *string) (*transaction.Transaction, util.Uint160) { @@ -549,7 +547,7 @@ func prepareContractMethodInvokeGeneric(chain *Blockchain, sysfee int64, return nil, w.Err } script := w.Bytes() - tx := transaction.New(chain.GetConfig().Magic, script, sysfee) + tx := transaction.New(script, sysfee) tx.ValidUntilBlock = chain.blockHeight + 1 var err error switch s := signer.(type) { @@ -592,7 +590,7 @@ func signTxWithAccounts(chain *Blockchain, tx *transaction.Transaction, accs ... tx.NetworkFee += int64(size) * chain.FeePerByte() for _, acc := range accs { - if err := acc.SignTx(tx); err != nil { + if err := acc.SignTx(testchain.Network(), tx); err != nil { panic(err) } } diff --git a/pkg/core/interop/context.go b/pkg/core/interop/context.go index 9f7471ab7..e973a68a2 100644 --- a/pkg/core/interop/context.go +++ b/pkg/core/interop/context.go @@ -12,7 +12,7 @@ import ( "github.com/nspcc-dev/neo-go/pkg/core/interop/interopnames" "github.com/nspcc-dev/neo-go/pkg/core/state" "github.com/nspcc-dev/neo-go/pkg/core/transaction" - "github.com/nspcc-dev/neo-go/pkg/crypto" + "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/callflag" "github.com/nspcc-dev/neo-go/pkg/smartcontract/manifest" @@ -34,7 +34,8 @@ const ( // Context represents context in which interops are executed. type Context struct { Chain blockchainer.Blockchainer - Container crypto.Verifiable + Container hash.Hashable + Network uint32 Natives []Contract Trigger trigger.Type Block *block.Block @@ -55,6 +56,7 @@ func NewContext(trigger trigger.Type, bc blockchainer.Blockchainer, d dao.DAO, nes := make([]state.NotificationEvent, 0) return &Context{ Chain: bc, + Network: uint32(bc.GetConfig().Magic), Natives: natives, Trigger: trigger, Block: block, diff --git a/pkg/core/interop/crypto/ecdsa.go b/pkg/core/interop/crypto/ecdsa.go index 78b9ddb1e..14c93aed4 100644 --- a/pkg/core/interop/crypto/ecdsa.go +++ b/pkg/core/interop/crypto/ecdsa.go @@ -7,6 +7,7 @@ import ( "github.com/nspcc-dev/neo-go/pkg/core/fee" "github.com/nspcc-dev/neo-go/pkg/core/interop" + "github.com/nspcc-dev/neo-go/pkg/crypto/hash" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/vm" ) @@ -14,7 +15,6 @@ import ( // ECDSASecp256r1CheckMultisig checks multiple ECDSA signatures at once using // Secp256r1 elliptic curve. func ECDSASecp256r1CheckMultisig(ic *interop.Context) error { - hashToCheck := ic.Container.GetSignedHash() pkeys, err := ic.VM.Estack().PopSigElements() if err != nil { return fmt.Errorf("wrong parameters: %w", err) @@ -31,21 +31,20 @@ func ECDSASecp256r1CheckMultisig(ic *interop.Context) error { if len(pkeys) < len(sigs) { return errors.New("more signatures than there are keys") } - sigok := vm.CheckMultisigPar(ic.VM, elliptic.P256(), hashToCheck.BytesBE(), pkeys, sigs) + sigok := vm.CheckMultisigPar(ic.VM, elliptic.P256(), hash.NetSha256(ic.Network, ic.Container).BytesBE(), pkeys, sigs) ic.VM.Estack().PushVal(sigok) return nil } // ECDSASecp256r1CheckSig checks ECDSA signature using Secp256r1 elliptic curve. func ECDSASecp256r1CheckSig(ic *interop.Context) error { - hashToCheck := ic.Container.GetSignedHash() keyb := ic.VM.Estack().Pop().Bytes() signature := ic.VM.Estack().Pop().Bytes() pkey, err := keys.NewPublicKeyFromBytes(keyb, elliptic.P256()) if err != nil { return err } - res := pkey.Verify(signature, hashToCheck.BytesBE()) + res := pkey.VerifyHashable(signature, ic.Network, ic.Container) ic.VM.Estack().PushVal(res) return nil } diff --git a/pkg/core/interop/crypto/ecdsa_test.go b/pkg/core/interop/crypto/ecdsa_test.go index e82f64414..a8d0bf610 100644 --- a/pkg/core/interop/crypto/ecdsa_test.go +++ b/pkg/core/interop/crypto/ecdsa_test.go @@ -11,6 +11,7 @@ import ( "github.com/nspcc-dev/neo-go/pkg/core/interop" "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/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/smartcontract/trigger" "github.com/nspcc-dev/neo-go/pkg/util" @@ -21,7 +22,7 @@ import ( "github.com/stretchr/testify/require" ) -func initCHECKMULTISIG(msg []byte, n int) ([]stackitem.Item, []stackitem.Item, map[string]*keys.PublicKey, error) { +func initCHECKMULTISIG(msgHash util.Uint256, n int) ([]stackitem.Item, []stackitem.Item, map[string]*keys.PublicKey, error) { var err error keyMap := make(map[string]*keys.PublicKey) @@ -41,7 +42,7 @@ func initCHECKMULTISIG(msg []byte, n int) ([]stackitem.Item, []stackitem.Item, m sigs := make([]stackitem.Item, n) for i := range sigs { - sig := pkeys[i].Sign(msg) + sig := pkeys[i].SignHash(msgHash) sigs[i] = stackitem.NewByteArray(sig) } @@ -67,6 +68,7 @@ func initCheckMultisigVMNoArgs(container *transaction.Transaction) *vm.VM { binary.LittleEndian.PutUint32(buf[1:], neoCryptoCheckMultisigID) ic := &interop.Context{ + Network: uint32(netmode.UnitTestNet), Trigger: trigger.Verification, Container: container, } @@ -77,13 +79,13 @@ func initCheckMultisigVMNoArgs(container *transaction.Transaction) *vm.VM { } func initCHECKMULTISIGVM(t *testing.T, n int, ik, is []int) *vm.VM { - tx := transaction.New(netmode.UnitTestNet, []byte("NEO - An Open Network For Smart Economy"), 10) + tx := transaction.New([]byte("NEO - An Open Network For Smart Economy"), 10) tx.Signers = []transaction.Signer{{Account: util.Uint160{1, 2, 3}}} tx.Scripts = []transaction.Witness{{}} v := initCheckMultisigVMNoArgs(tx) - pubs, sigs, _, err := initCHECKMULTISIG(tx.GetSignedPart(), n) + pubs, sigs, _, err := initCHECKMULTISIG(hash.NetSha256(uint32(netmode.UnitTestNet), tx), n) require.NoError(t, err) pubs = subSlice(pubs, ik) @@ -145,10 +147,10 @@ func testCurveCHECKMULTISIGBad(t *testing.T) { }) msg := []byte("NEO - An Open Network For Smart Economy") - pubs, sigs, _, err := initCHECKMULTISIG(msg, 1) + pubs, sigs, _, err := initCHECKMULTISIG(hash.Sha256(msg), 1) require.NoError(t, err) arr := stackitem.NewArray([]stackitem.Item{stackitem.NewArray(nil)}) - tx := transaction.New(netmode.UnitTestNet, []byte("NEO - An Open Network For Smart Economy"), 10) + tx := transaction.New([]byte("NEO - An Open Network For Smart Economy"), 10) tx.Signers = []transaction.Signer{{Account: util.Uint160{1, 2, 3}}} tx.Scripts = []transaction.Witness{{}} @@ -171,8 +173,8 @@ func TestCheckSig(t *testing.T) { require.NoError(t, err) verifyFunc := ECDSASecp256r1CheckSig - d := dao.NewSimple(storage.NewMemoryStore(), netmode.UnitTestNet, false) - ic := &interop.Context{DAO: dao.NewCached(d)} + d := dao.NewSimple(storage.NewMemoryStore(), false) + ic := &interop.Context{Network: uint32(netmode.UnitTestNet), DAO: dao.NewCached(d)} runCase := func(t *testing.T, isErr bool, result interface{}, args ...interface{}) { ic.SpawnVM() for i := range args { @@ -198,29 +200,28 @@ func TestCheckSig(t *testing.T) { require.Equal(t, result, ic.VM.Estack().Pop().Value().(bool)) } - tx := transaction.New(netmode.UnitTestNet, []byte{0, 1, 2}, 1) - msg := tx.GetSignedPart() + tx := transaction.New([]byte{0, 1, 2}, 1) ic.Container = tx t.Run("success", func(t *testing.T) { - sign := priv.Sign(msg) + sign := priv.SignHashable(uint32(netmode.UnitTestNet), tx) runCase(t, false, true, sign, priv.PublicKey().Bytes()) }) t.Run("missing argument", func(t *testing.T) { runCase(t, true, false) - sign := priv.Sign(msg) + sign := priv.SignHashable(uint32(netmode.UnitTestNet), tx) runCase(t, true, false, sign) }) t.Run("invalid signature", func(t *testing.T) { - sign := priv.Sign(msg) + sign := priv.SignHashable(uint32(netmode.UnitTestNet), tx) sign[0] = ^sign[0] runCase(t, false, false, sign, priv.PublicKey().Bytes()) }) t.Run("invalid public key", func(t *testing.T) { - sign := priv.Sign(msg) + sign := priv.SignHashable(uint32(netmode.UnitTestNet), tx) pub := priv.PublicKey().Bytes() pub[0] = 0xFF // invalid prefix runCase(t, true, false, sign, pub) diff --git a/pkg/core/interop/runtime/engine_test.go b/pkg/core/interop/runtime/engine_test.go index a6a23ae3e..87618e00d 100644 --- a/pkg/core/interop/runtime/engine_test.go +++ b/pkg/core/interop/runtime/engine_test.go @@ -7,7 +7,6 @@ import ( "testing" "github.com/nspcc-dev/neo-go/internal/random" - "github.com/nspcc-dev/neo-go/pkg/config/netmode" "github.com/nspcc-dev/neo-go/pkg/core/block" "github.com/nspcc-dev/neo-go/pkg/core/interop" "github.com/nspcc-dev/neo-go/pkg/crypto/hash" @@ -45,7 +44,7 @@ func TestPlatform(t *testing.T) { } func TestGetTime(t *testing.T) { - b := block.New(netmode.UnitTestNet, false) + b := block.New(false) b.Timestamp = rand.Uint64() ic := &interop.Context{VM: vm.New(), Block: b} require.NoError(t, GetTime(ic)) diff --git a/pkg/core/interop_neo_test.go b/pkg/core/interop_neo_test.go index 8d2976960..a2ee8c6c8 100644 --- a/pkg/core/interop_neo_test.go +++ b/pkg/core/interop_neo_test.go @@ -4,7 +4,6 @@ import ( "math/big" "testing" - "github.com/nspcc-dev/neo-go/pkg/config/netmode" "github.com/nspcc-dev/neo-go/pkg/core/block" "github.com/nspcc-dev/neo-go/pkg/core/dao" "github.com/nspcc-dev/neo-go/pkg/core/interop" @@ -213,7 +212,7 @@ func TestStorageFind(t *testing.T) { func createVM(t *testing.T) (*vm.VM, *interop.Context, *Blockchain) { chain := newTestChain(t) context := chain.newInteropContext(trigger.Application, - dao.NewSimple(storage.NewMemoryStore(), netmode.UnitTestNet, chain.config.StateRootInHeader), nil, nil) + dao.NewSimple(storage.NewMemoryStore(), chain.config.StateRootInHeader), nil, nil) v := context.SpawnVM() return v, context, chain } @@ -227,7 +226,7 @@ func createVMAndPushBlock(t *testing.T) (*vm.VM, *block.Block, *interop.Context, func createVMAndBlock(t *testing.T) (*vm.VM, *block.Block, *interop.Context, *Blockchain) { block := newDumbBlock() chain := newTestChain(t) - d := dao.NewSimple(storage.NewMemoryStore(), netmode.UnitTestNet, chain.GetConfig().StateRootInHeader) + d := dao.NewSimple(storage.NewMemoryStore(), chain.GetConfig().StateRootInHeader) context := chain.newInteropContext(trigger.Application, d, block, nil) v := context.SpawnVM() return v, block, context, chain @@ -254,7 +253,7 @@ func createVMAndContractState(t *testing.T) (*vm.VM, *state.Contract, *interop.C } chain := newTestChain(t) - d := dao.NewSimple(storage.NewMemoryStore(), netmode.UnitTestNet, chain.config.StateRootInHeader) + d := dao.NewSimple(storage.NewMemoryStore(), chain.config.StateRootInHeader) context := chain.newInteropContext(trigger.Application, d, nil, nil) v := context.SpawnVM() return v, contractState, context, chain @@ -262,11 +261,11 @@ func createVMAndContractState(t *testing.T) (*vm.VM, *state.Contract, *interop.C func createVMAndTX(t *testing.T) (*vm.VM, *transaction.Transaction, *interop.Context, *Blockchain) { script := []byte{byte(opcode.PUSH1), byte(opcode.RET)} - tx := transaction.New(netmode.UnitTestNet, script, 0) + tx := transaction.New(script, 0) tx.Signers = []transaction.Signer{{Account: util.Uint160{1, 2, 3, 4}}} tx.Scripts = []transaction.Witness{{InvocationScript: []byte{}, VerificationScript: []byte{}}} chain := newTestChain(t) - d := dao.NewSimple(storage.NewMemoryStore(), netmode.UnitTestNet, chain.config.StateRootInHeader) + d := dao.NewSimple(storage.NewMemoryStore(), chain.config.StateRootInHeader) context := chain.newInteropContext(trigger.Application, d, nil, tx) v := context.SpawnVM() return v, tx, context, chain diff --git a/pkg/core/interops_test.go b/pkg/core/interops_test.go index efed8f7cd..0db9acd40 100644 --- a/pkg/core/interops_test.go +++ b/pkg/core/interops_test.go @@ -5,7 +5,6 @@ import ( "runtime" "testing" - "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" "github.com/nspcc-dev/neo-go/pkg/core/storage" @@ -18,7 +17,7 @@ func testNonInterop(t *testing.T, value interface{}, f func(*interop.Context) er v := vm.New() v.Estack().PushVal(value) chain := newTestChain(t) - d := dao.NewSimple(storage.NewMemoryStore(), netmode.UnitTestNet, chain.config.StateRootInHeader) + d := dao.NewSimple(storage.NewMemoryStore(), chain.config.StateRootInHeader) context := chain.newInteropContext(trigger.Application, d, nil, nil) context.VM = v require.Error(t, f(context)) diff --git a/pkg/core/mempool/mem_pool_test.go b/pkg/core/mempool/mem_pool_test.go index c7b79ef80..694ce8960 100644 --- a/pkg/core/mempool/mem_pool_test.go +++ b/pkg/core/mempool/mem_pool_test.go @@ -8,7 +8,6 @@ import ( "time" "github.com/nspcc-dev/neo-go/internal/random" - "github.com/nspcc-dev/neo-go/pkg/config/netmode" "github.com/nspcc-dev/neo-go/pkg/core/transaction" "github.com/nspcc-dev/neo-go/pkg/network/payload" "github.com/nspcc-dev/neo-go/pkg/util" @@ -46,7 +45,7 @@ func (fs *FeerStub) P2PSigExtensionsEnabled() bool { func testMemPoolAddRemoveWithFeer(t *testing.T, fs Feer) { mp := New(10, 0, false) - tx := transaction.New(netmode.UnitTestNet, []byte{byte(opcode.PUSH1)}, 0) + tx := transaction.New([]byte{byte(opcode.PUSH1)}, 0) tx.Nonce = 0 tx.Signers = []transaction.Signer{{Account: util.Uint160{1, 2, 3}}} _, ok := mp.TryGetValue(tx.Hash()) @@ -69,7 +68,7 @@ func TestMemPoolRemoveStale(t *testing.T) { mp := New(5, 0, false) txs := make([]*transaction.Transaction, 5) for i := range txs { - txs[i] = transaction.New(netmode.UnitTestNet, []byte{byte(opcode.PUSH1)}, 0) + txs[i] = transaction.New([]byte{byte(opcode.PUSH1)}, 0) txs[i].Nonce = uint32(i) txs[i].Signers = []transaction.Signer{{Account: util.Uint160{1, 2, 3}}} require.NoError(t, mp.Add(txs[i], &FeerStub{blockHeight: uint32(i)})) @@ -120,7 +119,7 @@ func TestOverCapacity(t *testing.T) { mp := New(mempoolSize, 0, false) for i := 0; i < mempoolSize; i++ { - tx := transaction.New(netmode.UnitTestNet, []byte{byte(opcode.PUSH1)}, 0) + tx := transaction.New([]byte{byte(opcode.PUSH1)}, 0) tx.Nonce = uint32(i) tx.Signers = []transaction.Signer{{Account: util.Uint160{1, 2, 3}}} require.NoError(t, mp.Add(tx, fs)) @@ -134,7 +133,7 @@ func TestOverCapacity(t *testing.T) { bigScript[1] = byte(opcode.RET) // Fees are also prioritized. for i := 0; i < mempoolSize; i++ { - tx := transaction.New(netmode.UnitTestNet, bigScript, 0) + tx := transaction.New(bigScript, 0) tx.NetworkFee = 10000 tx.Nonce = txcnt tx.Signers = []transaction.Signer{{Account: util.Uint160{1, 2, 3}}} @@ -145,7 +144,7 @@ func TestOverCapacity(t *testing.T) { require.Equal(t, true, sort.IsSorted(sort.Reverse(mp.verifiedTxes))) } // Less prioritized txes are not allowed anymore. - tx := transaction.New(netmode.UnitTestNet, bigScript, 0) + tx := transaction.New(bigScript, 0) tx.NetworkFee = 100 tx.Nonce = txcnt tx.Signers = []transaction.Signer{{Account: util.Uint160{1, 2, 3}}} @@ -158,7 +157,7 @@ func TestOverCapacity(t *testing.T) { require.Equal(t, true, sort.IsSorted(sort.Reverse(mp.verifiedTxes))) // Low net fee, but higher per-byte fee is still a better combination. - tx = transaction.New(netmode.UnitTestNet, []byte{byte(opcode.PUSH1)}, 0) + tx = transaction.New([]byte{byte(opcode.PUSH1)}, 0) tx.Nonce = txcnt tx.NetworkFee = 7000 tx.Signers = []transaction.Signer{{Account: util.Uint160{1, 2, 3}}} @@ -171,7 +170,7 @@ func TestOverCapacity(t *testing.T) { // High priority always wins over low priority. for i := 0; i < mempoolSize; i++ { - tx := transaction.New(netmode.UnitTestNet, []byte{byte(opcode.PUSH1)}, 0) + tx := transaction.New([]byte{byte(opcode.PUSH1)}, 0) tx.NetworkFee = 8000 tx.Nonce = txcnt tx.Signers = []transaction.Signer{{Account: util.Uint160{1, 2, 3}}} @@ -181,7 +180,7 @@ func TestOverCapacity(t *testing.T) { require.Equal(t, true, sort.IsSorted(sort.Reverse(mp.verifiedTxes))) } // Good luck with low priority now. - tx = transaction.New(netmode.UnitTestNet, []byte{byte(opcode.PUSH1)}, 0) + tx = transaction.New([]byte{byte(opcode.PUSH1)}, 0) tx.Nonce = txcnt tx.NetworkFee = 7000 tx.Signers = []transaction.Signer{{Account: util.Uint160{1, 2, 3}}} @@ -197,7 +196,7 @@ func TestGetVerified(t *testing.T) { txes := make([]*transaction.Transaction, 0, mempoolSize) for i := 0; i < mempoolSize; i++ { - tx := transaction.New(netmode.UnitTestNet, []byte{byte(opcode.PUSH1)}, 0) + tx := transaction.New([]byte{byte(opcode.PUSH1)}, 0) tx.Nonce = uint32(i) tx.Signers = []transaction.Signer{{Account: util.Uint160{1, 2, 3}}} txes = append(txes, tx) @@ -222,7 +221,7 @@ func TestRemoveStale(t *testing.T) { txes1 := make([]*transaction.Transaction, 0, mempoolSize/2) txes2 := make([]*transaction.Transaction, 0, mempoolSize/2) for i := 0; i < mempoolSize; i++ { - tx := transaction.New(netmode.UnitTestNet, []byte{byte(opcode.PUSH1)}, 0) + tx := transaction.New([]byte{byte(opcode.PUSH1)}, 0) tx.Nonce = uint32(i) tx.Signers = []transaction.Signer{{Account: util.Uint160{1, 2, 3}}} if i%2 == 0 { @@ -253,7 +252,7 @@ func TestMemPoolFees(t *testing.T) { mp := New(10, 0, false) fs := &FeerStub{balance: 10000000} sender0 := util.Uint160{1, 2, 3} - tx0 := transaction.New(netmode.UnitTestNet, []byte{byte(opcode.PUSH1)}, 0) + tx0 := transaction.New([]byte{byte(opcode.PUSH1)}, 0) tx0.NetworkFee = fs.balance + 1 tx0.Signers = []transaction.Signer{{Account: sender0}} // insufficient funds to add transaction, and balance shouldn't be stored @@ -263,7 +262,7 @@ func TestMemPoolFees(t *testing.T) { balancePart := new(big.Int).Div(big.NewInt(fs.balance), big.NewInt(4)) // no problems with adding another transaction with lower fee - tx1 := transaction.New(netmode.UnitTestNet, []byte{byte(opcode.PUSH1)}, 0) + tx1 := transaction.New([]byte{byte(opcode.PUSH1)}, 0) tx1.NetworkFee = balancePart.Int64() tx1.Signers = []transaction.Signer{{Account: sender0}} require.NoError(t, mp.Add(tx1, fs)) @@ -274,7 +273,7 @@ func TestMemPoolFees(t *testing.T) { }, mp.fees[sender0]) // balance shouldn't change after adding one more transaction - tx2 := transaction.New(netmode.UnitTestNet, []byte{byte(opcode.PUSH1)}, 0) + tx2 := transaction.New([]byte{byte(opcode.PUSH1)}, 0) tx2.NetworkFee = new(big.Int).Sub(big.NewInt(fs.balance), balancePart).Int64() tx2.Signers = []transaction.Signer{{Account: sender0}} require.NoError(t, mp.Add(tx2, fs)) @@ -286,7 +285,7 @@ func TestMemPoolFees(t *testing.T) { }, mp.fees[sender0]) // can't add more transactions as we don't have enough GAS - tx3 := transaction.New(netmode.UnitTestNet, []byte{byte(opcode.PUSH1)}, 0) + tx3 := transaction.New([]byte{byte(opcode.PUSH1)}, 0) tx3.NetworkFee = 1 tx3.Signers = []transaction.Signer{{Account: sender0}} require.Equal(t, false, mp.Verify(tx3, fs)) @@ -324,24 +323,24 @@ func TestMempoolItemsOrder(t *testing.T) { sender0 := util.Uint160{1, 2, 3} balance := big.NewInt(10000000) - tx1 := transaction.New(netmode.UnitTestNet, []byte{byte(opcode.PUSH1)}, 0) + tx1 := transaction.New([]byte{byte(opcode.PUSH1)}, 0) tx1.NetworkFee = new(big.Int).Div(balance, big.NewInt(8)).Int64() tx1.Signers = []transaction.Signer{{Account: sender0}} tx1.Attributes = []transaction.Attribute{{Type: transaction.HighPriority}} item1 := item{txn: tx1} - tx2 := transaction.New(netmode.UnitTestNet, []byte{byte(opcode.PUSH1)}, 0) + tx2 := transaction.New([]byte{byte(opcode.PUSH1)}, 0) tx2.NetworkFee = new(big.Int).Div(balance, big.NewInt(16)).Int64() tx2.Signers = []transaction.Signer{{Account: sender0}} tx2.Attributes = []transaction.Attribute{{Type: transaction.HighPriority}} item2 := item{txn: tx2} - tx3 := transaction.New(netmode.UnitTestNet, []byte{byte(opcode.PUSH1)}, 0) + tx3 := transaction.New([]byte{byte(opcode.PUSH1)}, 0) tx3.NetworkFee = new(big.Int).Div(balance, big.NewInt(2)).Int64() tx3.Signers = []transaction.Signer{{Account: sender0}} item3 := item{txn: tx3} - tx4 := transaction.New(netmode.UnitTestNet, []byte{byte(opcode.PUSH1)}, 0) + tx4 := transaction.New([]byte{byte(opcode.PUSH1)}, 0) tx4.NetworkFee = new(big.Int).Div(balance, big.NewInt(4)).Int64() tx4.Signers = []transaction.Signer{{Account: sender0}} item4 := item{txn: tx4} @@ -365,7 +364,7 @@ func TestMempoolAddRemoveOracleResponse(t *testing.T) { nonce := uint32(0) fs := &FeerStub{balance: 10000} newTx := func(netFee int64, id uint64) *transaction.Transaction { - tx := transaction.New(netmode.UnitTestNet, []byte{byte(opcode.PUSH1)}, 0) + tx := transaction.New([]byte{byte(opcode.PUSH1)}, 0) tx.NetworkFee = netFee tx.Nonce = nonce nonce++ @@ -437,7 +436,7 @@ func TestMempoolAddRemoveConflicts(t *testing.T) { nonce uint32 = 1 ) getConflictsTx := func(netFee int64, hashes ...util.Uint256) *transaction.Transaction { - tx := transaction.New(netmode.UnitTestNet, []byte{byte(opcode.PUSH1)}, 0) + tx := transaction.New([]byte{byte(opcode.PUSH1)}, 0) tx.NetworkFee = netFee tx.Nonce = nonce nonce++ @@ -535,7 +534,7 @@ func TestMempoolAddRemoveConflicts(t *testing.T) { assert.Equal(t, []util.Uint256{tx3.Hash(), tx2.Hash()}, mp.conflicts[tx1.Hash()]) // tx13 conflicts with tx2, but is not signed by tx2.Sender - tx13 := transaction.New(netmode.UnitTestNet, []byte{byte(opcode.PUSH1)}, 0) + tx13 := transaction.New([]byte{byte(opcode.PUSH1)}, 0) tx13.NetworkFee = smallNetFee tx13.Nonce = uint32(random.Int(0, 1e4)) tx13.Signers = []transaction.Signer{{Account: util.Uint160{3, 2, 1}}} @@ -563,7 +562,7 @@ func TestMempoolAddWithDataGetData(t *testing.T) { } mp := New(10, 1, false) newTx := func(t *testing.T, netFee int64) *transaction.Transaction { - tx := transaction.New(netmode.UnitTestNet, []byte{byte(opcode.RET)}, 0) + tx := transaction.New([]byte{byte(opcode.RET)}, 0) tx.Signers = []transaction.Signer{{}, {}} tx.NetworkFee = netFee nonce++ diff --git a/pkg/core/mempool/subscriptions_test.go b/pkg/core/mempool/subscriptions_test.go index 77b18141e..67557455f 100644 --- a/pkg/core/mempool/subscriptions_test.go +++ b/pkg/core/mempool/subscriptions_test.go @@ -4,7 +4,6 @@ import ( "testing" "time" - "github.com/nspcc-dev/neo-go/pkg/config/netmode" "github.com/nspcc-dev/neo-go/pkg/core/transaction" "github.com/nspcc-dev/neo-go/pkg/util" "github.com/nspcc-dev/neo-go/pkg/vm/opcode" @@ -33,7 +32,7 @@ func TestSubscriptions(t *testing.T) { txs := make([]*transaction.Transaction, 4) for i := range txs { - txs[i] = transaction.New(netmode.UnitTestNet, []byte{byte(opcode.PUSH1)}, 0) + txs[i] = transaction.New([]byte{byte(opcode.PUSH1)}, 0) txs[i].Nonce = uint32(i) txs[i].Signers = []transaction.Signer{{Account: util.Uint160{1, 2, 3}}} txs[i].NetworkFee = int64(i) diff --git a/pkg/core/native/management_test.go b/pkg/core/native/management_test.go index 61002accf..d8e619fe1 100644 --- a/pkg/core/native/management_test.go +++ b/pkg/core/native/management_test.go @@ -3,7 +3,6 @@ package native import ( "testing" - "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" "github.com/nspcc-dev/neo-go/pkg/core/state" @@ -18,7 +17,7 @@ import ( func TestDeployGetUpdateDestroyContract(t *testing.T) { mgmt := newManagement() - d := dao.NewCached(dao.NewSimple(storage.NewMemoryStore(), netmode.UnitTestNet, false)) + d := dao.NewCached(dao.NewSimple(storage.NewMemoryStore(), false)) mgmt.Initialize(&interop.Context{DAO: d}) script := []byte{byte(opcode.RET)} sender := util.Uint160{1, 2, 3} @@ -72,12 +71,12 @@ func TestDeployGetUpdateDestroyContract(t *testing.T) { func TestManagement_Initialize(t *testing.T) { t.Run("good", func(t *testing.T) { - d := dao.NewSimple(storage.NewMemoryStore(), netmode.UnitTestNet, false) + d := dao.NewSimple(storage.NewMemoryStore(), false) mgmt := newManagement() require.NoError(t, mgmt.InitializeCache(d)) }) t.Run("invalid contract state", func(t *testing.T) { - d := dao.NewSimple(storage.NewMemoryStore(), netmode.UnitTestNet, false) + d := dao.NewSimple(storage.NewMemoryStore(), false) mgmt := newManagement() require.NoError(t, d.PutStorageItem(mgmt.ID, []byte{prefixContract}, state.StorageItem{0xFF})) require.Error(t, mgmt.InitializeCache(d)) diff --git a/pkg/core/native/notary.go b/pkg/core/native/notary.go index 34beafc4d..269051784 100644 --- a/pkg/core/native/notary.go +++ b/pkg/core/native/notary.go @@ -17,6 +17,7 @@ import ( "github.com/nspcc-dev/neo-go/pkg/core/state" "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/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/smartcontract" "github.com/nspcc-dev/neo-go/pkg/smartcontract/callflag" @@ -356,10 +357,10 @@ func (n *Notary) verify(ic *interop.Context, args []stackitem.Item) stackitem.It if err != nil { panic(fmt.Errorf("failed to get notary nodes: %w", err)) } - hash := tx.GetSignedHash().BytesBE() + shash := hash.NetSha256(uint32(ic.Network), tx) var verified bool for _, n := range notaries { - if n.Verify(sig, hash) { + if n.Verify(sig, shash[:]) { verified = true break } diff --git a/pkg/core/native_contract_test.go b/pkg/core/native_contract_test.go index 17bd076f2..9c7b81fcb 100644 --- a/pkg/core/native_contract_test.go +++ b/pkg/core/native_contract_test.go @@ -5,7 +5,6 @@ import ( "math/big" "testing" - "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/fee" "github.com/nspcc-dev/neo-go/pkg/core/interop" @@ -227,7 +226,7 @@ func TestNativeContract_InvokeInternal(t *testing.T) { }) require.NoError(t, err) - d := dao.NewSimple(storage.NewMemoryStore(), netmode.UnitTestNet, chain.config.StateRootInHeader) + d := dao.NewSimple(storage.NewMemoryStore(), chain.config.StateRootInHeader) ic := chain.newInteropContext(trigger.Application, d, nil, nil) sumOffset := 0 diff --git a/pkg/core/native_designate_test.go b/pkg/core/native_designate_test.go index c19794478..386859359 100644 --- a/pkg/core/native_designate_test.go +++ b/pkg/core/native_designate_test.go @@ -5,7 +5,6 @@ import ( "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/block" "github.com/nspcc-dev/neo-go/pkg/core/native" "github.com/nspcc-dev/neo-go/pkg/core/native/noderoles" @@ -33,7 +32,7 @@ func (bc *Blockchain) setNodesByRole(t *testing.T, ok bool, r noderoles.Role, no emit.Opcodes(w.BinWriter, opcode.PACK) emit.AppCallNoArgs(w.BinWriter, bc.contracts.Designate.Hash, "designateAsRole", callflag.All) require.NoError(t, w.Err) - tx := transaction.New(netmode.UnitTestNet, w.Bytes(), 0) + tx := transaction.New(w.Bytes(), 0) tx.NetworkFee = 10_000_000 tx.SystemFee = 10_000_000 tx.ValidUntilBlock = 100 @@ -49,7 +48,7 @@ func (bc *Blockchain) setNodesByRole(t *testing.T, ok bool, r noderoles.Role, no } require.NoError(t, testchain.SignTx(bc, tx)) tx.Scripts = append(tx.Scripts, transaction.Witness{ - InvocationScript: testchain.SignCommittee(tx.GetSignedPart()), + InvocationScript: testchain.SignCommittee(tx), VerificationScript: testchain.CommitteeVerificationScript(), }) require.NoError(t, bc.AddBlock(bc.newBlock(tx))) @@ -114,8 +113,8 @@ func TestDesignate_DesignateAsRole(t *testing.T) { bc := newTestChain(t) des := bc.contracts.Designate - tx := transaction.New(netmode.UnitTestNet, []byte{}, 0) - bl := block.New(netmode.UnitTestNet, bc.config.StateRootInHeader) + tx := transaction.New([]byte{}, 0) + bl := block.New(bc.config.StateRootInHeader) bl.Index = bc.BlockHeight() + 1 ic := bc.newInteropContext(trigger.OnPersist, bc.dao, bl, tx) ic.SpawnVM() diff --git a/pkg/core/native_name_service_test.go b/pkg/core/native_name_service_test.go index dc519aaa2..e79e559d4 100644 --- a/pkg/core/native_name_service_test.go +++ b/pkg/core/native_name_service_test.go @@ -329,7 +329,7 @@ func testTokensOf(t *testing.T, bc *Blockchain, signer *wallet.Account, result [ emit.Opcodes(w.BinWriter, opcode.PACK) require.NoError(t, w.Err) script := w.Bytes() - tx := transaction.New(bc.GetConfig().Magic, script, defaultNameServiceSysfee) + tx := transaction.New(script, defaultNameServiceSysfee) tx.ValidUntilBlock = bc.BlockHeight() + 1 signTxWithAccounts(bc, tx, signer) aers, err := persistBlock(bc, tx) diff --git a/pkg/core/native_neo_test.go b/pkg/core/native_neo_test.go index d86cd9e47..b085ba824 100644 --- a/pkg/core/native_neo_test.go +++ b/pkg/core/native_neo_test.go @@ -41,7 +41,7 @@ func TestNEO_Vote(t *testing.T) { bc := newTestChain(t) neo := bc.contracts.NEO - tx := transaction.New(netmode.UnitTestNet, []byte{byte(opcode.PUSH1)}, 0) + tx := transaction.New([]byte{byte(opcode.PUSH1)}, 0) ic := bc.newInteropContext(trigger.Application, bc.dao, nil, tx) ic.SpawnVM() ic.Block = bc.newBlock(tx) @@ -85,7 +85,7 @@ func TestNEO_Vote(t *testing.T) { int64(1_000_000_000), nil) emit.Opcodes(w.BinWriter, opcode.ASSERT) require.NoError(t, w.Err) - tx := transaction.New(netmode.UnitTestNet, w.Bytes(), 1000_000_000) + tx := transaction.New(w.Bytes(), 1000_000_000) tx.ValidUntilBlock = bc.BlockHeight() + 1 setSigner(tx, testchain.MultisigScriptHash()) require.NoError(t, testchain.SignTx(bc, tx)) @@ -146,12 +146,12 @@ func TestNEO_Vote(t *testing.T) { h.BytesBE(), h.BytesBE(), int64(1), nil) emit.Opcodes(w.BinWriter, opcode.ASSERT) require.NoError(t, w.Err) - tx := transaction.New(netmode.UnitTestNet, w.Bytes(), 0) + tx := transaction.New(w.Bytes(), 0) tx.ValidUntilBlock = bc.BlockHeight() + 1 tx.NetworkFee = 2_000_000 tx.SystemFee = 11_000_000 setSigner(tx, h) - require.NoError(t, accs[i].SignTx(tx)) + require.NoError(t, accs[i].SignTx(netmode.UnitTestNet, tx)) txs = append(txs, tx) } require.NoError(t, bc.AddBlock(bc.newBlock(txs...))) @@ -204,7 +204,7 @@ func TestNEO_CalculateBonus(t *testing.T) { bc := newTestChain(t) neo := bc.contracts.NEO - tx := transaction.New(netmode.UnitTestNet, []byte{}, 0) + tx := transaction.New([]byte{}, 0) ic := bc.newInteropContext(trigger.Application, bc.dao, nil, tx) ic.SpawnVM() ic.VM.LoadScript([]byte{byte(opcode.RET)}) diff --git a/pkg/core/native_notary_test.go b/pkg/core/native_notary_test.go index fc1294272..1eed3a19c 100644 --- a/pkg/core/native_notary_test.go +++ b/pkg/core/native_notary_test.go @@ -178,7 +178,7 @@ func TestNotaryContractPipeline(t *testing.T) { testchain.MultisigScriptHash(), acc.PrivateKey().PublicKey().GetScriptHash()) require.NoError(t, w.Err) script := w.Bytes() - withdrawTx := transaction.New(chain.GetConfig().Magic, script, 10000000) + withdrawTx := transaction.New(script, 10000000) withdrawTx.ValidUntilBlock = chain.blockHeight + 1 withdrawTx.NetworkFee = 10000000 withdrawTx.Signers = []transaction.Signer{ @@ -187,7 +187,7 @@ func TestNotaryContractPipeline(t *testing.T) { Scopes: transaction.None, }, } - err = acc.SignTx(withdrawTx) + err = acc.SignTx(chain.GetConfig().Magic, withdrawTx) require.NoError(t, err) b := chain.newBlock(withdrawTx) err = chain.AddBlock(b) @@ -291,13 +291,12 @@ func TestNotaryNodesReward(t *testing.T) { Scopes: transaction.None, }, } - data := tx.GetSignedPart() tx.Scripts = []transaction.Witness{ { - InvocationScript: append([]byte{byte(opcode.PUSHDATA1), 64}, notaryNodes[0].Sign(data)...), + InvocationScript: append([]byte{byte(opcode.PUSHDATA1), 64}, notaryNodes[0].SignHashable(uint32(testchain.Network()), tx)...), }, { - InvocationScript: testchain.Sign(data), + InvocationScript: testchain.Sign(tx), VerificationScript: testchain.MultisigVerificationScript(), }, } diff --git a/pkg/core/native_oracle_test.go b/pkg/core/native_oracle_test.go index f1191278d..3c56fb00a 100644 --- a/pkg/core/native_oracle_test.go +++ b/pkg/core/native_oracle_test.go @@ -7,7 +7,6 @@ import ( "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/block" "github.com/nspcc-dev/neo-go/pkg/core/interop/interopnames" "github.com/nspcc-dev/neo-go/pkg/core/native" @@ -148,8 +147,8 @@ func TestOracle_Request(t *testing.T) { require.NoError(t, err) pub := priv.PublicKey() - tx := transaction.New(netmode.UnitTestNet, []byte{}, 0) - bl := block.New(netmode.UnitTestNet, bc.config.StateRootInHeader) + tx := transaction.New([]byte{}, 0) + bl := block.New(bc.config.StateRootInHeader) bl.Index = bc.BlockHeight() + 1 setSigner(tx, testchain.CommitteeScriptHash()) ic := bc.newInteropContext(trigger.Application, bc.dao, bl, tx) @@ -158,7 +157,7 @@ func TestOracle_Request(t *testing.T) { err = bc.contracts.Designate.DesignateAsRole(ic, noderoles.Oracle, keys.PublicKeys{pub}) require.NoError(t, err) - tx = transaction.New(netmode.UnitTestNet, orc.GetOracleResponseScript(), 0) + tx = transaction.New(orc.GetOracleResponseScript(), 0) ic.Tx = tx ic.Block = bc.newBlock(tx) @@ -208,7 +207,7 @@ func TestOracle_Request(t *testing.T) { _, err := orc.GetRequestInternal(bc.dao, reqID) // ensure ID is 1 require.NoError(t, err) - tx = transaction.New(netmode.UnitTestNet, orc.GetOracleResponseScript(), 0) + tx = transaction.New(orc.GetOracleResponseScript(), 0) tx.Attributes = []transaction.Attribute{{ Type: transaction.OracleResponseT, Value: &transaction.OracleResponse{ diff --git a/pkg/core/notary_test.go b/pkg/core/notary_test.go index c3ee363f0..493cdd492 100644 --- a/pkg/core/notary_test.go +++ b/pkg/core/notary_test.go @@ -12,7 +12,6 @@ import ( "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/block" "github.com/nspcc-dev/neo-go/pkg/core/blockchainer" "github.com/nspcc-dev/neo-go/pkg/core/mempool" @@ -48,7 +47,7 @@ func getTestNotary(t *testing.T, bc *Blockchain, walletPath, pass string, onTx f Log: zaptest.NewLogger(t), } mp := mempool.New(10, 1, true) - ntr, err := notary.NewNotary(cfg, mp, onTx) + ntr, err := notary.NewNotary(cfg, testchain.Network(), mp, onTx) require.NoError(t, err) w, err := wallet.NewWalletFromFile(path.Join(notaryModulePath, walletPath)) @@ -107,7 +106,7 @@ func TestNotary(t *testing.T) { bc.setNodesByRole(t, true, noderoles.P2PNotary, notaryNodes) createFallbackTx := func(requester *wallet.Account, mainTx *transaction.Transaction, nvbIncrement ...uint32) *transaction.Transaction { - fallback := transaction.New(testchain.Network(), []byte{byte(opcode.RET)}, 2000_0000) + fallback := transaction.New([]byte{byte(opcode.RET)}, 2000_0000) fallback.Nonce = nonce nonce++ fallback.SystemFee = 1_0000_0000 @@ -146,12 +145,12 @@ func TestNotary(t *testing.T) { VerificationScript: []byte{}, }, } - requester.SignTx(fallback) + requester.SignTx(testchain.Network(), fallback) return fallback } createStandardRequest := func(requesters []*wallet.Account, NVBincrements ...uint32) []*payload.P2PNotaryRequest { - mainTx := *transaction.New(testchain.Network(), []byte{byte(opcode.RET)}, 11000000) + mainTx := *transaction.New([]byte{byte(opcode.RET)}, 11000000) mainTx.Nonce = nonce nonce++ mainTx.SystemFee = 100000000 @@ -182,7 +181,7 @@ func TestNotary(t *testing.T) { for j := range requesters { scripts[j].VerificationScript = requesters[j].PrivateKey().PublicKey().GetVerificationScript() } - scripts[i].InvocationScript = append([]byte{byte(opcode.PUSHDATA1), 64}, requesters[i].PrivateKey().Sign(main.GetSignedPart())...) + scripts[i].InvocationScript = append([]byte{byte(opcode.PUSHDATA1), 64}, requesters[i].PrivateKey().SignHashable(uint32(testchain.Network()), main)...) main.Scripts = scripts _ = main.Size() // for size update test @@ -199,13 +198,12 @@ func TestNotary(t *testing.T) { payloads[i] = &payload.P2PNotaryRequest{ MainTransaction: main, FallbackTransaction: fallback, - Network: netmode.UnitTestNet, } } return payloads } createMultisigRequest := func(m int, requesters []*wallet.Account) []*payload.P2PNotaryRequest { - mainTx := *transaction.New(testchain.Network(), []byte{byte(opcode.RET)}, 11000000) + mainTx := *transaction.New([]byte{byte(opcode.RET)}, 11000000) mainTx.Nonce = nonce nonce++ mainTx.SystemFee = 100000000 @@ -240,7 +238,7 @@ func TestNotary(t *testing.T) { main := &cp main.Scripts = []transaction.Witness{ { - InvocationScript: append([]byte{byte(opcode.PUSHDATA1), 64}, requesters[i].PrivateKey().Sign(main.GetSignedPart())...), + InvocationScript: append([]byte{byte(opcode.PUSHDATA1), 64}, requesters[i].PrivateKey().SignHashable(uint32(testchain.Network()), main)...), VerificationScript: script, }, {}, // empty Notary witness @@ -249,7 +247,6 @@ func TestNotary(t *testing.T) { payloads[i] = &payload.P2PNotaryRequest{ MainTransaction: main, FallbackTransaction: fallback, - Network: netmode.UnitTestNet, } } return payloads @@ -272,7 +269,7 @@ func TestNotary(t *testing.T) { require.NoError(t, err) } require.Equal(t, transaction.Witness{ - InvocationScript: append([]byte{byte(opcode.PUSHDATA1), 64}, acc1.PrivateKey().Sign(requests[0].MainTransaction.GetSignedPart())...), + InvocationScript: append([]byte{byte(opcode.PUSHDATA1), 64}, acc1.PrivateKey().SignHashable(uint32(testchain.Network()), requests[0].MainTransaction)...), VerificationScript: []byte{}, }, completedTx.Scripts[nKeys]) } else { @@ -289,7 +286,7 @@ func TestNotary(t *testing.T) { _, err := bc.verifyHashAgainstScript(completedTx.Signers[0].Account, &completedTx.Scripts[0], interopCtx, -1) require.NoError(t, err) require.Equal(t, transaction.Witness{ - InvocationScript: append([]byte{byte(opcode.PUSHDATA1), 64}, acc1.PrivateKey().Sign(requests[0].MainTransaction.GetSignedPart())...), + InvocationScript: append([]byte{byte(opcode.PUSHDATA1), 64}, acc1.PrivateKey().SignHashable(uint32(testchain.Network()), requests[0].MainTransaction)...), VerificationScript: []byte{}, }, completedTx.Scripts[1]) // check that only nSigs out of nKeys signatures are presented in the invocation script @@ -312,7 +309,7 @@ func TestNotary(t *testing.T) { require.Equal(t, 2, len(completedTx.Signers)) require.Equal(t, 2, len(completedTx.Scripts)) require.Equal(t, transaction.Witness{ - InvocationScript: append([]byte{byte(opcode.PUSHDATA1), 64}, acc1.PrivateKey().Sign(req.FallbackTransaction.GetSignedPart())...), + InvocationScript: append([]byte{byte(opcode.PUSHDATA1), 64}, acc1.PrivateKey().SignHashable(uint32(testchain.Network()), req.FallbackTransaction)...), VerificationScript: []byte{}, }, completedTx.Scripts[0]) diff --git a/pkg/core/state/mpt_root.go b/pkg/core/state/mpt_root.go index 5fd716ff4..fa1d6b469 100644 --- a/pkg/core/state/mpt_root.go +++ b/pkg/core/state/mpt_root.go @@ -9,27 +9,17 @@ import ( // MPTRoot represents storage state root together with sign info. type MPTRoot struct { - Version byte `json:"version"` - Index uint32 `json:"index"` - Root util.Uint256 `json:"stateroot"` - Witness *transaction.Witness `json:"witness,omitempty"` -} - -// GetSignedPart returns part of MPTRootBase which needs to be signed. -func (s *MPTRoot) GetSignedPart() []byte { - buf := io.NewBufBinWriter() - s.EncodeBinaryUnsigned(buf.BinWriter) - return buf.Bytes() -} - -// GetSignedHash returns hash of MPTRootBase which needs to be signed. -func (s *MPTRoot) GetSignedHash() util.Uint256 { - return hash.Sha256(s.GetSignedPart()) + Version byte `json:"version"` + Index uint32 `json:"index"` + Root util.Uint256 `json:"roothash"` + Witness []transaction.Witness `json:"witnesses"` } // Hash returns hash of s. func (s *MPTRoot) Hash() util.Uint256 { - return hash.DoubleSha256(s.GetSignedPart()) + buf := io.NewBufBinWriter() + s.EncodeBinaryUnsigned(buf.BinWriter) + return hash.Sha256(buf.Bytes()) } // DecodeBinaryUnsigned decodes hashable part of state root. @@ -49,20 +39,11 @@ func (s *MPTRoot) EncodeBinaryUnsigned(w *io.BinWriter) { // DecodeBinary implements io.Serializable. func (s *MPTRoot) DecodeBinary(r *io.BinReader) { s.DecodeBinaryUnsigned(r) - - var ws []transaction.Witness - r.ReadArray(&ws, 1) - if len(ws) == 1 { - s.Witness = &ws[0] - } + r.ReadArray(&s.Witness, 1) } // EncodeBinary implements io.Serializable. func (s *MPTRoot) EncodeBinary(w *io.BinWriter) { s.EncodeBinaryUnsigned(w) - if s.Witness == nil { - w.WriteVarUint(0) - } else { - w.WriteArray([]*transaction.Witness{s.Witness}) - } + w.WriteArray(s.Witness) } diff --git a/pkg/core/state/mpt_root_test.go b/pkg/core/state/mpt_root_test.go index eaf5c45dd..b38621497 100644 --- a/pkg/core/state/mpt_root_test.go +++ b/pkg/core/state/mpt_root_test.go @@ -17,6 +17,7 @@ func testStateRoot() *MPTRoot { Version: byte(rand.Uint32()), Index: rand.Uint32(), Root: random.Uint256(), + Witness: []transaction.Witness{}, } } @@ -25,10 +26,10 @@ func TestStateRoot_Serializable(t *testing.T) { testserdes.EncodeDecodeBinary(t, r, new(MPTRoot)) t.Run("WithWitness", func(t *testing.T) { - r.Witness = &transaction.Witness{ + r.Witness = []transaction.Witness{{ InvocationScript: random.Bytes(10), VerificationScript: random.Bytes(11), - } + }} testserdes.EncodeDecodeBinary(t, r, new(MPTRoot)) }) } @@ -43,7 +44,7 @@ func TestMPTRoot_MarshalJSON(t *testing.T) { js := []byte(`{ "version": 1, "index": 3000000, - "stateroot": "0xb2fd7e368a848ef70d27cf44940a35237333ed05f1d971c9408f0eb285e0b6f3" + "roothash": "0xb2fd7e368a848ef70d27cf44940a35237333ed05f1d971c9408f0eb285e0b6f3" }`) rs := new(MPTRoot) @@ -51,7 +52,7 @@ func TestMPTRoot_MarshalJSON(t *testing.T) { require.EqualValues(t, 1, rs.Version) require.EqualValues(t, 3000000, rs.Index) - require.Nil(t, rs.Witness) + require.Equal(t, 0, len(rs.Witness)) u, err := util.Uint256DecodeStringLE("b2fd7e368a848ef70d27cf44940a35237333ed05f1d971c9408f0eb285e0b6f3") require.NoError(t, err) diff --git a/pkg/core/stateroot/module.go b/pkg/core/stateroot/module.go index 2d63b89b5..fa6f5127d 100644 --- a/pkg/core/stateroot/module.go +++ b/pkg/core/stateroot/module.go @@ -6,6 +6,7 @@ import ( "fmt" "sync" + "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/mpt" "github.com/nspcc-dev/neo-go/pkg/core/state" @@ -19,10 +20,11 @@ import ( type ( // Module represents module for local processing of state roots. Module struct { - Store *storage.MemCachedStore - mpt *mpt.Trie - bc blockchainer.Blockchainer - log *zap.Logger + Store *storage.MemCachedStore + network netmode.Magic + mpt *mpt.Trie + bc blockchainer.Blockchainer + log *zap.Logger currentLocal atomic.Value localHeight atomic.Uint32 @@ -45,9 +47,10 @@ type ( // NewModule returns new instance of stateroot module. func NewModule(bc blockchainer.Blockchainer, log *zap.Logger, s *storage.MemCachedStore) *Module { return &Module{ - bc: bc, - log: log, - Store: s, + network: bc.GetConfig().Magic, + bc: bc, + log: log, + Store: s, } } @@ -129,6 +132,9 @@ func (s *Module) VerifyStateRoot(r *state.MPTRoot) error { if err != nil { return errors.New("can't get previous state root") } + if len(r.Witness) != 1 { + return errors.New("no witness") + } return s.verifyWitness(r) } @@ -139,5 +145,5 @@ func (s *Module) verifyWitness(r *state.MPTRoot) error { s.mtx.Lock() h := s.getKeyCacheForHeight(r.Index).validatorsHash s.mtx.Unlock() - return s.bc.VerifyWitness(h, r, r.Witness, maxVerificationGAS) + return s.bc.VerifyWitness(h, r, &r.Witness[0], maxVerificationGAS) } diff --git a/pkg/core/stateroot/store.go b/pkg/core/stateroot/store.go index b2ab7d210..865073159 100644 --- a/pkg/core/stateroot/store.go +++ b/pkg/core/stateroot/store.go @@ -46,7 +46,7 @@ func (s *Module) getStateRoot(key []byte) (*state.MPTRoot, error) { return nil, err } - sr := new(state.MPTRoot) + sr := &state.MPTRoot{} r := io.NewBinReaderFromBuf(data) sr.DecodeBinary(r) return sr, r.Err @@ -69,7 +69,7 @@ func (s *Module) AddStateRoot(sr *state.MPTRoot) error { if err != nil { return err } - if local.Witness != nil { + if len(local.Witness) != 0 { return nil } if err := s.putStateRoot(key, sr); err != nil { diff --git a/pkg/core/stateroot_test.go b/pkg/core/stateroot_test.go index dc9632081..2277fdfac 100644 --- a/pkg/core/stateroot_test.go +++ b/pkg/core/stateroot_test.go @@ -10,6 +10,7 @@ import ( "github.com/nspcc-dev/neo-go/internal/testserdes" "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/native/noderoles" "github.com/nspcc-dev/neo-go/pkg/core/state" "github.com/nspcc-dev/neo-go/pkg/core/storage" @@ -32,17 +33,17 @@ func testSignStateRoot(t *testing.T, r *state.MPTRoot, pubs keys.PublicKeys, acc n := smartcontract.GetMajorityHonestNodeCount(len(accs)) w := io.NewBufBinWriter() for i := 0; i < n; i++ { - sig := accs[i].PrivateKey().SignHash(r.GetSignedHash()) + sig := accs[i].PrivateKey().SignHashable(uint32(netmode.UnitTestNet), r) emit.Bytes(w.BinWriter, sig) } require.NoError(t, w.Err) script, err := smartcontract.CreateMajorityMultiSigRedeemScript(pubs.Copy()) require.NoError(t, err) - r.Witness = &transaction.Witness{ + r.Witness = []transaction.Witness{{ VerificationScript: script, InvocationScript: w.Bytes(), - } + }} data, err := testserdes.EncodeBinary(stateroot.NewMessage(stateroot.RootT, r)) require.NoError(t, err) return data @@ -131,8 +132,8 @@ func TestStateRoot(t *testing.T) { r, err = srv.GetStateRoot(updateIndex + 1) require.NoError(t, err) - require.NotNil(t, r.Witness) - require.Equal(t, h, r.Witness.ScriptHash()) + require.NotEqual(t, 0, len(r.Witness)) + require.Equal(t, h, r.Witness[0].ScriptHash()) } func TestStateRootInitNonZeroHeight(t *testing.T) { @@ -220,7 +221,7 @@ func TestStateRootFull(t *testing.T) { r, err := srv.GetStateRoot(2) require.NoError(t, err) - require.NoError(t, srv.AddSignature(2, 0, accs[0].PrivateKey().SignHash(r.GetSignedHash()))) + require.NoError(t, srv.AddSignature(2, 0, accs[0].PrivateKey().SignHashable(uint32(netmode.UnitTestNet), r))) require.NotNil(t, lastValidated.Load().(*payload.Extensible)) msg := new(stateroot.Message) @@ -249,5 +250,5 @@ func checkVoteBroadcasted(t *testing.T, bc *Blockchain, p *payload.Extensible, pubs, _, err := bc.contracts.Designate.GetDesignatedByRole(bc.dao, noderoles.StateValidator, bc.BlockHeight()) require.True(t, len(pubs) > int(valIndex)) - require.True(t, pubs[valIndex].Verify(vote.Signature, r.GetSignedHash().BytesBE())) + require.True(t, pubs[valIndex].VerifyHashable(vote.Signature, uint32(netmode.UnitTestNet), r)) } diff --git a/pkg/core/transaction/helper_test.go b/pkg/core/transaction/helper_test.go index fddfa503d..13987a18c 100644 --- a/pkg/core/transaction/helper_test.go +++ b/pkg/core/transaction/helper_test.go @@ -4,7 +4,6 @@ import ( "encoding/base64" "testing" - "github.com/nspcc-dev/neo-go/pkg/config/netmode" "github.com/stretchr/testify/assert" ) @@ -16,7 +15,7 @@ var ( func decodeTransaction(rawTX string, t *testing.T) *Transaction { b, err1 := base64.StdEncoding.DecodeString(rawTX) assert.Nil(t, err1) - tx, err := NewTransactionFromBytes(netmode.PrivNet, b) + tx, err := NewTransactionFromBytes(b) assert.NoError(t, err) return tx } diff --git a/pkg/core/transaction/transaction.go b/pkg/core/transaction/transaction.go index b2eb455e8..d49b8061d 100644 --- a/pkg/core/transaction/transaction.go +++ b/pkg/core/transaction/transaction.go @@ -7,7 +7,6 @@ import ( "math" "math/rand" - "github.com/nspcc-dev/neo-go/pkg/config/netmode" "github.com/nspcc-dev/neo-go/pkg/crypto/hash" "github.com/nspcc-dev/neo-go/pkg/encoding/address" "github.com/nspcc-dev/neo-go/pkg/io" @@ -66,20 +65,12 @@ type Transaction struct { // and invocation script. Scripts []Witness - // Network magic number. This one actually is not a part of the - // wire-representation of Transaction, but it's absolutely necessary - // for correct signing/verification. - Network netmode.Magic - // size is transaction's serialized size. size int // Hash of the transaction (double SHA256). hash util.Uint256 - // Hash of the transaction used to verify it (single SHA256). - verificationHash util.Uint256 - // Trimmed indicates this is a transaction from trimmed // data. Trimmed bool @@ -96,7 +87,7 @@ func NewTrimmedTX(hash util.Uint256) *Transaction { // New returns a new transaction to execute given script and pay given system // fee. -func New(network netmode.Magic, script []byte, gas int64) *Transaction { +func New(script []byte, gas int64) *Transaction { return &Transaction{ Version: 0, Nonce: rand.Uint32(), @@ -105,7 +96,6 @@ func New(network netmode.Magic, script []byte, gas int64) *Transaction { Attributes: []Attribute{}, Signers: []Signer{}, Scripts: []Witness{}, - Network: network, } } @@ -119,16 +109,6 @@ func (t *Transaction) Hash() util.Uint256 { return t.hash } -// GetSignedHash returns a hash of the transaction used to verify it. -func (t *Transaction) GetSignedHash() util.Uint256 { - if t.verificationHash.Equals(util.Uint256{}) { - if t.createHash() != nil { - panic("failed to compute hash!") - } - } - return t.verificationHash -} - // HasAttribute returns true iff t has an attribute of type typ. func (t *Transaction) HasAttribute(typ AttrType) bool { for i := range t.Attributes { @@ -229,32 +209,9 @@ func (t *Transaction) createHash() error { } t.hash = hash.Sha256(buf.Bytes()) - buf.Reset() - t.writeSignedPart(buf) - t.verificationHash = hash.Sha256(buf.Bytes()) return nil } -// GetSignedPart returns a part of the transaction which must be signed. -func (t *Transaction) GetSignedPart() []byte { - if t.hash.Equals(util.Uint256{}) { - if err := t.createHash(); err != nil { - panic(fmt.Errorf("failed to compute hash: %w", err)) - } - } - buf := io.NewBufBinWriter() - t.writeSignedPart(buf) - if buf.Err != nil { - return nil - } - return buf.Bytes() -} - -func (t *Transaction) writeSignedPart(buf *io.BufBinWriter) { - buf.WriteU32LE(uint32(t.Network)) - buf.WriteBytes(t.hash[:]) -} - // DecodeHashableFields decodes a part of transaction which should be hashed. func (t *Transaction) DecodeHashableFields(buf []byte) error { r := io.NewBinReaderFromBuf(buf) @@ -270,9 +227,6 @@ func (t *Transaction) DecodeHashableFields(buf []byte) error { t.Scripts = make([]Witness, 0) t.hash = hash.Sha256(buf) - b := io.NewBufBinWriter() - t.writeSignedPart(b) - t.verificationHash = hash.Sha256(b.Bytes()) return nil } @@ -287,8 +241,8 @@ func (t *Transaction) Bytes() []byte { } // NewTransactionFromBytes decodes byte array into *Transaction -func NewTransactionFromBytes(network netmode.Magic, b []byte) (*Transaction, error) { - tx := &Transaction{Network: network} +func NewTransactionFromBytes(b []byte) (*Transaction, error) { + tx := &Transaction{} r := io.NewBinReaderFromBuf(b) tx.DecodeBinary(r) if r.Err != nil { diff --git a/pkg/core/transaction/transaction_test.go b/pkg/core/transaction/transaction_test.go index d00344be1..62a46123c 100644 --- a/pkg/core/transaction/transaction_test.go +++ b/pkg/core/transaction/transaction_test.go @@ -10,7 +10,6 @@ import ( "github.com/nspcc-dev/neo-go/internal/random" "github.com/nspcc-dev/neo-go/internal/testserdes" - "github.com/nspcc-dev/neo-go/pkg/config/netmode" "github.com/nspcc-dev/neo-go/pkg/encoding/fixedn" "github.com/nspcc-dev/neo-go/pkg/util" "github.com/nspcc-dev/neo-go/pkg/vm/opcode" @@ -70,7 +69,7 @@ func TestDecodeEncodeInvocationTX(t *testing.T) { func TestNew(t *testing.T) { script := []byte{0x51} - tx := New(netmode.UnitTestNet, script, 1) + tx := New(script, 1) tx.Signers = []Signer{{Account: util.Uint160{1, 2, 3}}} tx.Scripts = []Witness{{InvocationScript: []byte{}, VerificationScript: []byte{}}} assert.Equal(t, int64(1), tx.SystemFee) @@ -78,12 +77,12 @@ func TestNew(t *testing.T) { // Update hash fields to match tx2 that is gonna autoupdate them on decode. _ = tx.Hash() _ = tx.Size() - testserdes.EncodeDecodeBinary(t, tx, &Transaction{Network: netmode.UnitTestNet}) + testserdes.EncodeDecodeBinary(t, tx, &Transaction{}) } func TestNewTransactionFromBytes(t *testing.T) { script := []byte{0x51} - tx := New(netmode.UnitTestNet, script, 1) + tx := New(script, 1) tx.NetworkFee = 123 tx.Signers = []Signer{{Account: util.Uint160{1, 2, 3}}} tx.Scripts = []Witness{{InvocationScript: []byte{}, VerificationScript: []byte{}}} @@ -94,12 +93,12 @@ func TestNewTransactionFromBytes(t *testing.T) { tx.Hash() tx.FeePerByte() - tx1, err := NewTransactionFromBytes(netmode.UnitTestNet, data) + tx1, err := NewTransactionFromBytes(data) require.NoError(t, err) require.Equal(t, tx, tx1) data = append(data, 42) - _, err = NewTransactionFromBytes(netmode.UnitTestNet, data) + _, err = NewTransactionFromBytes(data) require.Error(t, err) } @@ -116,7 +115,7 @@ func TestDecodingTXWithNoScript(t *testing.T) { } func TestDecodingTxWithInvalidWitnessesNumber(t *testing.T) { - tx := New(netmode.UnitTestNet, []byte{byte(opcode.RET)}, 1) + tx := New([]byte{byte(opcode.RET)}, 1) tx.Signers = []Signer{{Account: util.Uint160{1, 2, 3}}} tx.Scripts = []Witness{{InvocationScript: []byte{}, VerificationScript: []byte{}}, {InvocationScript: []byte{}, VerificationScript: []byte{}}} data, err := testserdes.EncodeBinary(tx) @@ -151,7 +150,6 @@ func TestUnmarshalNeoFSTX(t *testing.T) { ] }`) tx := new(Transaction) - tx.Network = 56753 require.NoError(t, json.Unmarshal(txjson, tx)) } @@ -171,7 +169,7 @@ func TestMarshalUnmarshalJSONInvocationTX(t *testing.T) { } func TestTransaction_HasAttribute(t *testing.T) { - tx := New(netmode.UnitTestNet, []byte{1}, 0) + tx := New([]byte{1}, 0) require.False(t, tx.HasAttribute(HighPriority)) tx.Attributes = append(tx.Attributes, Attribute{Type: HighPriority}) require.True(t, tx.HasAttribute(HighPriority)) diff --git a/pkg/core/util.go b/pkg/core/util.go index 0d104a0cb..2c1750ab8 100644 --- a/pkg/core/util.go +++ b/pkg/core/util.go @@ -48,7 +48,6 @@ func createGenesisBlock(cfg config.ProtocolConfiguration) (*block.Block, error) VerificationScript: []byte{byte(opcode.PUSH1)}, }, StateRootEnabled: cfg.StateRootInHeader, - Network: cfg.Magic, } b := &block.Block{ diff --git a/pkg/crypto/hash/hash.go b/pkg/crypto/hash/hash.go index e161e4051..06ce1f421 100644 --- a/pkg/crypto/hash/hash.go +++ b/pkg/crypto/hash/hash.go @@ -2,11 +2,34 @@ package hash import ( "crypto/sha256" + "encoding/binary" "github.com/nspcc-dev/neo-go/pkg/util" "golang.org/x/crypto/ripemd160" ) +// Hashable represents an object which can be hashed. Usually these objects +// are io.Serializable and signable. They tend to cache the hash inside for +// effectiveness, providing this accessor method. Anything that can be +// identified with a hash can then be signed and verified. +type Hashable interface { + Hash() util.Uint256 +} + +func getSignedData(net uint32, hh Hashable) []byte { + var b = make([]byte, 4+32) + binary.LittleEndian.PutUint32(b, net) + h := hh.Hash() + copy(b[4:], h[:]) + return b +} + +// NetSha256 calculates network-specific hash of Hashable item that can then +// be signed/verified. +func NetSha256(net uint32, hh Hashable) util.Uint256 { + return Sha256(getSignedData(net, hh)) +} + // Sha256 hashes the incoming byte slice // using the sha256 algorithm. func Sha256(data []byte) util.Uint256 { diff --git a/pkg/crypto/keys/private_key.go b/pkg/crypto/keys/private_key.go index 111f3283e..adb4460c9 100644 --- a/pkg/crypto/keys/private_key.go +++ b/pkg/crypto/keys/private_key.go @@ -11,6 +11,7 @@ import ( "math/big" "github.com/btcsuite/btcd/btcec" + "github.com/nspcc-dev/neo-go/pkg/crypto/hash" "github.com/nspcc-dev/neo-go/pkg/util" "github.com/nspcc-dev/rfc6979" ) @@ -154,6 +155,12 @@ func (p *PrivateKey) SignHash(digest util.Uint256) []byte { return getSignatureSlice(p.PrivateKey.Curve, r, s) } +// SignHashable signs some Hashable item for the network specified using +// hash.NetSha256() with the private key. +func (p *PrivateKey) SignHashable(net uint32, hh hash.Hashable) []byte { + return p.SignHash(hash.NetSha256(net, hh)) +} + func getSignatureSlice(curve elliptic.Curve, r, s *big.Int) []byte { params := curve.Params() curveOrderByteSize := params.P.BitLen() / 8 diff --git a/pkg/crypto/keys/publickey.go b/pkg/crypto/keys/publickey.go index c5ae4de3f..b4e86d0e9 100644 --- a/pkg/crypto/keys/publickey.go +++ b/pkg/crypto/keys/publickey.go @@ -343,6 +343,13 @@ func (p *PublicKey) Verify(signature []byte, hash []byte) bool { return ecdsa.Verify(&pk, hash, rBytes, sBytes) } +// VerifyHashable returns true if the signature is valid and corresponds +// to the hash and public key. +func (p *PublicKey) VerifyHashable(signature []byte, net uint32, hh hash.Hashable) bool { + var digest = hash.NetSha256(net, hh) + return p.Verify(signature, digest[:]) +} + // IsInfinity checks if the key is infinite (null, basically). func (p *PublicKey) IsInfinity() bool { return p.X == nil && p.Y == nil diff --git a/pkg/crypto/verifiable.go b/pkg/crypto/verifiable.go index 10468f6f9..68670ef16 100644 --- a/pkg/crypto/verifiable.go +++ b/pkg/crypto/verifiable.go @@ -1,17 +1,11 @@ package crypto -import "github.com/nspcc-dev/neo-go/pkg/util" - -// Verifiable represents an object which can be verified. -type Verifiable interface { - GetSignedPart() []byte - GetSignedHash() util.Uint256 -} +import "github.com/nspcc-dev/neo-go/pkg/crypto/hash" // VerifiableDecodable represents an object which can be verified and // those hashable part can be encoded/decoded. type VerifiableDecodable interface { - Verifiable + hash.Hashable EncodeHashableFields() ([]byte, error) DecodeHashableFields([]byte) error } diff --git a/pkg/network/extpool/pool_test.go b/pkg/network/extpool/pool_test.go index 5757b5310..aaf554050 100644 --- a/pkg/network/extpool/pool_test.go +++ b/pkg/network/extpool/pool_test.go @@ -6,7 +6,7 @@ import ( "github.com/nspcc-dev/neo-go/pkg/core/blockchainer" "github.com/nspcc-dev/neo-go/pkg/core/transaction" - "github.com/nspcc-dev/neo-go/pkg/crypto" + "github.com/nspcc-dev/neo-go/pkg/crypto/hash" "github.com/nspcc-dev/neo-go/pkg/network/payload" "github.com/nspcc-dev/neo-go/pkg/util" "github.com/stretchr/testify/require" @@ -93,7 +93,7 @@ func newTestChain() *testChain { }, } } -func (c *testChain) VerifyWitness(u util.Uint160, _ crypto.Verifiable, _ *transaction.Witness, _ int64) error { +func (c *testChain) VerifyWitness(u util.Uint160, _ hash.Hashable, _ *transaction.Witness, _ int64) error { if !c.verifyWitness(u) { return errVerification } diff --git a/pkg/network/helper_test.go b/pkg/network/helper_test.go index 5787655df..0be730bb1 100644 --- a/pkg/network/helper_test.go +++ b/pkg/network/helper_test.go @@ -9,7 +9,6 @@ import ( "time" "github.com/nspcc-dev/neo-go/internal/fakechain" - "github.com/nspcc-dev/neo-go/pkg/config/netmode" "github.com/nspcc-dev/neo-go/pkg/io" "github.com/nspcc-dev/neo-go/pkg/network/capability" "github.com/nspcc-dev/neo-go/pkg/network/payload" @@ -122,7 +121,7 @@ func (p *localPeer) EnqueueP2PPacket(m []byte) error { return p.EnqueueHPPacket(true, m) } func (p *localPeer) EnqueueHPPacket(_ bool, m []byte) error { - msg := &Message{Network: netmode.UnitTestNet} + msg := &Message{} r := io.NewBinReaderFromBuf(m) err := msg.Decode(r) if err == nil { diff --git a/pkg/network/message.go b/pkg/network/message.go index 9c64cc802..1a8025cb0 100644 --- a/pkg/network/message.go +++ b/pkg/network/message.go @@ -4,7 +4,6 @@ import ( "errors" "fmt" - "github.com/nspcc-dev/neo-go/pkg/config/netmode" "github.com/nspcc-dev/neo-go/pkg/core/block" "github.com/nspcc-dev/neo-go/pkg/core/transaction" "github.com/nspcc-dev/neo-go/pkg/io" @@ -30,9 +29,6 @@ type Message struct { // Compressed message payload. compressedPayload []byte - // Network this message comes from, it has to be set upon Message - // creation for correct decoding. - Network netmode.Magic // StateRootInHeader specifies if state root is included in block header. // This is needed for correct decoding. StateRootInHeader bool @@ -87,8 +83,7 @@ const ( CMDAlert CommandType = 0x40 ) -// NewMessage returns a new message with the given payload. It's intended to be -// used for messages to be sent, thus it doesn't care much about the Network. +// NewMessage returns a new message with the given payload. func NewMessage(cmd CommandType, p payload.Payload) *Message { return &Message{ Command: cmd, @@ -145,11 +140,11 @@ func (m *Message) decodePayload() error { case CMDAddr: p = &payload.AddressList{} case CMDBlock: - p = block.New(m.Network, m.StateRootInHeader) + p = block.New(m.StateRootInHeader) case CMDExtensible: - p = payload.NewExtensible(m.Network) + p = payload.NewExtensible() case CMDP2PNotaryRequest: - p = &payload.P2PNotaryRequest{Network: m.Network} + p = &payload.P2PNotaryRequest{} case CMDGetBlocks: p = &payload.GetBlocks{} case CMDGetHeaders: @@ -157,11 +152,11 @@ func (m *Message) decodePayload() error { case CMDGetBlockByIndex: p = &payload.GetBlockByIndex{} case CMDHeaders: - p = &payload.Headers{Network: m.Network, StateRootInHeader: m.StateRootInHeader} + p = &payload.Headers{StateRootInHeader: m.StateRootInHeader} case CMDTX: - p = &transaction.Transaction{Network: m.Network} + p = &transaction.Transaction{} case CMDMerkleBlock: - p = &payload.MerkleBlock{Network: m.Network} + p = &payload.MerkleBlock{} case CMDPing, CMDPong: p = &payload.Ping{} case CMDNotFound: diff --git a/pkg/network/message_test.go b/pkg/network/message_test.go index 64b538115..879d4a9f7 100644 --- a/pkg/network/message_test.go +++ b/pkg/network/message_test.go @@ -130,10 +130,9 @@ func TestEncodeDecodeBlock(t *testing.T) { }) t.Run("invalid state root enabled setting", func(t *testing.T) { expected := NewMessage(CMDBlock, newDummyBlock(31, 1)) - expected.Network = netmode.UnitTestNet data, err := testserdes.Encode(expected) require.NoError(t, err) - require.Error(t, testserdes.Decode(data, &Message{Network: netmode.UnitTestNet, StateRootInHeader: true})) + require.Error(t, testserdes.Decode(data, &Message{StateRootInHeader: true})) }) } @@ -204,12 +203,10 @@ func TestEncodeDecodeMerkleBlock(t *testing.T) { InvocationScript: random.Bytes(10), VerificationScript: random.Bytes(11), }, - Network: netmode.UnitTestNet, } base.Hash() t.Run("good", func(t *testing.T) { testEncodeDecode(t, CMDMerkleBlock, &payload.MerkleBlock{ - Network: netmode.UnitTestNet, Header: base, TxCount: 1, Hashes: []util.Uint256{random.Uint256()}, @@ -243,7 +240,7 @@ func TestInvalidMessages(t *testing.T) { require.NoError(t, err) require.True(t, m.Flags&Compressed == 0) data[0] |= byte(Compressed) - require.Error(t, testserdes.Decode(data, &Message{Network: netmode.UnitTestNet})) + require.Error(t, testserdes.Decode(data, &Message{})) }) t.Run("invalid command", func(t *testing.T) { testEncodeDecodeFail(t, CommandType(0xFF), &payload.Version{Magic: netmode.UnitTestNet}) @@ -255,7 +252,7 @@ func TestInvalidMessages(t *testing.T) { w.WriteB(byte(m.Command)) w.WriteVarBytes(make([]byte, payload.MaxSize+1)) require.NoError(t, w.Err) - require.Error(t, testserdes.Decode(w.Bytes(), &Message{Network: netmode.UnitTestNet})) + require.Error(t, testserdes.Decode(w.Bytes(), &Message{})) }) t.Run("fail to encode message if payload can't be serialized", func(t *testing.T) { m := NewMessage(CMDBlock, failSer(true)) @@ -272,7 +269,7 @@ func TestInvalidMessages(t *testing.T) { data, err := testserdes.Encode(m) require.NoError(t, err) data = data[:len(data)-1] - require.Error(t, testserdes.Decode(data, &Message{Network: netmode.UnitTestNet})) + require.Error(t, testserdes.Decode(data, &Message{})) }) } @@ -287,7 +284,7 @@ func (f failSer) EncodeBinary(r *io.BinWriter) { func (failSer) DecodeBinary(w *io.BinReader) {} func newDummyBlock(height uint32, txCount int) *block.Block { - b := block.New(netmode.UnitTestNet, false) + b := block.New(false) b.Index = height b.PrevHash = random.Uint256() b.Timestamp = rand.Uint64() @@ -302,7 +299,7 @@ func newDummyBlock(height uint32, txCount int) *block.Block { } func newDummyTx() *transaction.Transaction { - tx := transaction.New(netmode.UnitTestNet, random.Bytes(100), 123) + tx := transaction.New(random.Bytes(100), 123) tx.Signers = []transaction.Signer{{Account: random.Uint160()}} tx.Scripts = []transaction.Witness{{InvocationScript: []byte{}, VerificationScript: []byte{}}} tx.Size() @@ -312,19 +309,17 @@ func newDummyTx() *transaction.Transaction { func testEncodeDecode(t *testing.T, cmd CommandType, p payload.Payload) *Message { expected := NewMessage(cmd, p) - expected.Network = netmode.UnitTestNet - actual := &Message{Network: netmode.UnitTestNet} + actual := &Message{} testserdes.EncodeDecode(t, expected, actual) return actual } func testEncodeDecodeFail(t *testing.T, cmd CommandType, p payload.Payload) *Message { expected := NewMessage(cmd, p) - expected.Network = netmode.UnitTestNet data, err := testserdes.Encode(expected) require.NoError(t, err) - actual := &Message{Network: netmode.UnitTestNet} + actual := &Message{} require.Error(t, testserdes.Decode(data, actual)) return actual } diff --git a/pkg/network/payload/extensible.go b/pkg/network/payload/extensible.go index ab09f2cb5..529a8dc37 100644 --- a/pkg/network/payload/extensible.go +++ b/pkg/network/payload/extensible.go @@ -4,7 +4,6 @@ import ( "errors" "math" - "github.com/nspcc-dev/neo-go/pkg/config/netmode" "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" @@ -18,8 +17,6 @@ const ( // Extensible represents payload containing arbitrary data. type Extensible struct { - // Network represents network magic. - Network netmode.Magic // Category is payload type. Category string // ValidBlockStart is starting height for payload to be valid. @@ -33,16 +30,14 @@ type Extensible struct { // Witness is payload witness. Witness transaction.Witness - hash util.Uint256 - signedHash util.Uint256 - signedpart []byte + hash util.Uint256 } var errInvalidPadding = errors.New("invalid padding") // NewExtensible creates new extensible payload. -func NewExtensible(network netmode.Magic) *Extensible { - return &Extensible{Network: network} +func NewExtensible() *Extensible { + return &Extensible{} } func (e *Extensible) encodeBinaryUnsigned(w *io.BinWriter) { @@ -81,22 +76,6 @@ func (e *Extensible) DecodeBinary(r *io.BinReader) { e.Witness.DecodeBinary(r) } -// GetSignedPart implements crypto.Verifiable. -func (e *Extensible) GetSignedPart() []byte { - if e.signedpart == nil { - e.createHash() - } - return e.signedpart -} - -// GetSignedHash implements crypto.Verifiable. -func (e *Extensible) GetSignedHash() util.Uint256 { - if e.signedHash.Equals(util.Uint256{}) { - e.createHash() - } - return e.signedHash -} - // Hash returns payload hash. func (e *Extensible) Hash() util.Uint256 { if e.hash.Equals(util.Uint256{}) { @@ -110,14 +89,4 @@ func (e *Extensible) createHash() { buf := io.NewBufBinWriter() e.encodeBinaryUnsigned(buf.BinWriter) e.hash = hash.Sha256(buf.Bytes()) - e.updateSignedPart() - e.signedHash = hash.Sha256(e.signedpart) -} - -// updateSignedPart updates serialized message if needed. -func (e *Extensible) updateSignedPart() { - buf := io.NewBufBinWriter() - buf.WriteU32LE(uint32(e.Network)) - buf.WriteBytes(e.hash[:]) - e.signedpart = buf.Bytes() } diff --git a/pkg/network/payload/extensible_test.go b/pkg/network/payload/extensible_test.go index 88ae45189..f1f6b28c8 100644 --- a/pkg/network/payload/extensible_test.go +++ b/pkg/network/payload/extensible_test.go @@ -7,7 +7,6 @@ import ( "github.com/nspcc-dev/neo-go/internal/random" "github.com/nspcc-dev/neo-go/internal/testserdes" - "github.com/nspcc-dev/neo-go/pkg/config/netmode" "github.com/nspcc-dev/neo-go/pkg/core/transaction" "github.com/nspcc-dev/neo-go/pkg/io" "github.com/stretchr/testify/require" @@ -54,23 +53,13 @@ func TestExtensible_Serializable(t *testing.T) { func TestExtensible_Hashes(t *testing.T) { getExtensiblePair := func() (*Extensible, *Extensible) { - p1 := NewExtensible(netmode.UnitTestNet) + p1 := NewExtensible() p1.Data = []byte{1, 2, 3} - p2 := NewExtensible(netmode.UnitTestNet) + p2 := NewExtensible() p2.Data = []byte{3, 2, 1} return p1, p2 } - t.Run("GetSignedPart", func(t *testing.T) { - p1, p2 := getExtensiblePair() - require.NotEqual(t, p1.GetSignedPart(), p2.GetSignedPart()) - require.NotEqual(t, p1.GetSignedPart(), p2.GetSignedPart()) - }) - t.Run("GetSignedHash", func(t *testing.T) { - p1, p2 := getExtensiblePair() - require.NotEqual(t, p1.GetSignedHash(), p2.GetSignedHash()) - require.NotEqual(t, p1.GetSignedHash(), p2.GetSignedHash()) - }) t.Run("Hash", func(t *testing.T) { p1, p2 := getExtensiblePair() require.NotEqual(t, p1.Hash(), p2.Hash()) diff --git a/pkg/network/payload/headers.go b/pkg/network/payload/headers.go index 7c8c53d30..b9b21c415 100644 --- a/pkg/network/payload/headers.go +++ b/pkg/network/payload/headers.go @@ -4,15 +4,13 @@ import ( "errors" "fmt" - "github.com/nspcc-dev/neo-go/pkg/config/netmode" "github.com/nspcc-dev/neo-go/pkg/core/block" "github.com/nspcc-dev/neo-go/pkg/io" ) // Headers payload. type Headers struct { - Hdrs []*block.Header - Network netmode.Magic + Hdrs []*block.Header // StateRootInHeader specifies whether header contains state root. StateRootInHeader bool } @@ -48,7 +46,6 @@ func (p *Headers) DecodeBinary(br *io.BinReader) { for i := 0; i < int(lenHeaders); i++ { header := &block.Header{} - header.Network = p.Network header.StateRootEnabled = p.StateRootInHeader header.DecodeBinary(br) p.Hdrs[i] = header diff --git a/pkg/network/payload/merkleblock.go b/pkg/network/payload/merkleblock.go index ac578523d..888b34e92 100644 --- a/pkg/network/payload/merkleblock.go +++ b/pkg/network/payload/merkleblock.go @@ -3,7 +3,6 @@ package payload import ( "errors" - "github.com/nspcc-dev/neo-go/pkg/config/netmode" "github.com/nspcc-dev/neo-go/pkg/core/block" "github.com/nspcc-dev/neo-go/pkg/io" "github.com/nspcc-dev/neo-go/pkg/util" @@ -12,7 +11,6 @@ import ( // MerkleBlock represents a merkle block packet payload. type MerkleBlock struct { *block.Header - Network netmode.Magic TxCount int Hashes []util.Uint256 Flags []byte @@ -20,7 +18,7 @@ type MerkleBlock struct { // DecodeBinary implements Serializable interface. func (m *MerkleBlock) DecodeBinary(br *io.BinReader) { - m.Header = &block.Header{Network: m.Network} + m.Header = &block.Header{} m.Header.DecodeBinary(br) txCount := int(br.ReadVarUint()) diff --git a/pkg/network/payload/notary_request.go b/pkg/network/payload/notary_request.go index 8dcd5e1ad..e78178901 100644 --- a/pkg/network/payload/notary_request.go +++ b/pkg/network/payload/notary_request.go @@ -4,7 +4,6 @@ import ( "bytes" "errors" - "github.com/nspcc-dev/neo-go/pkg/config/netmode" "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" @@ -16,17 +15,15 @@ import ( type P2PNotaryRequest struct { MainTransaction *transaction.Transaction FallbackTransaction *transaction.Transaction - Network netmode.Magic Witness transaction.Witness - hash util.Uint256 - signedHash util.Uint256 + hash util.Uint256 } // NewP2PNotaryRequestFromBytes decodes P2PNotaryRequest from the given bytes. -func NewP2PNotaryRequestFromBytes(network netmode.Magic, b []byte) (*P2PNotaryRequest, error) { - req := &P2PNotaryRequest{Network: network} +func NewP2PNotaryRequestFromBytes(b []byte) (*P2PNotaryRequest, error) { + req := &P2PNotaryRequest{} br := io.NewBinReaderFromBuf(b) req.DecodeBinary(br) if br.Err != nil { @@ -59,43 +56,18 @@ func (r *P2PNotaryRequest) Hash() util.Uint256 { return r.hash } -// GetSignedHash returns a hash of the payload used to verify it. -func (r *P2PNotaryRequest) GetSignedHash() util.Uint256 { - if r.signedHash.Equals(util.Uint256{}) { - if r.createHash() != nil { - panic("failed to compute hash!") - } - } - return r.signedHash -} - -// GetSignedPart returns a part of the payload which must be signed. -func (r *P2PNotaryRequest) GetSignedPart() []byte { - if r.hash.Equals(util.Uint256{}) { - if r.createHash() != nil { - panic("failed to compute hash!") - } - } - buf := io.NewBufBinWriter() - buf.WriteU32LE(uint32(r.Network)) - buf.WriteBytes(r.hash[:]) - return buf.Bytes() -} - // createHash creates hash of the payload. func (r *P2PNotaryRequest) createHash() error { buf := io.NewBufBinWriter() r.encodeHashableFields(buf.BinWriter) r.hash = hash.Sha256(buf.Bytes()) - signed := r.GetSignedPart() - r.signedHash = hash.Sha256(signed) return nil } // DecodeBinaryUnsigned reads payload from w excluding signature. func (r *P2PNotaryRequest) decodeHashableFields(br *io.BinReader) { - r.MainTransaction = &transaction.Transaction{Network: r.Network} - r.FallbackTransaction = &transaction.Transaction{Network: r.Network} + r.MainTransaction = &transaction.Transaction{} + r.FallbackTransaction = &transaction.Transaction{} r.MainTransaction.DecodeBinary(br) r.FallbackTransaction.DecodeBinary(br) if br.Err == nil { diff --git a/pkg/network/payload/notary_request_test.go b/pkg/network/payload/notary_request_test.go index 7f82175cb..e148ab9ba 100644 --- a/pkg/network/payload/notary_request_test.go +++ b/pkg/network/payload/notary_request_test.go @@ -4,7 +4,6 @@ import ( "testing" "github.com/nspcc-dev/neo-go/internal/random" - "github.com/nspcc-dev/neo-go/pkg/config/netmode" "github.com/nspcc-dev/neo-go/pkg/core/transaction" "github.com/nspcc-dev/neo-go/pkg/util" "github.com/nspcc-dev/neo-go/pkg/vm/opcode" @@ -144,7 +143,6 @@ func TestNotaryRequestIsValid(t *testing.T) { func TestNotaryRequestBytesFromBytes(t *testing.T) { mainTx := &transaction.Transaction{ - Network: netmode.UnitTestNet, Attributes: []transaction.Attribute{{Type: transaction.NotaryAssistedT, Value: &transaction.NotaryAssisted{NKeys: 1}}}, Script: []byte{0, 1, 2}, ValidUntilBlock: 123, @@ -157,7 +155,6 @@ func TestNotaryRequestBytesFromBytes(t *testing.T) { _ = mainTx.Hash() _ = mainTx.Size() fallbackTx := &transaction.Transaction{ - Network: netmode.UnitTestNet, Script: []byte{3, 2, 1}, ValidUntilBlock: 123, Attributes: []transaction.Attribute{ @@ -173,7 +170,6 @@ func TestNotaryRequestBytesFromBytes(t *testing.T) { _ = fallbackTx.Hash() _ = fallbackTx.Size() p := &P2PNotaryRequest{ - Network: netmode.UnitTestNet, MainTransaction: mainTx, FallbackTransaction: fallbackTx, Witness: transaction.Witness{ @@ -185,7 +181,7 @@ func TestNotaryRequestBytesFromBytes(t *testing.T) { _ = p.Hash() // initialize hash caches bytes, err := p.Bytes() require.NoError(t, err) - actual, err := NewP2PNotaryRequestFromBytes(netmode.UnitTestNet, bytes) + actual, err := NewP2PNotaryRequestFromBytes(bytes) require.NoError(t, err) require.Equal(t, p, actual) } diff --git a/pkg/network/server.go b/pkg/network/server.go index af5287cd1..f53c4c97c 100644 --- a/pkg/network/server.go +++ b/pkg/network/server.go @@ -152,7 +152,7 @@ func newServerFromConstructors(config ServerConfig, chain blockchainer.Blockchai Chain: chain, Log: log, } - n, err := notary.NewNotary(cfg, s.notaryRequestPool, func(tx *transaction.Transaction) error { + n, err := notary.NewNotary(cfg, s.network, s.notaryRequestPool, func(tx *transaction.Transaction) error { if err := s.RelayTxn(tx); err != nil { return fmt.Errorf("can't relay completed notary transaction: hash %s, error: %w", tx.Hash().StringLE(), err) } diff --git a/pkg/network/server_test.go b/pkg/network/server_test.go index 9284b5134..3f3e589ff 100644 --- a/pkg/network/server_test.go +++ b/pkg/network/server_test.go @@ -12,7 +12,6 @@ import ( "github.com/nspcc-dev/neo-go/internal/fakechain" "github.com/nspcc-dev/neo-go/internal/random" "github.com/nspcc-dev/neo-go/pkg/config" - "github.com/nspcc-dev/neo-go/pkg/config/netmode" "github.com/nspcc-dev/neo-go/pkg/consensus" "github.com/nspcc-dev/neo-go/pkg/core" "github.com/nspcc-dev/neo-go/pkg/core/block" @@ -372,7 +371,6 @@ func (s *Server) testHandleMessage(t *testing.T, p Peer, cmd CommandType, pl pay p.(*localPeer).handshaked = true } msg := NewMessage(cmd, pl) - msg.Network = netmode.UnitTestNet require.NoError(t, s.handleMessage(p, msg)) return s } @@ -393,7 +391,7 @@ func TestBlock(t *testing.T) { atomic2.StoreUint32(&s.chain.(*fakechain.FakeChain).Blockheight, 12344) require.Equal(t, uint32(12344), s.chain.BlockHeight()) - b := block.New(netmode.UnitTestNet, false) + b := block.New(false) b.Index = 12345 s.testHandleMessage(t, nil, CMDBlock, b) require.Eventually(t, func() bool { return s.chain.BlockHeight() == 12345 }, time.Second, time.Millisecond*500) @@ -407,7 +405,7 @@ func TestConsensus(t *testing.T) { p.handshaked = true newConsensusMessage := func(start, end uint32) *Message { - pl := payload.NewExtensible(netmode.UnitTestNet) + pl := payload.NewExtensible() pl.Category = consensus.Category pl.ValidBlockStart = start pl.ValidBlockEnd = end @@ -438,7 +436,7 @@ func TestConsensus(t *testing.T) { require.Error(t, s.handleMessage(p, msg)) }) t.Run("invalid category", func(t *testing.T) { - pl := payload.NewExtensible(netmode.UnitTestNet) + pl := payload.NewExtensible() pl.Category = "invalid" pl.ValidBlockEnd = s.chain.BlockHeight() + 1 msg := NewMessage(CMDExtensible, pl) @@ -518,7 +516,6 @@ func TestGetData(t *testing.T) { }) t.Run("p2pNotaryRequest", func(t *testing.T) { mainTx := &transaction.Transaction{ - Network: netmode.UnitTestNet, Attributes: []transaction.Attribute{{Type: transaction.NotaryAssistedT, Value: &transaction.NotaryAssisted{NKeys: 1}}}, Script: []byte{0, 1, 2}, ValidUntilBlock: 123, @@ -528,7 +525,6 @@ func TestGetData(t *testing.T) { mainTx.Size() mainTx.Hash() fallbackTx := &transaction.Transaction{ - Network: netmode.UnitTestNet, Script: []byte{1, 2, 3}, ValidUntilBlock: 123, Attributes: []transaction.Attribute{ @@ -544,7 +540,6 @@ func TestGetData(t *testing.T) { r := &payload.P2PNotaryRequest{ MainTransaction: mainTx, FallbackTransaction: fallbackTx, - Network: netmode.UnitTestNet, Witness: transaction.Witness{ InvocationScript: []byte{1, 2, 3}, VerificationScript: []byte{1, 2, 3}, @@ -596,7 +591,6 @@ func TestGetBlocks(t *testing.T) { }) t.Run("invalid start", func(t *testing.T) { msg := NewMessage(CMDGetBlocks, &payload.GetBlocks{HashStart: util.Uint256{}, Count: -1}) - msg.Network = netmode.UnitTestNet require.Error(t, s.handleMessage(p, msg)) }) } @@ -708,7 +702,7 @@ func TestInv(t *testing.T) { require.Equal(t, []util.Uint256{hs[0], hs[2]}, actual) }) t.Run("extensible", func(t *testing.T) { - ep := payload.NewExtensible(netmode.UnitTestNet) + ep := payload.NewExtensible() s.chain.(*fakechain.FakeChain).VerifyWitnessF = func() error { return nil } ep.ValidBlockEnd = s.chain.(*fakechain.FakeChain).BlockHeight() + 1 ok, err := s.extensiblePool.Add(ep) @@ -720,14 +714,13 @@ func TestInv(t *testing.T) { }) }) t.Run("p2pNotaryRequest", func(t *testing.T) { - fallbackTx := transaction.New(netmode.UnitTestNet, random.Bytes(100), 123) + fallbackTx := transaction.New(random.Bytes(100), 123) fallbackTx.Signers = []transaction.Signer{{Account: random.Uint160()}, {Account: random.Uint160()}} fallbackTx.Size() fallbackTx.Hash() r := &payload.P2PNotaryRequest{ MainTransaction: newDummyTx(), FallbackTransaction: fallbackTx, - Network: netmode.UnitTestNet, } require.NoError(t, s.notaryRequestPool.Add(r.FallbackTransaction, s.chain, r)) hs := []util.Uint256{random.Uint256(), r.FallbackTransaction.Hash(), random.Uint256()} @@ -828,7 +821,6 @@ func TestAddrs(t *testing.T) { t.Run("CMDAddr not requested", func(t *testing.T) { msg := NewMessage(CMDAddr, pl) - msg.Network = netmode.UnitTestNet require.Error(t, s.handleMessage(p, msg)) }) } diff --git a/pkg/network/tcp_peer.go b/pkg/network/tcp_peer.go index f8c29d61d..d0ba1c576 100644 --- a/pkg/network/tcp_peer.go +++ b/pkg/network/tcp_peer.go @@ -165,7 +165,7 @@ func (p *TCPPeer) handleConn() { if err == nil { r := io.NewBinReaderFromIO(p.conn) for { - msg := &Message{Network: p.server.network, StateRootInHeader: p.server.stateRootInHeader} + msg := &Message{StateRootInHeader: p.server.stateRootInHeader} err = msg.Decode(r) if err == payload.ErrTooManyHeaders { diff --git a/pkg/rpc/client/nep17.go b/pkg/rpc/client/nep17.go index 62a61b1fe..f9ce80a7f 100644 --- a/pkg/rpc/client/nep17.go +++ b/pkg/rpc/client/nep17.go @@ -179,7 +179,7 @@ func (c *Client) CreateTxFromScript(script []byte, acc *wallet.Account, sysFee, if !c.initDone { return nil, errNetworkNotInitialized } - tx := transaction.New(c.GetNetwork(), script, sysFee) + tx := transaction.New(script, sysFee) tx.Signers = signers tx.ValidUntilBlock, err = c.CalculateValidUntilBlock() @@ -205,7 +205,7 @@ func (c *Client) TransferNEP17(acc *wallet.Account, to util.Uint160, token util. return util.Uint256{}, err } - if err := acc.SignTx(tx); err != nil { + if err := acc.SignTx(c.GetNetwork(), tx); err != nil { return util.Uint256{}, fmt.Errorf("can't sign tx: %w", err) } @@ -219,7 +219,7 @@ func (c *Client) MultiTransferNEP17(acc *wallet.Account, gas int64, recipients [ return util.Uint256{}, err } - if err := acc.SignTx(tx); err != nil { + if err := acc.SignTx(c.GetNetwork(), tx); err != nil { return util.Uint256{}, fmt.Errorf("can't sign tx: %w", err) } diff --git a/pkg/rpc/client/rpc.go b/pkg/rpc/client/rpc.go index dcec9177c..9465badb3 100644 --- a/pkg/rpc/client/rpc.go +++ b/pkg/rpc/client/rpc.go @@ -86,7 +86,7 @@ func (c *Client) getBlock(params request.RawParams) (*block.Block, error) { return nil, err } r := io.NewBinReaderFromBuf(resp) - b = block.New(c.GetNetwork(), c.StateRootInHeader()) + b = block.New(c.StateRootInHeader()) b.DecodeBinary(r) if r.Err != nil { return nil, r.Err @@ -115,7 +115,6 @@ func (c *Client) getBlockVerbose(params request.RawParams) (*result.Block, error if !c.initDone { return nil, errNetworkNotInitialized } - resp.Network = c.GetNetwork() if err = c.performRequest("getblock", params, resp); err != nil { return nil, err } @@ -151,7 +150,6 @@ func (c *Client) GetBlockHeader(hash util.Uint256) (*block.Header, error) { } r := io.NewBinReaderFromBuf(resp) h = new(block.Header) - h.Network = c.GetNetwork() h.DecodeBinary(r) if r.Err != nil { return nil, r.Err @@ -336,7 +334,7 @@ func (c *Client) GetRawTransaction(hash util.Uint256) (*transaction.Transaction, if err = c.performRequest("getrawtransaction", params, &resp); err != nil { return nil, err } - tx, err := transaction.NewTransactionFromBytes(c.GetNetwork(), resp) + tx, err := transaction.NewTransactionFromBytes(resp) if err != nil { return nil, err } @@ -356,7 +354,6 @@ func (c *Client) GetRawTransactionVerbose(hash util.Uint256) (*result.Transactio if !c.initDone { return nil, errNetworkNotInitialized } - resp.Network = c.GetNetwork() if err = c.performRequest("getrawtransaction", params, resp); err != nil { return nil, err } @@ -529,7 +526,7 @@ func (c *Client) SignAndPushInvocationTx(script []byte, acc *wallet.Account, sys if err != nil { return txHash, fmt.Errorf("failed to create tx: %w", err) } - if err = acc.SignTx(tx); err != nil { + if err = acc.SignTx(c.GetNetwork(), tx); err != nil { return txHash, fmt.Errorf("failed to sign tx: %w", err) } txHash = tx.Hash() @@ -621,7 +618,7 @@ func (c *Client) SignAndPushP2PNotaryRequest(mainTx *transaction.Transaction, fa if int64(fallbackValidFor) > maxNVBDelta { return nil, fmt.Errorf("fallback transaction should be valid for not more than %d blocks", maxNVBDelta) } - fallbackTx := transaction.New(c.GetNetwork(), fallbackScript, fallbackSysFee) + fallbackTx := transaction.New(fallbackScript, fallbackSysFee) fallbackTx.Signers = signers fallbackTx.ValidUntilBlock = mainTx.ValidUntilBlock fallbackTx.Attributes = []transaction.Attribute{ @@ -655,17 +652,16 @@ func (c *Client) SignAndPushP2PNotaryRequest(mainTx *transaction.Transaction, fa VerificationScript: []byte{}, }, } - if err = acc.SignTx(fallbackTx); err != nil { + if err = acc.SignTx(c.GetNetwork(), fallbackTx); err != nil { return nil, fmt.Errorf("failed to sign fallback tx: %w", err) } fallbackHash := fallbackTx.Hash() req := &payload.P2PNotaryRequest{ MainTransaction: mainTx, FallbackTransaction: fallbackTx, - Network: c.GetNetwork(), } req.Witness = transaction.Witness{ - InvocationScript: append([]byte{byte(opcode.PUSHDATA1), 64}, acc.PrivateKey().Sign(req.GetSignedPart())...), + InvocationScript: append([]byte{byte(opcode.PUSHDATA1), 64}, acc.PrivateKey().SignHashable(uint32(c.GetNetwork()), req)...), VerificationScript: acc.GetVerificationScript(), } actualHash, err := c.SubmitP2PNotaryRequest(req) diff --git a/pkg/rpc/client/rpc_test.go b/pkg/rpc/client/rpc_test.go index 7f48ea0b6..9268674a2 100644 --- a/pkg/rpc/client/rpc_test.go +++ b/pkg/rpc/client/rpc_test.go @@ -66,7 +66,7 @@ func getResultBlock1() *result.Block { if err != nil { panic(err) } - b := block.New(netmode.UnitTestNet, false) + b := block.New(false) err = testserdes.DecodeBinary(binB, b) if err != nil { panic(err) @@ -91,7 +91,7 @@ func getTxMoveNeo() *result.TransactionOutputRaw { if err != nil { panic(err) } - tx, err := transaction.NewTransactionFromBytes(netmode.UnitTestNet, txBin) + tx, err := transaction.NewTransactionFromBytes(txBin) if err != nil { panic(err) } @@ -939,7 +939,7 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{ { name: "positive", invoke: func(c *Client) (interface{}, error) { - return c.SendRawTransaction(transaction.New(netmode.UnitTestNet, []byte{byte(opcode.PUSH1)}, 0)) + return c.SendRawTransaction(transaction.New([]byte{byte(opcode.PUSH1)}, 0)) }, serverResponse: `{"jsonrpc":"2.0","id":1,"result":{"hash":"0x72159b0cf1221110daad6e1df6ef4ff03012173b63c86910bd7134deb659c875"}}`, result: func(c *Client) interface{} { @@ -1076,7 +1076,7 @@ var rpcClientErrorCases = map[string][]rpcClientErrorCase{ { name: "sendrawtransaction_bad_server_answer", invoke: func(c *Client) (interface{}, error) { - return c.SendRawTransaction(transaction.New(netmode.UnitTestNet, []byte{byte(opcode.PUSH1)}, 0)) + return c.SendRawTransaction(transaction.New([]byte{byte(opcode.PUSH1)}, 0)) }, }, { @@ -1437,7 +1437,7 @@ var rpcClientErrorCases = map[string][]rpcClientErrorCase{ { name: "sendrawtransaction_unmarshalling_error", invoke: func(c *Client) (interface{}, error) { - return c.SendRawTransaction(transaction.New(netmode.UnitTestNet, []byte{byte(opcode.PUSH1)}, 0)) + return c.SendRawTransaction(transaction.New([]byte{byte(opcode.PUSH1)}, 0)) }, }, { diff --git a/pkg/rpc/client/wsclient.go b/pkg/rpc/client/wsclient.go index 7f79b6711..7ff486246 100644 --- a/pkg/rpc/client/wsclient.go +++ b/pkg/rpc/client/wsclient.go @@ -139,9 +139,9 @@ readloop: var val interface{} switch event { case response.BlockEventID: - val = block.New(c.GetNetwork(), c.StateRootInHeader()) + val = block.New(c.StateRootInHeader()) case response.TransactionEventID: - val = &transaction.Transaction{Network: c.GetNetwork()} + val = &transaction.Transaction{} case response.NotificationEventID: val = new(state.NotificationEvent) case response.ExecutionEventID: diff --git a/pkg/rpc/response/result/invoke.go b/pkg/rpc/response/result/invoke.go index 76be179df..7b29cc239 100644 --- a/pkg/rpc/response/result/invoke.go +++ b/pkg/rpc/response/result/invoke.go @@ -2,25 +2,20 @@ package result import ( "encoding/json" - "errors" - "github.com/nspcc-dev/neo-go/pkg/config/netmode" "github.com/nspcc-dev/neo-go/pkg/core/transaction" "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" ) // Invoke represents code invocation result and is used by several RPC calls -// that invoke functions, scripts and generic bytecode. Transaction is -// represented in raw serialized format, use transaction.NewTransactionFromBytes -// or GetTransaction method to deserialize it. +// that invoke functions, scripts and generic bytecode. type Invoke struct { State string GasConsumed int64 Script []byte Stack []stackitem.Item FaultException string - // Transaction represents transaction bytes. Use GetTransaction method to decode it. - Transaction []byte + Transaction *transaction.Transaction } type invokeAux struct { @@ -52,25 +47,29 @@ func (r Invoke) MarshalJSON() ([]byte, error) { return nil, err } } - + var txbytes []byte + if r.Transaction != nil { + txbytes = r.Transaction.Bytes() + } return json.Marshal(&invokeAux{ GasConsumed: r.GasConsumed, Script: r.Script, State: r.State, Stack: st, FaultException: r.FaultException, - Transaction: r.Transaction, + Transaction: txbytes, }) } // UnmarshalJSON implements json.Unmarshaler. func (r *Invoke) UnmarshalJSON(data []byte) error { + var err error aux := new(invokeAux) - if err := json.Unmarshal(data, aux); err != nil { + if err = json.Unmarshal(data, aux); err != nil { return err } var arr []json.RawMessage - if err := json.Unmarshal(aux.Stack, &arr); err == nil { + if err = json.Unmarshal(aux.Stack, &arr); err == nil { st := make([]stackitem.Item, len(arr)) for i := range arr { st[i], err = stackitem.FromJSONWithTypes(arr[i]) @@ -82,18 +81,17 @@ func (r *Invoke) UnmarshalJSON(data []byte) error { r.Stack = st } } + var tx *transaction.Transaction + if len(aux.Transaction) != 0 { + tx, err = transaction.NewTransactionFromBytes(aux.Transaction) + if err != nil { + return err + } + } r.GasConsumed = aux.GasConsumed r.Script = aux.Script r.State = aux.State r.FaultException = aux.FaultException - r.Transaction = aux.Transaction + r.Transaction = tx return nil } - -// GetTransaction returns decoded transaction from Invoke.Transaction bytes. -func (r *Invoke) GetTransaction(magic netmode.Magic) (*transaction.Transaction, error) { - if r.Transaction == nil { - return nil, errors.New("empty transaction") - } - return transaction.NewTransactionFromBytes(magic, r.Transaction) -} diff --git a/pkg/rpc/response/result/invoke_test.go b/pkg/rpc/response/result/invoke_test.go index 247abd944..769b26620 100644 --- a/pkg/rpc/response/result/invoke_test.go +++ b/pkg/rpc/response/result/invoke_test.go @@ -6,19 +6,26 @@ import ( "math/big" "testing" + "github.com/nspcc-dev/neo-go/pkg/core/transaction" + "github.com/nspcc-dev/neo-go/pkg/util" "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" "github.com/stretchr/testify/require" ) func TestInvoke_MarshalJSON(t *testing.T) { + tx := transaction.New([]byte{1, 2, 3, 4}, 0) + tx.Signers = []transaction.Signer{{Account: util.Uint160{1, 2, 3}}} + tx.Scripts = []transaction.Witness{transaction.Witness{InvocationScript: []byte{}, VerificationScript: []byte{}}} + _ = tx.Size() + tx.Hash() + result := &Invoke{ State: "HALT", GasConsumed: 237626000, Script: []byte{10}, Stack: []stackitem.Item{stackitem.NewBigInteger(big.NewInt(1))}, FaultException: "", - // Transaction represents transaction bytes. Use GetTransaction method to decode it. - Transaction: []byte{1, 2, 3, 4}, + Transaction: tx, } data, err := json.Marshal(result) @@ -30,7 +37,7 @@ func TestInvoke_MarshalJSON(t *testing.T) { "stack":[ {"type":"Integer","value":"1"} ], - "tx":"` + base64.StdEncoding.EncodeToString(result.Transaction) + `" + "tx":"` + base64.StdEncoding.EncodeToString(tx.Bytes()) + `" }` require.JSONEq(t, expected, string(data)) diff --git a/pkg/rpc/server/client_test.go b/pkg/rpc/server/client_test.go index c7c459a9e..41305f332 100644 --- a/pkg/rpc/server/client_test.go +++ b/pkg/rpc/server/client_test.go @@ -6,7 +6,6 @@ import ( "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/fee" "github.com/nspcc-dev/neo-go/pkg/core/native/nativenames" "github.com/nspcc-dev/neo-go/pkg/core/transaction" @@ -90,7 +89,7 @@ func TestAddNetworkFee(t *testing.T) { feePerByte := chain.FeePerByte() t.Run("Invalid", func(t *testing.T) { - tx := transaction.New(testchain.Network(), []byte{byte(opcode.PUSH1)}, 0) + tx := transaction.New([]byte{byte(opcode.PUSH1)}, 0) accs := getAccounts(t, 2) tx.Signers = []transaction.Signer{{ Account: accs[0].PrivateKey().GetScriptHash(), @@ -99,20 +98,20 @@ func TestAddNetworkFee(t *testing.T) { require.Error(t, c.AddNetworkFee(tx, extraFee, accs[0], accs[1])) }) t.Run("Simple", func(t *testing.T) { - tx := transaction.New(testchain.Network(), []byte{byte(opcode.PUSH1)}, 0) + tx := transaction.New([]byte{byte(opcode.PUSH1)}, 0) accs := getAccounts(t, 1) tx.Signers = []transaction.Signer{{ Account: accs[0].PrivateKey().GetScriptHash(), Scopes: transaction.CalledByEntry, }} require.NoError(t, c.AddNetworkFee(tx, 10, accs[0])) - require.NoError(t, accs[0].SignTx(tx)) + require.NoError(t, accs[0].SignTx(testchain.Network(), tx)) cFee, _ := fee.Calculate(chain.GetBaseExecFee(), accs[0].Contract.Script) require.Equal(t, int64(io.GetVarSize(tx))*feePerByte+cFee+extraFee, tx.NetworkFee) }) t.Run("Multi", func(t *testing.T) { - tx := transaction.New(testchain.Network(), []byte{byte(opcode.PUSH1)}, 0) + tx := transaction.New([]byte{byte(opcode.PUSH1)}, 0) accs := getAccounts(t, 4) pubs := keys.PublicKeys{accs[1].PrivateKey().PublicKey(), accs[2].PrivateKey().PublicKey(), accs[3].PrivateKey().PublicKey()} require.NoError(t, accs[1].ConvertMultisig(2, pubs)) @@ -128,9 +127,9 @@ func TestAddNetworkFee(t *testing.T) { }, } require.NoError(t, c.AddNetworkFee(tx, extraFee, accs[0], accs[1])) - require.NoError(t, accs[0].SignTx(tx)) - require.NoError(t, accs[1].SignTx(tx)) - require.NoError(t, accs[2].SignTx(tx)) + require.NoError(t, accs[0].SignTx(testchain.Network(), tx)) + require.NoError(t, accs[1].SignTx(testchain.Network(), tx)) + require.NoError(t, accs[2].SignTx(testchain.Network(), tx)) cFee, _ := fee.Calculate(chain.GetBaseExecFee(), accs[0].Contract.Script) cFeeM, _ := fee.Calculate(chain.GetBaseExecFee(), accs[1].Contract.Script) require.Equal(t, int64(io.GetVarSize(tx))*feePerByte+cFee+cFeeM+extraFee, tx.NetworkFee) @@ -145,7 +144,7 @@ func TestAddNetworkFee(t *testing.T) { acc1.Contract.Script, err = base64.StdEncoding.DecodeString(verifyContractAVM) newTx := func(t *testing.T) *transaction.Transaction { - tx := transaction.New(testchain.Network(), []byte{byte(opcode.PUSH1)}, 0) + tx := transaction.New([]byte{byte(opcode.PUSH1)}, 0) require.NoError(t, err) tx.ValidUntilBlock = chain.BlockHeight() + 10 return tx @@ -170,21 +169,21 @@ func TestAddNetworkFee(t *testing.T) { // check that network fee with extra value is enough tx1 := completeTx(t) - require.NoError(t, acc0.SignTx(tx1)) + require.NoError(t, acc0.SignTx(testchain.Network(), tx1)) tx1.Scripts = append(tx1.Scripts, transaction.Witness{}) require.NoError(t, chain.VerifyTx(tx1)) // check that network fee without extra value is enough tx2 := completeTx(t) tx2.NetworkFee -= extraFee - require.NoError(t, acc0.SignTx(tx2)) + require.NoError(t, acc0.SignTx(testchain.Network(), tx2)) tx2.Scripts = append(tx2.Scripts, transaction.Witness{}) require.NoError(t, chain.VerifyTx(tx2)) // check that we don't add unexpected extra GAS tx3 := completeTx(t) tx3.NetworkFee -= extraFee + 1 - require.NoError(t, acc0.SignTx(tx3)) + require.NoError(t, acc0.SignTx(testchain.Network(), tx3)) tx3.Scripts = append(tx3.Scripts, transaction.Witness{}) require.Error(t, chain.VerifyTx(tx3)) }) @@ -286,7 +285,6 @@ func TestSignAndPushP2PNotaryRequest(t *testing.T) { sender := testchain.PrivateKeyByID(0) // owner of the deposit in testchain acc := wallet.NewAccountFromPrivateKey(sender) expected := transaction.Transaction{ - Network: netmode.UnitTestNet, Attributes: []transaction.Attribute{{Type: transaction.NotaryAssistedT, Value: &transaction.NotaryAssisted{NKeys: 1}}}, Script: []byte{byte(opcode.RET)}, ValidUntilBlock: chain.BlockHeight() + 5, @@ -328,7 +326,7 @@ func TestSignAndPushP2PNotaryRequest(t *testing.T) { ntr := w.Accounts[0] ntr.Decrypt(notaryPass) req.FallbackTransaction.Scripts[0] = transaction.Witness{ - InvocationScript: append([]byte{byte(opcode.PUSHDATA1), 64}, ntr.PrivateKey().Sign(req.FallbackTransaction.GetSignedPart())...), + InvocationScript: append([]byte{byte(opcode.PUSHDATA1), 64}, ntr.PrivateKey().SignHashable(uint32(testchain.Network()), req.FallbackTransaction)...), VerificationScript: []byte{}, } b := testchain.NewBlock(t, chain, 1, 0, req.FallbackTransaction) @@ -416,7 +414,7 @@ func TestCreateNEP17TransferTx(t *testing.T) { tx, err := c.CreateNEP17TransferTx(acc, util.Uint160{}, gasContractHash, 1000, 0, nil) require.NoError(t, err) - require.NoError(t, acc.SignTx(tx)) + require.NoError(t, acc.SignTx(testchain.Network(), tx)) require.NoError(t, chain.VerifyTx(tx)) v := chain.GetTestVM(trigger.Application, tx, nil) v.LoadScriptWithFlags(tx.Script, callflag.All) diff --git a/pkg/rpc/server/server.go b/pkg/rpc/server/server.go index fc299e9ef..f097df5c1 100644 --- a/pkg/rpc/server/server.go +++ b/pkg/rpc/server/server.go @@ -1194,7 +1194,7 @@ func (s *Server) runScriptInVM(t trigger.Type, script []byte, contractScriptHash // When transferring funds, script execution does no auto GAS claim, // because it depends on persisting tx height. // This is why we provide block here. - b := block.New(s.network, s.stateRootEnabled) + b := block.New(s.stateRootEnabled) b.Index = s.chain.BlockHeight() + 1 hdr, err := s.chain.GetHeader(s.chain.GetHeaderHash(int(s.chain.BlockHeight()))) if err != nil { @@ -1246,7 +1246,7 @@ func (s *Server) submitBlock(reqParams request.Params) (interface{}, *response.E if err != nil { return nil, response.ErrInvalidParams } - b := block.New(s.network, s.stateRootEnabled) + b := block.New(s.stateRootEnabled) r := io.NewBinReaderFromBuf(blockBytes) b.DecodeBinary(r) if r.Err != nil { @@ -1279,7 +1279,7 @@ func (s *Server) submitNotaryRequest(ps request.Params) (interface{}, *response. if err != nil { return nil, response.ErrInvalidParams } - r, err := payload.NewP2PNotaryRequestFromBytes(s.network, bytePayload) + r, err := payload.NewP2PNotaryRequestFromBytes(bytePayload) if err != nil { return nil, response.ErrInvalidParams } @@ -1344,7 +1344,7 @@ func (s *Server) sendrawtransaction(reqParams request.Params) (interface{}, *res if err != nil { return nil, response.ErrInvalidParams } - tx, err := transaction.NewTransactionFromBytes(s.network, byteTx) + tx, err := transaction.NewTransactionFromBytes(byteTx) if err != nil { return nil, response.ErrInvalidParams } diff --git a/pkg/rpc/server/server_helper_test.go b/pkg/rpc/server/server_helper_test.go index eb81f31ce..24c18da73 100644 --- a/pkg/rpc/server/server_helper_test.go +++ b/pkg/rpc/server/server_helper_test.go @@ -89,7 +89,7 @@ func getTestBlocks(t *testing.T) []*block.Block { blocks := make([]*block.Block, 0, int(nBlocks)) for i := 0; i < int(nBlocks); i++ { _ = br.ReadU32LE() - b := block.New(netmode.UnitTestNet, false) + b := block.New(false) b.DecodeBinary(br) require.Nil(t, br.Err) blocks = append(blocks, b) diff --git a/pkg/rpc/server/server_test.go b/pkg/rpc/server/server_test.go index aa222cb32..c29c4cdd3 100644 --- a/pkg/rpc/server/server_test.go +++ b/pkg/rpc/server/server_test.go @@ -19,7 +19,6 @@ import ( "github.com/gorilla/websocket" "github.com/nspcc-dev/neo-go/internal/testchain" "github.com/nspcc-dev/neo-go/internal/testserdes" - "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/fee" @@ -1076,7 +1075,6 @@ func TestSubmitNotaryRequest(t *testing.T) { t.Run("invalid request bytes", runCase(t, true, `"not-a-request"`)) t.Run("invalid request", func(t *testing.T) { mainTx := &transaction.Transaction{ - Network: netmode.UnitTestNet, Attributes: []transaction.Attribute{{Type: transaction.NotaryAssistedT, Value: &transaction.NotaryAssisted{NKeys: 1}}}, Script: []byte{byte(opcode.RET)}, ValidUntilBlock: 123, @@ -1087,7 +1085,6 @@ func TestSubmitNotaryRequest(t *testing.T) { }}, } fallbackTx := &transaction.Transaction{ - Network: netmode.UnitTestNet, Script: []byte{byte(opcode.RET)}, ValidUntilBlock: 123, Attributes: []transaction.Attribute{ @@ -1101,7 +1098,6 @@ func TestSubmitNotaryRequest(t *testing.T) { {InvocationScript: []byte{1, 2, 3}, VerificationScript: []byte{1, 2, 3}}}, } p := &payload.P2PNotaryRequest{ - Network: netmode.UnitTestNet, MainTransaction: mainTx, FallbackTransaction: fallbackTx, Witness: transaction.Witness{ @@ -1117,7 +1113,6 @@ func TestSubmitNotaryRequest(t *testing.T) { t.Run("valid request", func(t *testing.T) { sender := testchain.PrivateKeyByID(0) // owner of the deposit in testchain mainTx := &transaction.Transaction{ - Network: netmode.UnitTestNet, Attributes: []transaction.Attribute{{Type: transaction.NotaryAssistedT, Value: &transaction.NotaryAssisted{NKeys: 1}}}, Script: []byte{byte(opcode.RET)}, ValidUntilBlock: 123, @@ -1128,7 +1123,6 @@ func TestSubmitNotaryRequest(t *testing.T) { }}, } fallbackTx := &transaction.Transaction{ - Network: netmode.UnitTestNet, Script: []byte{byte(opcode.RET)}, ValidUntilBlock: 123, Attributes: []transaction.Attribute{ @@ -1143,16 +1137,15 @@ func TestSubmitNotaryRequest(t *testing.T) { NetworkFee: 2_0000_0000, } fallbackTx.Scripts = append(fallbackTx.Scripts, transaction.Witness{ - InvocationScript: append([]byte{byte(opcode.PUSHDATA1), 64}, sender.Sign(fallbackTx.GetSignedPart())...), + InvocationScript: append([]byte{byte(opcode.PUSHDATA1), 64}, sender.SignHashable(uint32(testchain.Network()), fallbackTx)...), VerificationScript: sender.PublicKey().GetVerificationScript(), }) p := &payload.P2PNotaryRequest{ - Network: netmode.UnitTestNet, MainTransaction: mainTx, FallbackTransaction: fallbackTx, } p.Witness = transaction.Witness{ - InvocationScript: append([]byte{byte(opcode.PUSHDATA1), 64}, sender.Sign(p.GetSignedPart())...), + InvocationScript: append([]byte{byte(opcode.PUSHDATA1), 64}, sender.SignHashable(uint32(testchain.Network()), p)...), VerificationScript: sender.PublicKey().GetVerificationScript(), } bytes, err := p.Bytes() @@ -1314,12 +1307,12 @@ func testRPCProtocol(t *testing.T, doRPCCall func(string, string, *testing.T) [] newTx := func() *transaction.Transaction { height := chain.BlockHeight() - tx := transaction.New(testchain.Network(), []byte{byte(opcode.PUSH1)}, 0) + tx := transaction.New([]byte{byte(opcode.PUSH1)}, 0) tx.Nonce = height + 1 tx.ValidUntilBlock = height + 10 tx.Signers = []transaction.Signer{{Account: acc0.PrivateKey().GetScriptHash()}} addNetworkFee(tx) - require.NoError(t, acc0.SignTx(tx)) + require.NoError(t, acc0.SignTx(testchain.Network(), tx)) return tx } @@ -1368,7 +1361,7 @@ func testRPCProtocol(t *testing.T, doRPCCall func(string, string, *testing.T) [] body := doRPCCall(rpc, httpSrv.URL, t) rawRes := checkErrGetResult(t, body, false) - res := new(state.MPTRoot) + res := &state.MPTRoot{} require.NoError(t, json.Unmarshal(rawRes, res)) require.NotEqual(t, util.Uint256{}, res.Root) // be sure this test uses valid height @@ -1417,7 +1410,7 @@ func testRPCProtocol(t *testing.T, doRPCCall func(string, string, *testing.T) [] rpc := fmt.Sprintf(`{"jsonrpc": "2.0", "id": 1, "method": "getrawtransaction", "params": ["%s", 1]}"`, TXHash.StringLE()) body := doRPCCall(rpc, httpSrv.URL, t) txOut := checkErrGetResult(t, body, false) - actual := result.TransactionOutputRaw{Transaction: transaction.Transaction{Network: testchain.Network()}} + actual := result.TransactionOutputRaw{Transaction: transaction.Transaction{}} err := json.Unmarshal(txOut, &actual) require.NoErrorf(t, err, "could not parse response: %s", txOut) @@ -1486,7 +1479,7 @@ func testRPCProtocol(t *testing.T, doRPCCall func(string, string, *testing.T) [] expected = append(expected, tx.Hash()) } for i := 0; i < 5; i++ { - tx := transaction.New(testchain.Network(), []byte{byte(opcode.PUSH1)}, 0) + tx := transaction.New([]byte{byte(opcode.PUSH1)}, 0) tx.Signers = []transaction.Signer{{Account: util.Uint160{1, 2, 3}}} assert.NoError(t, mp.Add(tx, &FeerStub{})) expected = append(expected, tx.Hash()) @@ -1572,10 +1565,6 @@ func (tc rpcTestCase) getResultPair(e *executor) (expected interface{}, res inte expected = tc.result(e) resVal := reflect.New(reflect.TypeOf(expected).Elem()) res = resVal.Interface() - switch r := res.(type) { - case *result.Block: - r.Network = testchain.Network() - } return expected, res } diff --git a/pkg/services/notary/node_test.go b/pkg/services/notary/node_test.go index 99e20ee52..4c30f0b2c 100644 --- a/pkg/services/notary/node_test.go +++ b/pkg/services/notary/node_test.go @@ -5,6 +5,7 @@ import ( "github.com/nspcc-dev/neo-go/internal/fakechain" "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/blockchainer" "github.com/nspcc-dev/neo-go/pkg/core/mempool" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" @@ -27,7 +28,7 @@ func getTestNotary(t *testing.T, bc blockchainer.Blockchainer, walletPath, pass Chain: bc, Log: zaptest.NewLogger(t), } - ntr, err := NewNotary(cfg, mp, nil) + ntr, err := NewNotary(cfg, netmode.UnitTestNet, mp, nil) require.NoError(t, err) w, err := wallet.NewWalletFromFile(walletPath) diff --git a/pkg/services/notary/notary.go b/pkg/services/notary/notary.go index eb5b83cf3..66d2eb5eb 100644 --- a/pkg/services/notary/notary.go +++ b/pkg/services/notary/notary.go @@ -9,6 +9,7 @@ import ( "sync" "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/block" "github.com/nspcc-dev/neo-go/pkg/core/blockchainer" "github.com/nspcc-dev/neo-go/pkg/core/mempool" @@ -29,6 +30,8 @@ type ( Notary struct { Config Config + Network netmode.Magic + // onTransaction is a callback for completed transactions (mains or fallbacks) sending. onTransaction func(tx *transaction.Transaction) error @@ -81,7 +84,7 @@ type request struct { } // NewNotary returns new Notary module. -func NewNotary(cfg Config, mp *mempool.Pool, onTransaction func(tx *transaction.Transaction) error) (*Notary, error) { +func NewNotary(cfg Config, net netmode.Magic, mp *mempool.Pool, onTransaction func(tx *transaction.Transaction) error) (*Notary, error) { w := cfg.MainCfg.UnlockWallet wallet, err := wallet.NewWalletFromFile(w.Path) if err != nil { @@ -102,6 +105,7 @@ func NewNotary(cfg Config, mp *mempool.Pool, onTransaction func(tx *transaction. return &Notary{ requests: make(map[util.Uint256]*request), Config: cfg, + Network: net, wallet: wallet, onTransaction: onTransaction, mp: mp, @@ -203,7 +207,7 @@ func (n *Notary) OnNewRequest(payload *payload.P2PNotaryRequest) { r.sigs = make(map[*keys.PublicKey][]byte) } - hash := r.main.GetSignedHash().BytesBE() + hash := hash.NetSha256(uint32(n.Network), r.main).BytesBE() for _, pub := range pubs { if r.sigs[pub] != nil { continue // signature for this pub has already been added @@ -308,7 +312,7 @@ func (n *Notary) finalize(tx *transaction.Transaction) error { panic(errors.New("no available Notary account")) // unreachable code, because all callers of `finalize` check that acc != nil } notaryWitness := transaction.Witness{ - InvocationScript: append([]byte{byte(opcode.PUSHDATA1), 64}, acc.PrivateKey().Sign(tx.GetSignedPart())...), + InvocationScript: append([]byte{byte(opcode.PUSHDATA1), 64}, acc.PrivateKey().SignHashable(uint32(n.Network), tx)...), VerificationScript: []byte{}, } for i, signer := range tx.Signers { @@ -332,7 +336,7 @@ func updateTxSize(tx *transaction.Transaction) (*transaction.Transaction, error) if bw.Err != nil { return nil, fmt.Errorf("encode binary: %w", bw.Err) } - return transaction.NewTransactionFromBytes(tx.Network, tx.Bytes()) + return transaction.NewTransactionFromBytes(tx.Bytes()) } // verifyIncompleteWitnesses checks that tx either doesn't have all witnesses attached (in this case none of them diff --git a/pkg/services/notary/notary_test.go b/pkg/services/notary/notary_test.go index 15e14dce6..2d5f1b9fe 100644 --- a/pkg/services/notary/notary_test.go +++ b/pkg/services/notary/notary_test.go @@ -5,6 +5,7 @@ import ( "github.com/nspcc-dev/neo-go/internal/fakechain" "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/mempool" "github.com/nspcc-dev/neo-go/pkg/core/transaction" "github.com/nspcc-dev/neo-go/pkg/crypto/hash" @@ -27,21 +28,21 @@ func TestWallet(t *testing.T) { } t.Run("unexisting wallet", func(t *testing.T) { cfg.MainCfg.UnlockWallet.Path = "./testdata/does_not_exists.json" - _, err := NewNotary(cfg, mempool.New(1, 1, true), nil) + _, err := NewNotary(cfg, netmode.UnitTestNet, mempool.New(1, 1, true), nil) require.Error(t, err) }) t.Run("bad password", func(t *testing.T) { cfg.MainCfg.UnlockWallet.Path = "./testdata/notary1.json" cfg.MainCfg.UnlockWallet.Password = "invalid" - _, err := NewNotary(cfg, mempool.New(1, 1, true), nil) + _, err := NewNotary(cfg, netmode.UnitTestNet, mempool.New(1, 1, true), nil) require.Error(t, err) }) t.Run("good", func(t *testing.T) { cfg.MainCfg.UnlockWallet.Path = "./testdata/notary1.json" cfg.MainCfg.UnlockWallet.Password = "one" - _, err := NewNotary(cfg, mempool.New(1, 1, true), nil) + _, err := NewNotary(cfg, netmode.UnitTestNet, mempool.New(1, 1, true), nil) require.NoError(t, err) }) } diff --git a/pkg/services/oracle/request.go b/pkg/services/oracle/request.go index 11546b338..067b3a574 100644 --- a/pkg/services/oracle/request.go +++ b/pkg/services/oracle/request.go @@ -164,12 +164,12 @@ func (o *Oracle) processRequest(priv *keys.PrivateKey, req request) error { incTx.request = req.Req incTx.tx = tx incTx.backupTx = backupTx - incTx.reverifyTx() + incTx.reverifyTx(o.Network) - txSig := priv.Sign(tx.GetSignedPart()) + txSig := priv.SignHashable(uint32(o.Network), tx) incTx.addResponse(priv.PublicKey(), txSig, false) - backupSig := priv.Sign(backupTx.GetSignedPart()) + backupSig := priv.SignHashable(uint32(o.Network), backupTx) incTx.addResponse(priv.PublicKey(), backupSig, true) readyTx, ready := incTx.finalize(o.getOracleNodes(), false) diff --git a/pkg/services/oracle/response.go b/pkg/services/oracle/response.go index de9a20e38..fea159b10 100644 --- a/pkg/services/oracle/response.go +++ b/pkg/services/oracle/response.go @@ -38,9 +38,9 @@ func (o *Oracle) AddResponse(pub *keys.PublicKey, reqID uint64, txSig []byte) { incTx.Lock() isBackup := false if incTx.tx != nil { - ok := pub.Verify(txSig, incTx.tx.GetSignedHash().BytesBE()) + ok := pub.VerifyHashable(txSig, uint32(o.Network), incTx.tx) if !ok { - ok = pub.Verify(txSig, incTx.backupTx.GetSignedHash().BytesBE()) + ok = pub.VerifyHashable(txSig, uint32(o.Network), incTx.backupTx) if !ok { o.Log.Debug("invalid response signature", zap.String("pub", hex.EncodeToString(pub.Bytes()))) @@ -82,7 +82,7 @@ func readResponse(rc gio.ReadCloser, limit int) ([]byte, error) { // CreateResponseTx creates unsigned oracle response transaction. func (o *Oracle) CreateResponseTx(gasForResponse int64, height uint32, resp *transaction.OracleResponse) (*transaction.Transaction, error) { - tx := transaction.New(o.Network, o.oracleResponse, 0) + tx := transaction.New(o.oracleResponse, 0) tx.Nonce = uint32(resp.ID) tx.ValidUntilBlock = height + transaction.MaxValidUntilBlockIncrement tx.Attributes = []transaction.Attribute{{ diff --git a/pkg/services/oracle/transaction.go b/pkg/services/oracle/transaction.go index 7a803c83e..6e38b8416 100644 --- a/pkg/services/oracle/transaction.go +++ b/pkg/services/oracle/transaction.go @@ -4,8 +4,10 @@ import ( "sync" "time" + "github.com/nspcc-dev/neo-go/pkg/config/netmode" "github.com/nspcc-dev/neo-go/pkg/core/state" "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/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/io" "github.com/nspcc-dev/neo-go/pkg/smartcontract" @@ -50,9 +52,9 @@ func newIncompleteTx() *incompleteTx { } } -func (t *incompleteTx) reverifyTx() { - txHash := t.tx.GetSignedHash() - backupHash := t.backupTx.GetSignedHash() +func (t *incompleteTx) reverifyTx(net netmode.Magic) { + txHash := hash.NetSha256(uint32(net), t.tx) + backupHash := hash.NetSha256(uint32(net), t.backupTx) for pub, sig := range t.sigs { if !sig.ok { sig.ok = sig.pub.Verify(sig.sig, txHash.BytesBE()) diff --git a/pkg/services/stateroot/network.go b/pkg/services/stateroot/network.go index b5489edc5..21174c3a5 100644 --- a/pkg/services/stateroot/network.go +++ b/pkg/services/stateroot/network.go @@ -7,8 +7,10 @@ import ( "github.com/nspcc-dev/neo-go/pkg/config" "github.com/nspcc-dev/neo-go/pkg/core/state" "github.com/nspcc-dev/neo-go/pkg/core/transaction" + "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/io" "github.com/nspcc-dev/neo-go/pkg/network/payload" + "github.com/nspcc-dev/neo-go/pkg/vm/emit" "go.uber.org/zap" ) @@ -20,6 +22,10 @@ func (s *service) AddSignature(height uint32, validatorIndex int32, sig []byte) if !s.MainCfg.Enabled { return nil } + acc := s.getAccount() + if acc == nil { + return nil + } pubs := s.GetStateValidators(height) if validatorIndex < 0 || int(validatorIndex) >= len(pubs) { @@ -34,7 +40,7 @@ func (s *service) AddSignature(height uint32, validatorIndex int32, sig []byte) incRoot.Lock() if incRoot.root != nil { - ok := pub.Verify(sig, incRoot.root.GetSignedHash().BytesBE()) + ok := pub.VerifyHashable(sig, uint32(s.Network), incRoot.root) if !ok { incRoot.Unlock() return fmt.Errorf("invalid state root signature for %d", validatorIndex) @@ -49,7 +55,7 @@ func (s *service) AddSignature(height uint32, validatorIndex int32, sig []byte) if err != nil { s.log.Error("can't add validated state root", zap.Error(err)) } - s.sendValidatedRoot(sr) + s.sendValidatedRoot(sr, acc.PrivateKey()) } return nil } @@ -70,17 +76,23 @@ func (s *service) getIncompleteRoot(height uint32) *incompleteRoot { return incRoot } -func (s *service) sendValidatedRoot(r *state.MPTRoot) { +func (s *service) sendValidatedRoot(r *state.MPTRoot, priv *keys.PrivateKey) { w := io.NewBufBinWriter() m := NewMessage(RootT, r) m.EncodeBinary(w.BinWriter) ep := &payload.Extensible{ - Network: s.Network, ValidBlockStart: r.Index, ValidBlockEnd: r.Index + transaction.MaxValidUntilBlockIncrement, - Sender: s.getAccount().PrivateKey().GetScriptHash(), + Sender: priv.GetScriptHash(), Data: w.Bytes(), + Witness: transaction.Witness{ + VerificationScript: s.getAccount().GetVerificationScript(), + }, } + sig := priv.SignHashable(uint32(s.Network), ep) + buf := io.NewBufBinWriter() + emit.Bytes(buf.BinWriter, sig) + ep.Witness.InvocationScript = buf.Bytes() s.getRelayCallback()(ep) } diff --git a/pkg/services/stateroot/service.go b/pkg/services/stateroot/service.go index 0c5b17f40..d8ebc4249 100644 --- a/pkg/services/stateroot/service.go +++ b/pkg/services/stateroot/service.go @@ -61,6 +61,7 @@ const ( func New(cfg config.StateRoot, log *zap.Logger, bc blockchainer.Blockchainer) (Service, error) { s := &service{ StateRoot: bc.GetStateModule(), + Network: bc.GetConfig().Magic, chain: bc, log: log, incompleteRoots: make(map[uint32]*incompleteRoot), @@ -94,7 +95,7 @@ func New(cfg config.StateRoot, log *zap.Logger, bc blockchainer.Blockchainer) (S // OnPayload implements Service interface. func (s *service) OnPayload(ep *payload.Extensible) error { - m := new(Message) + m := &Message{} r := io.NewBinReaderFromBuf(ep.Data) m.DecodeBinary(r) if r.Err != nil { diff --git a/pkg/services/stateroot/signature.go b/pkg/services/stateroot/signature.go index b579f91fe..3ebbcbeb2 100644 --- a/pkg/services/stateroot/signature.go +++ b/pkg/services/stateroot/signature.go @@ -3,6 +3,7 @@ package stateroot import ( "sync" + "github.com/nspcc-dev/neo-go/pkg/config/netmode" "github.com/nspcc-dev/neo-go/pkg/core/state" "github.com/nspcc-dev/neo-go/pkg/core/transaction" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" @@ -38,11 +39,10 @@ func newIncompleteRoot() *incompleteRoot { } } -func (r *incompleteRoot) reverify() { - txHash := r.root.GetSignedHash() +func (r *incompleteRoot) reverify(net netmode.Magic) { for _, sig := range r.sigs { if !sig.ok { - sig.ok = sig.pub.Verify(sig.sig, txHash.BytesBE()) + sig.ok = sig.pub.VerifyHashable(sig.sig, uint32(net), r.root) } } } @@ -77,12 +77,17 @@ func (r *incompleteRoot) finalize(stateValidators keys.PublicKeys) (*state.MPTRo return nil, false } + verif, err := smartcontract.CreateDefaultMultiSigRedeemScript(stateValidators) + if err != nil { + return nil, false + } w := io.NewBufBinWriter() for i := range sigs { emit.Bytes(w.BinWriter, sigs[i]) } - r.root.Witness = &transaction.Witness{ - InvocationScript: w.Bytes(), - } + r.root.Witness = []transaction.Witness{{ + InvocationScript: w.Bytes(), + VerificationScript: verif, + }} return r.root, true } diff --git a/pkg/services/stateroot/validators.go b/pkg/services/stateroot/validators.go index b3a98378e..fbd9a88d2 100644 --- a/pkg/services/stateroot/validators.go +++ b/pkg/services/stateroot/validators.go @@ -5,6 +5,7 @@ import ( "github.com/nspcc-dev/neo-go/pkg/core/transaction" "github.com/nspcc-dev/neo-go/pkg/io" "github.com/nspcc-dev/neo-go/pkg/network/payload" + "github.com/nspcc-dev/neo-go/pkg/vm/emit" "github.com/nspcc-dev/neo-go/pkg/wallet" "go.uber.org/zap" ) @@ -46,11 +47,11 @@ func (s *service) signAndSend(r *state.MPTRoot) error { return nil } - sig := acc.PrivateKey().SignHash(r.GetSignedHash()) + sig := acc.PrivateKey().SignHashable(uint32(s.Network), r) incRoot := s.getIncompleteRoot(r.Index) incRoot.root = r incRoot.addSignature(acc.PrivateKey().PublicKey(), sig) - incRoot.reverify() + incRoot.reverify(s.Network) s.accMtx.RLock() myIndex := s.myIndex @@ -66,13 +67,20 @@ func (s *service) signAndSend(r *state.MPTRoot) error { if w.Err != nil { return w.Err } - s.getRelayCallback()(&payload.Extensible{ - Network: s.Network, + e := &payload.Extensible{ ValidBlockStart: r.Index, ValidBlockEnd: r.Index + transaction.MaxValidUntilBlockIncrement, Sender: s.getAccount().PrivateKey().GetScriptHash(), Data: w.Bytes(), - }) + Witness: transaction.Witness{ + VerificationScript: s.getAccount().GetVerificationScript(), + }, + } + sig = acc.PrivateKey().SignHashable(uint32(s.Network), e) + buf := io.NewBufBinWriter() + emit.Bytes(buf.BinWriter, sig) + e.Witness.InvocationScript = buf.Bytes() + s.getRelayCallback()(e) return nil } diff --git a/pkg/smartcontract/context/context.go b/pkg/smartcontract/context/context.go index ddb810012..e5c3cafc5 100644 --- a/pkg/smartcontract/context/context.go +++ b/pkg/smartcontract/context/context.go @@ -190,7 +190,6 @@ func (c *ParameterContext) UnmarshalJSON(data []byte) error { switch pc.Type { case "Neo.Core.ContractTransaction": tx := new(transaction.Transaction) - tx.Network = netmode.Magic(pc.Net) verif = tx default: return fmt.Errorf("unsupported type: %s", c.Type) diff --git a/pkg/smartcontract/context/context_test.go b/pkg/smartcontract/context/context_test.go index e7876afd6..a2db41f53 100644 --- a/pkg/smartcontract/context/context_test.go +++ b/pkg/smartcontract/context/context_test.go @@ -24,7 +24,7 @@ func TestParameterContext_AddSignatureSimpleContract(t *testing.T) { priv, err := keys.NewPrivateKey() require.NoError(t, err) pub := priv.PublicKey() - sig := priv.Sign(tx.GetSignedPart()) + sig := priv.SignHashable(uint32(netmode.UnitTestNet), tx) t.Run("invalid contract", func(t *testing.T) { c := NewParameterContext("Neo.Core.ContractTransaction", netmode.UnitTestNet, tx) @@ -91,15 +91,14 @@ func TestParameterContext_AddSignatureMultisig(t *testing.T) { newParam(smartcontract.SignatureType, "parameter2"), }, } - data := tx.GetSignedPart() priv, err := keys.NewPrivateKey() require.NoError(t, err) - sig := priv.Sign(data) + sig := priv.SignHashable(uint32(c.Network), tx) require.Error(t, c.AddSignature(ctr.ScriptHash(), ctr, priv.PublicKey(), sig)) indices := []int{2, 3, 0} // random order for _, i := range indices { - sig := privs[i].Sign(data) + sig := privs[i].SignHashable(uint32(c.Network), tx) require.NoError(t, c.AddSignature(ctr.ScriptHash(), ctr, pubs[i], sig)) require.Error(t, c.AddSignature(ctr.ScriptHash(), ctr, pubs[i], sig)) @@ -119,7 +118,7 @@ func TestParameterContext_AddSignatureMultisig(t *testing.T) { } func newTestVM(w *transaction.Witness, tx *transaction.Transaction) *vm.VM { - ic := &interop.Context{Container: tx} + ic := &interop.Context{Network: uint32(netmode.UnitTestNet), Container: tx} crypto.Register(ic) v := ic.SpawnVM() v.LoadScript(w.VerificationScript) @@ -132,8 +131,7 @@ func TestParameterContext_MarshalJSON(t *testing.T) { require.NoError(t, err) tx := getContractTx() - data := tx.GetSignedPart() - sign := priv.Sign(data) + sign := priv.SignHashable(uint32(netmode.UnitTestNet), tx) expected := &ParameterContext{ Type: "Neo.Core.ContractTransaction", @@ -192,7 +190,7 @@ func newParam(typ smartcontract.ParamType, name string) wallet.ContractParam { } func getContractTx() *transaction.Transaction { - tx := transaction.New(netmode.UnitTestNet, []byte{byte(opcode.PUSH1)}, 0) + tx := transaction.New([]byte{byte(opcode.PUSH1)}, 0) tx.Attributes = make([]transaction.Attribute, 0) tx.Scripts = make([]transaction.Witness, 0) tx.Signers = []transaction.Signer{{Account: util.Uint160{1, 2, 3}}} diff --git a/pkg/wallet/account.go b/pkg/wallet/account.go index e15e3f024..66393f9ab 100644 --- a/pkg/wallet/account.go +++ b/pkg/wallet/account.go @@ -5,6 +5,7 @@ import ( "errors" "fmt" + "github.com/nspcc-dev/neo-go/pkg/config/netmode" "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/crypto/keys" @@ -94,7 +95,7 @@ func NewAccount() (*Account, error) { } // SignTx signs transaction t and updates it's Witnesses. -func (a *Account) SignTx(t *transaction.Transaction) error { +func (a *Account) SignTx(net netmode.Magic, t *transaction.Transaction) error { if a.privateKey == nil { return errors.New("account is not unlocked") } @@ -102,11 +103,7 @@ func (a *Account) SignTx(t *transaction.Transaction) error { t.Scripts = append(t.Scripts, transaction.Witness{}) return nil } - data := t.GetSignedPart() - if data == nil { - return errors.New("failed to get transaction's signed part") - } - sign := a.privateKey.Sign(data) + sign := a.privateKey.SignHashable(uint32(net), t) verif := a.GetVerificationScript() invoc := append([]byte{byte(opcode.PUSHDATA1), 64}, sign...) diff --git a/scripts/gendump/main.go b/scripts/gendump/main.go index 0c1f1df64..60a8024bc 100644 --- a/scripts/gendump/main.go +++ b/scripts/gendump/main.go @@ -79,7 +79,7 @@ func main() { handleError("can't create deploy tx", err) tx.NetworkFee = 10_000_000 tx.ValidUntilBlock = bc.BlockHeight() + 1 - handleError("can't sign deploy tx", acc.SignTx(tx)) + handleError("can't sign deploy tx", acc.SignTx(netmode.UnitTestNet, tx)) lastBlock = addBlock(bc, lastBlock, valScript, tx) key := make([]byte, 10) @@ -99,7 +99,7 @@ func main() { emit.AppCall(w.BinWriter, contractHash, "put", callflag.All, key, value) handleError("can't create transaction", w.Err) - tx := transaction.New(netmode.UnitTestNet, w.Bytes(), 4_000_000) + tx := transaction.New(w.Bytes(), 4_000_000) tx.ValidUntilBlock = i + 1 tx.NetworkFee = 4_000_000 tx.Nonce = nonce @@ -107,7 +107,7 @@ func main() { Account: h, Scopes: transaction.CalledByEntry, }} - handleError("can't sign tx", acc.SignTx(tx)) + handleError("can't sign tx", acc.SignTx(netmode.UnitTestNet, tx)) txs[j] = tx } @@ -161,7 +161,6 @@ func newBlock(bc *core.Blockchain, lastBlock *block.Block, script []byte, txs .. witness := transaction.Witness{VerificationScript: script} b := &block.Block{ Header: block.Header{ - Network: netmode.UnitTestNet, PrevHash: lastBlock.Hash(), Timestamp: uint64(time.Now().UTC().Unix())*1000 + uint64(lastBlock.Index), Index: lastBlock.Index + 1, @@ -179,6 +178,6 @@ func newBlock(bc *core.Blockchain, lastBlock *block.Block, script []byte, txs .. b.PrevStateRoot = sr.Root } b.RebuildMerkleRoot() - b.Script.InvocationScript = testchain.Sign(b.GetSignedPart()) + b.Script.InvocationScript = testchain.Sign(b) return b, nil }