diff --git a/cli/wallet/multisig.go b/cli/wallet/multisig.go index 883e3149e..639b77235 100644 --- a/cli/wallet/multisig.go +++ b/cli/wallet/multisig.go @@ -121,15 +121,4 @@ func writeParameterContext(c *context.ParameterContext, filename string) error { func printTxInfo(t *transaction.Transaction) { fmt.Printf("Hash: %s\n", t.Hash().StringLE()) - for i := range t.Inputs { - fmt.Printf("Input%02d: [%2d] %s\n", i, t.Inputs[i].PrevIndex, t.Inputs[i].PrevHash.StringLE()) - } - for i := range t.Outputs { - fmt.Printf("Output%02d:\n", i) - fmt.Printf("\tAssetID : %s\n", t.Outputs[i].AssetID.StringLE()) - fmt.Printf("\tAmount : %s\n", t.Outputs[i].Amount.String()) - h := t.Outputs[i].ScriptHash - fmt.Printf("\tScriptHash: %s\n", t.Outputs[i].ScriptHash.StringLE()) - fmt.Printf("\tToAddr : %s\n", address.Uint160ToString(h)) - } } diff --git a/pkg/compiler/syscall.go b/pkg/compiler/syscall.go index 9fa81cbbd..8d47d5a5e 100644 --- a/pkg/compiler/syscall.go +++ b/pkg/compiler/syscall.go @@ -65,13 +65,9 @@ var syscalls = map[string]map[string]string{ "GetTransaction": "Neo.Block.GetTransaction", }, "transaction": { - "GetAttributes": "Neo.Transaction.GetAttributes", - "GetHash": "Neo.Transaction.GetHash", - "GetInputs": "Neo.Transaction.GetInputs", - "GetOutputs": "Neo.Transaction.GetOutputs", - "GetReferences": "Neo.Transaction.GetReferences", - "GetUnspentCoins": "Neo.Transaction.GetUnspentCoins", - "GetWitnesses": "Neo.Transaction.GetWitnesses", + "GetAttributes": "Neo.Transaction.GetAttributes", + "GetHash": "Neo.Transaction.GetHash", + "GetWitnesses": "Neo.Transaction.GetWitnesses", }, "asset": { "Create": "Neo.Asset.Create", @@ -93,15 +89,6 @@ var syscalls = map[string]map[string]string{ "Migrate": "Neo.Contract.Migrate", "GetStorageContext": "Neo.Contract.GetStorageContext", }, - "input": { - "GetHash": "Neo.Input.GetHash", - "GetIndex": "Neo.Input.GetIndex", - }, - "output": { - "GetAssetID": "Neo.Output.GetAssetID", - "GetValue": "Neo.Output.GetValue", - "GetScriptHash": "Neo.Output.GetScriptHash", - }, "engine": { "GetScriptContainer": "System.ExecutionEngine.GetScriptContainer", "GetCallingScriptHash": "System.ExecutionEngine.GetCallingScriptHash", diff --git a/pkg/core/blockchain.go b/pkg/core/blockchain.go index 4af9caad1..aac4134be 100644 --- a/pkg/core/blockchain.go +++ b/pkg/core/blockchain.go @@ -2,7 +2,6 @@ package core import ( "fmt" - "math" "math/big" "sort" "sync" @@ -559,65 +558,6 @@ func (bc *Blockchain) storeBlock(block *block.Block) error { return err } - if err := cache.PutUnspentCoinState(tx.Hash(), state.NewUnspentCoin(block.Index, tx)); err != nil { - return err - } - - // Process TX outputs. - if err := processOutputs(tx, cache); err != nil { - return err - } - - // Process TX inputs that are grouped by previous hash. - for _, inputs := range transaction.GroupInputsByPrevHash(tx.Inputs) { - prevHash := inputs[0].PrevHash - unspent, err := cache.GetUnspentCoinState(prevHash) - if err != nil { - return err - } - for _, input := range inputs { - if len(unspent.States) <= int(input.PrevIndex) { - return fmt.Errorf("bad input: %s/%d", input.PrevHash.StringLE(), input.PrevIndex) - } - if unspent.States[input.PrevIndex].State&state.CoinSpent != 0 { - return fmt.Errorf("double spend: %s/%d", input.PrevHash.StringLE(), input.PrevIndex) - } - unspent.States[input.PrevIndex].State |= state.CoinSpent - unspent.States[input.PrevIndex].SpendHeight = block.Index - prevTXOutput := &unspent.States[input.PrevIndex].Output - account, err := cache.GetAccountStateOrNew(prevTXOutput.ScriptHash) - if err != nil { - return err - } - - balancesLen := len(account.Balances[prevTXOutput.AssetID]) - if balancesLen <= 1 { - delete(account.Balances, prevTXOutput.AssetID) - } else { - var index = -1 - for i, balance := range account.Balances[prevTXOutput.AssetID] { - if balance.Tx.Equals(input.PrevHash) && balance.Index == input.PrevIndex { - index = i - break - } - } - if index >= 0 { - last := balancesLen - 1 - if last > index { - account.Balances[prevTXOutput.AssetID][index] = account.Balances[prevTXOutput.AssetID][last] - } - account.Balances[prevTXOutput.AssetID] = account.Balances[prevTXOutput.AssetID][:last] - } - } - if err = cache.PutAccountState(account); err != nil { - return err - } - } - if err = cache.PutUnspentCoinState(prevHash, unspent); err != nil { - return err - } - } - systemInterop := bc.newInteropContext(trigger.Application, cache, block, tx) v := SpawnVM(systemInterop) v.LoadScript(tx.Script) @@ -837,25 +777,6 @@ func (bc *Blockchain) LastBatch() *storage.MemBatch { return bc.lastBatch } -// processOutputs processes transaction outputs. -func processOutputs(tx *transaction.Transaction, dao *dao.Cached) error { - for index, output := range tx.Outputs { - account, err := dao.GetAccountStateOrNew(output.ScriptHash) - if err != nil { - return err - } - account.Balances[output.AssetID] = append(account.Balances[output.AssetID], state.UnspentBalance{ - Tx: tx.Hash(), - Index: uint16(index), - Value: output.Amount, - }) - if err = dao.PutAccountState(account); err != nil { - return err - } - } - return nil -} - // persist flushes current in-memory Store contents to the persistent storage. func (bc *Blockchain) persist() error { var ( @@ -1046,15 +967,6 @@ func (bc *Blockchain) GetAccountState(scriptHash util.Uint160) *state.Account { return as } -// GetUnspentCoinState returns unspent coin state for given tx hash. -func (bc *Blockchain) GetUnspentCoinState(hash util.Uint256) *state.UnspentCoin { - ucs, err := bc.dao.GetUnspentCoinState(hash) - if ucs == nil && err != storage.ErrKeyNotFound { - bc.log.Warn("failed to get unspent coin state", zap.Error(err)) - } - return ucs -} - // GetConfig returns the config stored in the blockchain. func (bc *Blockchain) GetConfig() config.ProtocolConfiguration { return bc.config @@ -1155,36 +1067,6 @@ func (bc *Blockchain) CalculateClaimable(value int64, startHeight, endHeight uin return amount * util.Fixed8(value) } -// References maps transaction's inputs into a slice of InOuts, effectively -// joining each Input with the corresponding Output. -// @TODO: unfortunately we couldn't attach this method to the Transaction struct in the -// transaction package because of a import cycle problem. Perhaps we should think to re-design -// the code base to avoid this situation. -func (bc *Blockchain) References(t *transaction.Transaction) ([]transaction.InOut, error) { - return bc.references(t.Inputs) -} - -// references is an internal implementation of References that operates directly -// on a slice of Input. -func (bc *Blockchain) references(ins []transaction.Input) ([]transaction.InOut, error) { - references := make([]transaction.InOut, 0, len(ins)) - - for _, inputs := range transaction.GroupInputsByPrevHash(ins) { - prevHash := inputs[0].PrevHash - unspent, err := bc.dao.GetUnspentCoinState(prevHash) - if err != nil { - return nil, errors.New("bad input reference") - } - for _, in := range inputs { - if int(in.PrevIndex) > len(unspent.States)-1 { - return nil, errors.New("bad input reference") - } - references = append(references, transaction.InOut{In: *in, Out: unspent.States[in.PrevIndex].Output}) - } - } - return references, nil -} - // FeePerByte returns transaction network fee per byte. // TODO: should be implemented as part of PolicyContract func (bc *Blockchain) FeePerByte() util.Fixed8 { @@ -1253,28 +1135,11 @@ func (bc *Blockchain) verifyTx(t *transaction.Transaction, block *block.Block) e if netFee < 0 { return errors.Errorf("insufficient funds: net fee is %v, need %v", t.NetworkFee, needNetworkFee) } - if transaction.HaveDuplicateInputs(t.Inputs) { - return errors.New("invalid transaction's inputs") - } if block == nil { if ok := bc.memPool.Verify(t, bc); !ok { return errors.New("invalid transaction due to conflicts with the memory pool") } } - if bc.dao.IsDoubleSpend(t) { - return errors.New("invalid transaction caused by double spending") - } - if err := bc.verifyOutputs(t); err != nil { - return errors.Wrap(err, "wrong outputs") - } - refs, err := bc.References(t) - if err != nil { - return err - } - results := refsAndOutsToResults(refs, t.Outputs) - if err := bc.verifyResults(t, results); err != nil { - return err - } for _, a := range t.Attributes { if a.Usage == transaction.ECDH02 || a.Usage == transaction.ECDH03 { @@ -1298,9 +1163,6 @@ func (bc *Blockchain) isTxStillRelevant(t *transaction.Transaction) bool { if bc.dao.HasTransaction(t.Hash()) { return false } - if bc.dao.IsDoubleSpend(t) { - return false - } for i := range t.Scripts { if !vm.IsStandardContract(t.Scripts[i].VerificationScript) { recheckWitness = true @@ -1357,88 +1219,6 @@ func (bc *Blockchain) PoolTx(t *transaction.Transaction) error { return nil } -func (bc *Blockchain) verifyOutputs(t *transaction.Transaction) error { - for assetID, outputs := range t.GroupOutputByAssetID() { - assetState := bc.GetAssetState(assetID) - if assetState == nil { - return fmt.Errorf("no asset state for %s", assetID.StringLE()) - } - - if assetState.Expiration < bc.blockHeight+1 && assetState.AssetType != transaction.GoverningToken && assetState.AssetType != transaction.UtilityToken { - return fmt.Errorf("asset %s expired", assetID.StringLE()) - } - - for _, out := range outputs { - if int64(out.Amount)%int64(math.Pow10(8-int(assetState.Precision))) != 0 { - return fmt.Errorf("output is not compliant with %s asset precision", assetID.StringLE()) - } - } - } - - return nil -} - -func (bc *Blockchain) verifyResults(t *transaction.Transaction, results []*transaction.Result) error { - var resultsDestroy []*transaction.Result - var resultsIssue []*transaction.Result - for _, re := range results { - if re.Amount.GreaterThan(util.Fixed8(0)) { - resultsDestroy = append(resultsDestroy, re) - } - - if re.Amount.LessThan(util.Fixed8(0)) { - resultsIssue = append(resultsIssue, re) - } - } - if len(resultsDestroy) > 1 { - return errors.New("tx has more than 1 destroy output") - } - - if len(resultsIssue) > 0 { - return errors.New("non issue/miner/claim tx issues tokens") - } - - return nil -} - -// GetTransactionResults returns the transaction results aggregate by assetID. -// Golang of GetTransationResults method in C# (https://github.com/neo-project/neo/blob/master/neo/Network/P2P/Payloads/Transaction.cs#L207) -func (bc *Blockchain) GetTransactionResults(t *transaction.Transaction) []*transaction.Result { - references, err := bc.References(t) - if err != nil { - return nil - } - return refsAndOutsToResults(references, t.Outputs) -} - -// mapReferencesToResults returns cumulative results of transaction based in its -// references and outputs. -func refsAndOutsToResults(references []transaction.InOut, outputs []transaction.Output) []*transaction.Result { - var results []*transaction.Result - tempResult := make(map[util.Uint256]util.Fixed8) - - for _, inout := range references { - c := tempResult[inout.Out.AssetID] - tempResult[inout.Out.AssetID] = c.Add(inout.Out.Amount) - } - for _, output := range outputs { - c := tempResult[output.AssetID] - tempResult[output.AssetID] = c.Sub(output.Amount) - } - - results = []*transaction.Result{} // this assignment is necessary. (Most of the time amount == 0 and results is the empty slice.) - for assetID, amount := range tempResult { - if amount != util.Fixed8(0) { - results = append(results, &transaction.Result{ - AssetID: assetID, - Amount: amount, - }) - } - } - - return results -} - //GetStandByValidators returns validators from the configuration. func (bc *Blockchain) GetStandByValidators() (keys.PublicKeys, error) { return getValidators(bc.config) @@ -1458,29 +1238,7 @@ func (bc *Blockchain) GetEnrollments() ([]state.Validator, error) { // to verify whether the transaction is bonafide or not. // Golang implementation of GetScriptHashesForVerifying method in C# (https://github.com/neo-project/neo/blob/master/neo/Network/P2P/Payloads/Transaction.cs#L190) func (bc *Blockchain) GetScriptHashesForVerifying(t *transaction.Transaction) ([]util.Uint160, error) { - references, err := bc.References(t) - if err != nil { - return nil, err - } hashes := make(map[util.Uint160]bool) - for i := range references { - hashes[references[i].Out.ScriptHash] = true - } - - for a, outputs := range t.GroupOutputByAssetID() { - as := bc.GetAssetState(a) - if as == nil { - return nil, errors.New("Invalid operation") - } - if as.AssetType&transaction.DutyFlag != 0 { - for _, o := range outputs { - h := o.ScriptHash - if _, ok := hashes[h]; !ok { - hashes[h] = true - } - } - } - } hashes[t.Sender] = true for _, c := range t.Cosigners { hashes[c.Account] = true @@ -1567,7 +1325,6 @@ func (bc *Blockchain) verifyHashAgainstScript(hash util.Uint160, witness *transa // is used for easy interop access and can be omitted for transactions that are // not yet added into any block. // Golang implementation of VerifyWitnesses method in C# (https://github.com/neo-project/neo/blob/master/neo/SmartContract/Helper.cs#L87). -// Unfortunately the IVerifiable interface could not be implemented because we can't move the References method in blockchain.go to the transaction.go file. func (bc *Blockchain) verifyTxWitnesses(t *transaction.Transaction, block *block.Block) error { hashes, err := bc.GetScriptHashesForVerifying(t) if err != nil { diff --git a/pkg/core/blockchainer/blockchainer.go b/pkg/core/blockchainer/blockchainer.go index 4d197ed05..ed04267f4 100644 --- a/pkg/core/blockchainer/blockchainer.go +++ b/pkg/core/blockchainer/blockchainer.go @@ -44,8 +44,6 @@ type Blockchainer interface { GetStorageItems(hash util.Uint160) (map[string]*state.StorageItem, error) GetTestVM() *vm.VM GetTransaction(util.Uint256) (*transaction.Transaction, uint32, error) - GetUnspentCoinState(util.Uint256) *state.UnspentCoin - References(t *transaction.Transaction) ([]transaction.InOut, error) mempool.Feer // fee interface PoolTx(*transaction.Transaction) error SubscribeForBlocks(ch chan<- *block.Block) diff --git a/pkg/core/dao/cacheddao.go b/pkg/core/dao/cacheddao.go index 50d3b9514..9fc792308 100644 --- a/pkg/core/dao/cacheddao.go +++ b/pkg/core/dao/cacheddao.go @@ -15,7 +15,6 @@ type Cached struct { DAO accounts map[util.Uint160]*state.Account contracts map[util.Uint160]*state.Contract - unspents map[util.Uint256]*state.UnspentCoin balances map[util.Uint160]*state.NEP5Balances transfers map[util.Uint160]map[uint32]*state.NEP5TransferLog } @@ -24,10 +23,9 @@ type Cached struct { func NewCached(d DAO) *Cached { accs := make(map[util.Uint160]*state.Account) ctrs := make(map[util.Uint160]*state.Contract) - unspents := make(map[util.Uint256]*state.UnspentCoin) balances := make(map[util.Uint160]*state.NEP5Balances) transfers := make(map[util.Uint160]map[uint32]*state.NEP5TransferLog) - return &Cached{d.GetWrapped(), accs, ctrs, unspents, balances, transfers} + return &Cached{d.GetWrapped(), accs, ctrs, balances, transfers} } // GetAccountStateOrNew retrieves Account from cache or underlying store @@ -77,20 +75,6 @@ func (cd *Cached) DeleteContractState(hash util.Uint160) error { return cd.DAO.DeleteContractState(hash) } -// GetUnspentCoinState retrieves UnspentCoin from cache or underlying store. -func (cd *Cached) GetUnspentCoinState(hash util.Uint256) (*state.UnspentCoin, error) { - if cd.unspents[hash] != nil { - return cd.unspents[hash], nil - } - return cd.DAO.GetUnspentCoinState(hash) -} - -// PutUnspentCoinState saves given UnspentCoin in the cache. -func (cd *Cached) PutUnspentCoinState(hash util.Uint256, ucs *state.UnspentCoin) error { - cd.unspents[hash] = ucs - return nil -} - // GetNEP5Balances retrieves NEP5Balances for the acc. func (cd *Cached) GetNEP5Balances(acc util.Uint160) (*state.NEP5Balances, error) { if bs := cd.balances[acc]; bs != nil { @@ -167,13 +151,6 @@ func (cd *Cached) Persist() (int, error) { } buf.Reset() } - for hash := range cd.unspents { - err := cd.DAO.putUnspentCoinState(hash, cd.unspents[hash], buf) - if err != nil { - return 0, err - } - buf.Reset() - } for acc, bs := range cd.balances { err := cd.DAO.putNEP5Balances(acc, bs, buf) if err != nil { @@ -197,7 +174,6 @@ func (cd *Cached) GetWrapped() DAO { return &Cached{cd.DAO.GetWrapped(), cd.accounts, cd.contracts, - cd.unspents, cd.balances, cd.transfers, } diff --git a/pkg/core/dao/dao.go b/pkg/core/dao/dao.go index 363aa9244..49886f59f 100644 --- a/pkg/core/dao/dao.go +++ b/pkg/core/dao/dao.go @@ -36,11 +36,9 @@ type DAO interface { GetStorageItems(hash util.Uint160) (map[string]*state.StorageItem, error) GetStorageItemsWithPrefix(hash util.Uint160, prefix []byte) (map[string]*state.StorageItem, error) GetTransaction(hash util.Uint256) (*transaction.Transaction, uint32, error) - GetUnspentCoinState(hash util.Uint256) (*state.UnspentCoin, error) GetVersion() (string, error) GetWrapped() DAO HasTransaction(hash util.Uint256) bool - IsDoubleSpend(tx *transaction.Transaction) bool Persist() (int, error) PutAccountState(as *state.Account) error PutAppExecResult(aer *state.AppExecResult) error @@ -50,14 +48,12 @@ type DAO interface { PutNEP5Balances(acc util.Uint160, bs *state.NEP5Balances) error PutNEP5TransferLog(acc util.Uint160, index uint32, lg *state.NEP5TransferLog) error PutStorageItem(scripthash util.Uint160, key []byte, si *state.StorageItem) error - PutUnspentCoinState(hash util.Uint256, ucs *state.UnspentCoin) error PutVersion(v string) error StoreAsBlock(block *block.Block) error StoreAsCurrentBlock(block *block.Block) error StoreAsTransaction(tx *transaction.Transaction, index uint32) error putAccountState(as *state.Account, buf *io.BufBinWriter) error putNEP5Balances(acc util.Uint160, bs *state.NEP5Balances, buf *io.BufBinWriter) error - putUnspentCoinState(hash util.Uint256, ucs *state.UnspentCoin, buf *io.BufBinWriter) error } // Simple is memCached wrapper around DB, simple DAO implementation. @@ -275,31 +271,6 @@ func (dao *Simple) AppendNEP5Transfer(acc util.Uint160, index uint32, tr *state. // -- end transfer log. -// -- start unspent coins. - -// GetUnspentCoinState retrieves UnspentCoinState from the given store. -func (dao *Simple) GetUnspentCoinState(hash util.Uint256) (*state.UnspentCoin, error) { - unspent := &state.UnspentCoin{} - key := storage.AppendPrefix(storage.STCoin, hash.BytesLE()) - err := dao.GetAndDecode(unspent, key) - if err != nil { - return nil, err - } - return unspent, nil -} - -// PutUnspentCoinState puts given UnspentCoinState into the given store. -func (dao *Simple) PutUnspentCoinState(hash util.Uint256, ucs *state.UnspentCoin) error { - return dao.putUnspentCoinState(hash, ucs, io.NewBufBinWriter()) -} - -func (dao *Simple) putUnspentCoinState(hash util.Uint256, ucs *state.UnspentCoin, buf *io.BufBinWriter) error { - key := storage.AppendPrefix(storage.STCoin, hash.BytesLE()) - return dao.putWithBuffer(ucs, key, buf) -} - -// -- end unspent coins. - // -- start notification event. // GetAppExecResult gets application execution result from the @@ -567,30 +538,6 @@ func (dao *Simple) StoreAsTransaction(tx *transaction.Transaction, index uint32) return dao.Store.Put(key, buf.Bytes()) } -// IsDoubleSpend verifies that the input transactions are not double spent. -func (dao *Simple) IsDoubleSpend(tx *transaction.Transaction) bool { - return dao.checkUsedInputs(tx.Inputs, state.CoinSpent) -} - -func (dao *Simple) checkUsedInputs(inputs []transaction.Input, coin state.Coin) bool { - if len(inputs) == 0 { - return false - } - for _, inputs := range transaction.GroupInputsByPrevHash(inputs) { - prevHash := inputs[0].PrevHash - unspent, err := dao.GetUnspentCoinState(prevHash) - if err != nil { - return true - } - for _, input := range inputs { - if int(input.PrevIndex) >= len(unspent.States) || (unspent.States[input.PrevIndex].State&coin) != 0 { - return true - } - } - } - return false -} - // Persist flushes all the changes made into the (supposedly) persistent // underlying store. func (dao *Simple) Persist() (int, error) { diff --git a/pkg/core/dao/dao_test.go b/pkg/core/dao/dao_test.go index 77c62bc0f..13b8bef89 100644 --- a/pkg/core/dao/dao_test.go +++ b/pkg/core/dao/dao_test.go @@ -94,25 +94,6 @@ func TestDeleteContractState(t *testing.T) { require.Nil(t, gotContractState) } -func TestGetUnspentCoinState_Err(t *testing.T) { - dao := NewSimple(storage.NewMemoryStore()) - hash := random.Uint256() - gotUnspentCoinState, err := dao.GetUnspentCoinState(hash) - require.Error(t, err) - require.Nil(t, gotUnspentCoinState) -} - -func TestPutGetUnspentCoinState(t *testing.T) { - dao := NewSimple(storage.NewMemoryStore()) - hash := random.Uint256() - unspentCoinState := &state.UnspentCoin{Height: 42, States: []state.OutputState{}} - err := dao.PutUnspentCoinState(hash, unspentCoinState) - require.NoError(t, err) - gotUnspentCoinState, err := dao.GetUnspentCoinState(hash) - require.NoError(t, err) - require.Equal(t, unspentCoinState, gotUnspentCoinState) -} - func TestPutGetAppExecResult(t *testing.T) { dao := NewSimple(storage.NewMemoryStore()) hash := random.Uint256() diff --git a/pkg/core/interop_neo.go b/pkg/core/interop_neo.go index 915fe5313..8ffc11a85 100644 --- a/pkg/core/interop_neo.go +++ b/pkg/core/interop_neo.go @@ -10,7 +10,6 @@ import ( "github.com/nspcc-dev/neo-go/pkg/core/interop" "github.com/nspcc-dev/neo-go/pkg/core/interop/runtime" "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/keys" "github.com/nspcc-dev/neo-go/pkg/smartcontract" @@ -88,95 +87,6 @@ func txGetAttributes(ic *interop.Context, v *vm.VM) error { return nil } -// txGetInputs returns current transaction inputs. -func txGetInputs(ic *interop.Context, v *vm.VM) error { - txInterface := v.Estack().Pop().Value() - tx, ok := txInterface.(*transaction.Transaction) - if !ok { - return errors.New("value is not a transaction") - } - if len(tx.Inputs) > vm.MaxArraySize { - return errors.New("too many inputs") - } - inputs := make([]vm.StackItem, 0, len(tx.Inputs)) - for i := range tx.Inputs { - inputs = append(inputs, vm.NewInteropItem(&tx.Inputs[i])) - } - v.Estack().PushVal(inputs) - return nil -} - -// txGetOutputs returns current transaction outputs. -func txGetOutputs(ic *interop.Context, v *vm.VM) error { - txInterface := v.Estack().Pop().Value() - tx, ok := txInterface.(*transaction.Transaction) - if !ok { - return errors.New("value is not a transaction") - } - if len(tx.Outputs) > vm.MaxArraySize { - return errors.New("too many outputs") - } - outputs := make([]vm.StackItem, 0, len(tx.Outputs)) - for i := range tx.Outputs { - outputs = append(outputs, vm.NewInteropItem(&tx.Outputs[i])) - } - v.Estack().PushVal(outputs) - return nil -} - -// txGetReferences returns current transaction references. -func txGetReferences(ic *interop.Context, v *vm.VM) error { - txInterface := v.Estack().Pop().Value() - tx, ok := txInterface.(*transaction.Transaction) - if !ok { - return fmt.Errorf("type mismatch: %T is not a Transaction", txInterface) - } - refs, err := ic.Chain.References(tx) - if err != nil { - return err - } - if len(refs) > vm.MaxArraySize { - return errors.New("too many references") - } - - stackrefs := make([]vm.StackItem, 0, len(refs)) - for i := range tx.Inputs { - for j := range refs { - if refs[j].In == tx.Inputs[i] { - stackrefs = append(stackrefs, vm.NewInteropItem(refs[j])) - break - } - } - } - v.Estack().PushVal(stackrefs) - return nil -} - -// txGetUnspentCoins returns current transaction unspent coins. -func txGetUnspentCoins(ic *interop.Context, v *vm.VM) error { - txInterface := v.Estack().Pop().Value() - tx, ok := txInterface.(*transaction.Transaction) - if !ok { - return errors.New("value is not a transaction") - } - ucs, err := ic.DAO.GetUnspentCoinState(tx.Hash()) - if err == storage.ErrKeyNotFound { - v.Estack().PushVal([]vm.StackItem{}) - return nil - } else if err != nil { - return errors.New("no unspent coin state found") - } - - items := make([]vm.StackItem, 0, len(ucs.States)) - for i := range items { - if ucs.States[i].State&state.CoinSpent == 0 { - items = append(items, vm.NewInteropItem(&ucs.States[i].Output)) - } - } - v.Estack().PushVal(items) - return nil -} - // txGetWitnesses returns current transaction witnesses. func txGetWitnesses(ic *interop.Context, v *vm.VM) error { txInterface := v.Estack().Pop().Value() @@ -209,84 +119,6 @@ func witnessGetVerificationScript(ic *interop.Context, v *vm.VM) error { return nil } -// popInputFromVM returns transaction.Input from the first estack element. -func popInputFromVM(v *vm.VM) (*transaction.Input, error) { - inInterface := v.Estack().Pop().Value() - input, ok := inInterface.(*transaction.Input) - if !ok { - txio, ok := inInterface.(transaction.InOut) - if !ok { - return nil, fmt.Errorf("type mismatch: %T is not an Input or InOut", inInterface) - } - input = &txio.In - } - return input, nil -} - -// inputGetHash returns hash from the given input. -func inputGetHash(ic *interop.Context, v *vm.VM) error { - input, err := popInputFromVM(v) - if err != nil { - return err - } - v.Estack().PushVal(input.PrevHash.BytesBE()) - return nil -} - -// inputGetIndex returns index from the given input. -func inputGetIndex(ic *interop.Context, v *vm.VM) error { - input, err := popInputFromVM(v) - if err != nil { - return err - } - v.Estack().PushVal(input.PrevIndex) - return nil -} - -// popOutputFromVM returns transaction.Input from the first estack element. -func popOutputFromVM(v *vm.VM) (*transaction.Output, error) { - outInterface := v.Estack().Pop().Value() - output, ok := outInterface.(*transaction.Output) - if !ok { - txio, ok := outInterface.(transaction.InOut) - if !ok { - return nil, fmt.Errorf("type mismatch: %T is not an Output or InOut", outInterface) - } - output = &txio.Out - } - return output, nil -} - -// outputGetAssetId returns asset ID from the given output. -func outputGetAssetID(ic *interop.Context, v *vm.VM) error { - output, err := popOutputFromVM(v) - if err != nil { - return err - } - v.Estack().PushVal(output.AssetID.BytesBE()) - return nil -} - -// outputGetScriptHash returns scripthash from the given output. -func outputGetScriptHash(ic *interop.Context, v *vm.VM) error { - output, err := popOutputFromVM(v) - if err != nil { - return err - } - v.Estack().PushVal(output.ScriptHash.BytesBE()) - return nil -} - -// outputGetValue returns value (amount) from the given output. -func outputGetValue(ic *interop.Context, v *vm.VM) error { - output, err := popOutputFromVM(v) - if err != nil { - return err - } - v.Estack().PushVal(int64(output.Amount)) - return nil -} - // attrGetData returns tx attribute data. func attrGetData(ic *interop.Context, v *vm.VM) error { attrInterface := v.Estack().Pop().Value() diff --git a/pkg/core/interop_neo_test.go b/pkg/core/interop_neo_test.go index 3dd0065be..b15339b53 100644 --- a/pkg/core/interop_neo_test.go +++ b/pkg/core/interop_neo_test.go @@ -25,8 +25,6 @@ import ( ) /* Missing tests: - * TestTxGetReferences - * TestTxGetUnspentCoins * TestTxGetWitnesses * TestBcGetAccount * TestBcGetAsset @@ -192,26 +190,6 @@ func TestTxGetAttributes(t *testing.T) { require.Equal(t, tx.Attributes[0].Usage, value[0].Value().(*transaction.Attribute).Usage) } -func TestTxGetInputs(t *testing.T) { - v, tx, context, chain := createVMAndPushTX(t) - defer chain.Close() - - err := txGetInputs(context, v) - require.NoError(t, err) - value := v.Estack().Pop().Value().([]vm.StackItem) - require.Equal(t, tx.Inputs[0], *value[0].Value().(*transaction.Input)) -} - -func TestTxGetOutputs(t *testing.T) { - v, tx, context, chain := createVMAndPushTX(t) - defer chain.Close() - - err := txGetOutputs(context, v) - require.NoError(t, err) - value := v.Estack().Pop().Value().([]vm.StackItem) - require.Equal(t, tx.Outputs[0], *value[0].Value().(*transaction.Output)) -} - func TestWitnessGetVerificationScript(t *testing.T) { v := vm.New() script := []byte{byte(opcode.PUSHM1), byte(opcode.RET)} @@ -304,81 +282,6 @@ func TestECDSAVerify(t *testing.T) { }) } -func TestPopInputFromVM(t *testing.T) { - v, tx, _, chain := createVMAndTX(t) - defer chain.Close() - v.Estack().PushVal(vm.NewInteropItem(&tx.Inputs[0])) - - input, err := popInputFromVM(v) - require.NoError(t, err) - require.Equal(t, tx.Inputs[0], *input) -} - -func TestInputGetHash(t *testing.T) { - v, tx, context, chain := createVMAndTX(t) - defer chain.Close() - v.Estack().PushVal(vm.NewInteropItem(&tx.Inputs[0])) - - err := inputGetHash(context, v) - require.NoError(t, err) - hash := v.Estack().Pop().Value() - require.Equal(t, tx.Inputs[0].PrevHash.BytesBE(), hash) -} - -func TestInputGetIndex(t *testing.T) { - v, tx, context, chain := createVMAndTX(t) - defer chain.Close() - v.Estack().PushVal(vm.NewInteropItem(&tx.Inputs[0])) - - err := inputGetIndex(context, v) - require.NoError(t, err) - index := v.Estack().Pop().Value() - require.Equal(t, big.NewInt(int64(tx.Inputs[0].PrevIndex)), index) -} - -func TestPopOutputFromVM(t *testing.T) { - v, tx, _, chain := createVMAndTX(t) - defer chain.Close() - v.Estack().PushVal(vm.NewInteropItem(&tx.Outputs[0])) - - output, err := popOutputFromVM(v) - require.NoError(t, err) - require.Equal(t, tx.Outputs[0], *output) -} - -func TestOutputGetAssetID(t *testing.T) { - v, tx, context, chain := createVMAndTX(t) - defer chain.Close() - v.Estack().PushVal(vm.NewInteropItem(&tx.Outputs[0])) - - err := outputGetAssetID(context, v) - require.NoError(t, err) - assetID := v.Estack().Pop().Value() - require.Equal(t, tx.Outputs[0].AssetID.BytesBE(), assetID) -} - -func TestOutputGetScriptHash(t *testing.T) { - v, tx, context, chain := createVMAndTX(t) - defer chain.Close() - v.Estack().PushVal(vm.NewInteropItem(&tx.Outputs[0])) - - err := outputGetScriptHash(context, v) - require.NoError(t, err) - scriptHash := v.Estack().Pop().Value() - require.Equal(t, tx.Outputs[0].ScriptHash.BytesBE(), scriptHash) -} - -func TestOutputGetValue(t *testing.T) { - v, tx, context, chain := createVMAndTX(t) - defer chain.Close() - v.Estack().PushVal(vm.NewInteropItem(&tx.Outputs[0])) - - err := outputGetValue(context, v) - require.NoError(t, err) - amount := v.Estack().Pop().Value() - require.Equal(t, big.NewInt(int64(tx.Outputs[0].Amount)), amount) -} - func TestAttrGetData(t *testing.T) { v, tx, context, chain := createVMAndTX(t) defer chain.Close() @@ -604,21 +507,7 @@ func createVMAndTX(t *testing.T) (*vm.VM, *transaction.Transaction, *interop.Con Data: bytes, }) - inputs := append(tx.Inputs, transaction.Input{ - PrevHash: random.Uint256(), - PrevIndex: 1, - }) - - outputs := append(tx.Outputs, transaction.Output{ - AssetID: random.Uint256(), - Amount: 10, - ScriptHash: random.Uint160(), - Position: 1, - }) - tx.Attributes = attributes - tx.Inputs = inputs - tx.Outputs = outputs chain := newTestChain(t) context := chain.newInteropContext(trigger.Application, dao.NewSimple(storage.NewMemoryStore()), nil, tx) return v, tx, context, chain diff --git a/pkg/core/interops.go b/pkg/core/interops.go index 1548345cc..a1ce73e46 100644 --- a/pkg/core/interops.go +++ b/pkg/core/interops.go @@ -148,17 +148,12 @@ var neoInterops = []interop.Function{ {Name: "Neo.Header.GetPrevHash", Func: headerGetPrevHash, Price: 1}, {Name: "Neo.Header.GetTimestamp", Func: headerGetTimestamp, Price: 1}, {Name: "Neo.Header.GetVersion", Func: headerGetVersion, Price: 1}, - {Name: "Neo.Input.GetHash", Func: inputGetHash, Price: 1}, - {Name: "Neo.Input.GetIndex", Func: inputGetIndex, Price: 1}, {Name: "Neo.Iterator.Concat", Func: iterator.Concat, Price: 1}, {Name: "Neo.Iterator.Create", Func: iterator.Create, Price: 1}, {Name: "Neo.Iterator.Key", Func: iterator.Key, Price: 1}, {Name: "Neo.Iterator.Keys", Func: iterator.Keys, Price: 1}, {Name: "Neo.Iterator.Values", Func: iterator.Values, Price: 1}, {Name: "Neo.Native.Deploy", Func: native.Deploy, Price: 1}, - {Name: "Neo.Output.GetAssetId", Func: outputGetAssetID, Price: 1}, - {Name: "Neo.Output.GetScriptHash", Func: outputGetScriptHash, Price: 1}, - {Name: "Neo.Output.GetValue", Func: outputGetValue, Price: 1}, {Name: "Neo.Runtime.CheckWitness", Func: runtime.CheckWitness, Price: 200}, {Name: "Neo.Runtime.Deserialize", Func: runtimeDeserialize, Price: 1}, {Name: "Neo.Runtime.GetTime", Func: runtimeGetTime, Price: 1}, @@ -175,10 +170,6 @@ var neoInterops = []interop.Function{ {Name: "Neo.StorageContext.AsReadOnly", Func: storageContextAsReadOnly, Price: 1}, {Name: "Neo.Transaction.GetAttributes", Func: txGetAttributes, Price: 1}, {Name: "Neo.Transaction.GetHash", Func: txGetHash, Price: 1}, - {Name: "Neo.Transaction.GetInputs", Func: txGetInputs, Price: 1}, - {Name: "Neo.Transaction.GetOutputs", Func: txGetOutputs, Price: 1}, - {Name: "Neo.Transaction.GetReferences", Func: txGetReferences, Price: 200}, - {Name: "Neo.Transaction.GetUnspentCoins", Func: txGetUnspentCoins, Price: 200}, {Name: "Neo.Transaction.GetWitnesses", Func: txGetWitnesses, Price: 200}, {Name: "Neo.Witness.GetVerificationScript", Func: witnessGetVerificationScript, Price: 100}, @@ -222,11 +213,6 @@ var neoInterops = []interop.Function{ {Name: "AntShares.Header.GetPrevHash", Func: headerGetPrevHash, Price: 1}, {Name: "AntShares.Header.GetTimestamp", Func: headerGetTimestamp, Price: 1}, {Name: "AntShares.Header.GetVersion", Func: headerGetVersion, Price: 1}, - {Name: "AntShares.Input.GetHash", Func: inputGetHash, Price: 1}, - {Name: "AntShares.Input.GetIndex", Func: inputGetIndex, Price: 1}, - {Name: "AntShares.Output.GetAssetId", Func: outputGetAssetID, Price: 1}, - {Name: "AntShares.Output.GetScriptHash", Func: outputGetScriptHash, Price: 1}, - {Name: "AntShares.Output.GetValue", Func: outputGetValue, Price: 1}, {Name: "AntShares.Runtime.CheckWitness", Func: runtime.CheckWitness, Price: 200}, {Name: "AntShares.Runtime.Log", Func: runtimeLog, Price: 1}, {Name: "AntShares.Runtime.Notify", Func: runtimeNotify, Price: 1}, @@ -236,9 +222,6 @@ var neoInterops = []interop.Function{ {Name: "AntShares.Storage.Put", Func: storagePut, Price: 0}, {Name: "AntShares.Transaction.GetAttributes", Func: txGetAttributes, Price: 1}, {Name: "AntShares.Transaction.GetHash", Func: txGetHash, Price: 1}, - {Name: "AntShares.Transaction.GetInputs", Func: txGetInputs, Price: 1}, - {Name: "AntShares.Transaction.GetOutputs", Func: txGetOutputs, Price: 1}, - {Name: "AntShares.Transaction.GetReferences", Func: txGetReferences, Price: 200}, } // initIDinInteropsSlice initializes IDs from names in one given diff --git a/pkg/core/interops_test.go b/pkg/core/interops_test.go index d1aa1b836..04babc946 100644 --- a/pkg/core/interops_test.go +++ b/pkg/core/interops_test.go @@ -58,11 +58,6 @@ func TestUnexpectedNonInterops(t *testing.T) { headerGetPrevHash, headerGetTimestamp, headerGetVersion, - inputGetHash, - inputGetIndex, - outputGetAssetID, - outputGetScriptHash, - outputGetValue, storageContextAsReadOnly, storageDelete, storageFind, @@ -71,10 +66,6 @@ func TestUnexpectedNonInterops(t *testing.T) { storagePutEx, txGetAttributes, txGetHash, - txGetInputs, - txGetOutputs, - txGetReferences, - txGetUnspentCoins, txGetWitnesses, witnessGetVerificationScript, } diff --git a/pkg/core/mempool/mem_pool.go b/pkg/core/mempool/mem_pool.go index 49741e170..f0ed818b4 100644 --- a/pkg/core/mempool/mem_pool.go +++ b/pkg/core/mempool/mem_pool.go @@ -12,8 +12,8 @@ import ( var ( // ErrConflict is returned when transaction being added is incompatible - // with the contents of the memory pool (using the same inputs as some - // other transaction in the pool) + // with the contents of the memory pool (Sender doesn't have enough GAS + // to pay for all transactions in the pool). ErrConflict = errors.New("conflicts with the memory pool") // ErrDup is returned when transaction being added is already present // in the memory pool. @@ -51,7 +51,6 @@ type Pool struct { lock sync.RWMutex verifiedMap map[util.Uint256]*item verifiedTxes items - inputs []*transaction.Input fees map[util.Uint160]utilityBalanceAndFees capacity int @@ -120,35 +119,6 @@ func (mp *Pool) containsKey(hash util.Uint256) bool { return false } -// findIndexForInput finds an index in a sorted Input pointers slice that is -// appropriate to place this input into (or which contains an identical Input). -func findIndexForInput(slice []*transaction.Input, input *transaction.Input) int { - return sort.Search(len(slice), func(n int) bool { - return input.Cmp(slice[n]) <= 0 - }) -} - -// pushInputToSortedSlice pushes new Input into the given slice. -func pushInputToSortedSlice(slice *[]*transaction.Input, input *transaction.Input) { - n := findIndexForInput(*slice, input) - *slice = append(*slice, input) - if n != len(*slice)-1 { - copy((*slice)[n+1:], (*slice)[n:]) - (*slice)[n] = input - } -} - -// dropInputFromSortedSlice removes given input from the given slice. -func dropInputFromSortedSlice(slice *[]*transaction.Input, input *transaction.Input) { - n := findIndexForInput(*slice, input) - if n == len(*slice) || *input != *(*slice)[n] { - // Not present. - return - } - copy((*slice)[n:], (*slice)[n+1:]) - *slice = (*slice)[:len(*slice)-1] -} - // tryAddSendersFee tries to add system fee and network fee to the total sender`s fee in mempool // and returns false if sender has not enough GAS to pay func (mp *Pool) tryAddSendersFee(tx *transaction.Transaction, feer Feer) bool { @@ -229,12 +199,6 @@ func (mp *Pool) Add(t *transaction.Transaction, fee Feer) error { } mp.addSendersFee(pItem.txn) - // For lots of inputs it might be easier to push them all and sort - // afterwards, but that requires benchmarking. - for i := range t.Inputs { - pushInputToSortedSlice(&mp.inputs, &t.Inputs[i]) - } - updateMempoolMetrics(len(mp.verifiedTxes)) mp.lock.Unlock() return nil @@ -260,9 +224,6 @@ func (mp *Pool) Remove(hash util.Uint256) { senderFee := mp.fees[it.txn.Sender] senderFee.feeSum -= it.txn.SystemFee + it.txn.NetworkFee mp.fees[it.txn.Sender] = senderFee - for i := range it.txn.Inputs { - dropInputFromSortedSlice(&mp.inputs, &it.txn.Inputs[i]) - } } updateMempoolMetrics(len(mp.verifiedTxes)) mp.lock.Unlock() @@ -276,23 +237,15 @@ func (mp *Pool) RemoveStale(isOK func(*transaction.Transaction) bool, feer Feer) // We can reuse already allocated slice // because items are iterated one-by-one in increasing order. newVerifiedTxes := mp.verifiedTxes[:0] - newInputs := mp.inputs[:0] mp.fees = make(map[util.Uint160]utilityBalanceAndFees) // it'd be nice to reuse existing map, but we can't easily clear it for _, itm := range mp.verifiedTxes { if isOK(itm.txn) && mp.tryAddSendersFee(itm.txn, feer) { newVerifiedTxes = append(newVerifiedTxes, itm) - for i := range itm.txn.Inputs { - newInputs = append(newInputs, &itm.txn.Inputs[i]) - } } else { delete(mp.verifiedMap, itm.txn.Hash()) } } - sort.Slice(newInputs, func(i, j int) bool { - return newInputs[i].Cmp(newInputs[j]) < 0 - }) mp.verifiedTxes = newVerifiedTxes - mp.inputs = newInputs mp.lock.Unlock() } @@ -317,8 +270,7 @@ func (mp *Pool) TryGetValue(hash util.Uint256) (*transaction.Transaction, util.F return nil, 0, false } -// GetVerifiedTransactions returns a slice of Input from all the transactions in the memory pool -// whose hash is not included in excludedHashes. +// GetVerifiedTransactions returns a slice of transactions with their fees. func (mp *Pool) GetVerifiedTransactions() []TxWithFee { mp.lock.RLock() defer mp.lock.RUnlock() @@ -333,32 +285,15 @@ func (mp *Pool) GetVerifiedTransactions() []TxWithFee { return t } -// areInputsInPool tries to find inputs in a given sorted pool and returns true -// if it finds any. -func areInputsInPool(inputs []transaction.Input, pool []*transaction.Input) bool { - for i := range inputs { - n := findIndexForInput(pool, &inputs[i]) - if n < len(pool) && *pool[n] == inputs[i] { - return true - } - } - return false -} - // checkTxConflicts is an internal unprotected version of Verify. func (mp *Pool) checkTxConflicts(tx *transaction.Transaction, fee Feer) bool { - if areInputsInPool(tx.Inputs, mp.inputs) { - return false - } - if !mp.checkBalanceAndUpdate(tx, fee) { - return false - } - return true + return mp.checkBalanceAndUpdate(tx, fee) } -// Verify verifies if the inputs of a transaction tx are already used in any other transaction in the memory pool. -// If yes, the transaction tx is not a valid transaction and the function return false. -// If no, the transaction tx is a valid transaction and the function return true. +// Verify checks if a Sender of tx is able to pay for it (and all the other +// transactions in the pool). If yes, the transaction tx is a valid +// transaction and the function returns true. If no, the transaction tx is +// considered to be invalid the function returns false. func (mp *Pool) Verify(tx *transaction.Transaction, feer Feer) bool { mp.lock.RLock() defer mp.lock.RUnlock() diff --git a/pkg/core/mempool/mem_pool_test.go b/pkg/core/mempool/mem_pool_test.go index 5a1129a96..33474540d 100644 --- a/pkg/core/mempool/mem_pool_test.go +++ b/pkg/core/mempool/mem_pool_test.go @@ -5,7 +5,6 @@ import ( "testing" "github.com/nspcc-dev/neo-go/pkg/core/transaction" - "github.com/nspcc-dev/neo-go/pkg/internal/random" "github.com/nspcc-dev/neo-go/pkg/util" "github.com/nspcc-dev/neo-go/pkg/vm/opcode" "github.com/stretchr/testify/assert" @@ -56,79 +55,6 @@ func TestMemPoolAddRemove(t *testing.T) { t.Run("high priority", func(t *testing.T) { testMemPoolAddRemoveWithFeer(t, fs) }) } -func TestMemPoolAddRemoveWithInputs(t *testing.T) { - mp := NewMemPool(50) - hash1, err := util.Uint256DecodeStringBE("a83ba6ede918a501558d3170a124324aedc89909e64c4ff2c6f863094f980b25") - require.NoError(t, err) - hash2, err := util.Uint256DecodeStringBE("629397158f852e838077bb2715b13a2e29b0a51c2157e5466321b70ed7904ce9") - require.NoError(t, err) - mpLessInputs := func(i, j int) bool { - return mp.inputs[i].Cmp(mp.inputs[j]) < 0 - } - txm1 := transaction.New([]byte{byte(opcode.PUSH1)}, 0) - txm1.Nonce = 1 - for i := 0; i < 5; i++ { - txm1.Inputs = append(txm1.Inputs, transaction.Input{PrevHash: hash1, PrevIndex: uint16(100 - i)}) - } - require.NoError(t, mp.Add(txm1, &FeerStub{})) - // Look inside. - assert.Equal(t, len(txm1.Inputs), len(mp.inputs)) - assert.True(t, sort.SliceIsSorted(mp.inputs, mpLessInputs)) - - txm2 := transaction.New([]byte{byte(opcode.PUSH1)}, 0) - txm2.Nonce = 1 - for i := 0; i < 10; i++ { - txm2.Inputs = append(txm2.Inputs, transaction.Input{PrevHash: hash2, PrevIndex: uint16(i)}) - } - require.NoError(t, mp.Add(txm2, &FeerStub{})) - assert.Equal(t, len(txm1.Inputs)+len(txm2.Inputs), len(mp.inputs)) - assert.True(t, sort.SliceIsSorted(mp.inputs, mpLessInputs)) - - mp.Remove(txm1.Hash()) - assert.Equal(t, len(txm2.Inputs), len(mp.inputs)) - assert.True(t, sort.SliceIsSorted(mp.inputs, mpLessInputs)) - - require.NoError(t, mp.Add(txm1, &FeerStub{})) - assert.Equal(t, len(txm1.Inputs)+len(txm2.Inputs), len(mp.inputs)) - assert.True(t, sort.SliceIsSorted(mp.inputs, mpLessInputs)) - - mp.RemoveStale(func(t *transaction.Transaction) bool { - if t.Hash() == txm2.Hash() { - return false - } - return true - }, &FeerStub{}) - assert.Equal(t, len(txm1.Inputs), len(mp.inputs)) - assert.True(t, sort.SliceIsSorted(mp.inputs, mpLessInputs)) -} - -func TestMemPoolVerifyInputs(t *testing.T) { - mp := NewMemPool(10) - tx := transaction.New([]byte{byte(opcode.PUSH1)}, 0) - tx.Nonce = 1 - inhash1 := random.Uint256() - tx.Inputs = append(tx.Inputs, transaction.Input{PrevHash: inhash1, PrevIndex: 0}) - require.Equal(t, true, mp.Verify(tx, &FeerStub{})) - require.NoError(t, mp.Add(tx, &FeerStub{})) - - tx2 := transaction.New([]byte{byte(opcode.PUSH1)}, 0) - tx2.Nonce = 2 - inhash2 := random.Uint256() - tx2.Inputs = append(tx2.Inputs, transaction.Input{PrevHash: inhash2, PrevIndex: 0}) - require.Equal(t, true, mp.Verify(tx2, &FeerStub{})) - require.NoError(t, mp.Add(tx2, &FeerStub{})) - - tx3 := transaction.New([]byte{byte(opcode.PUSH1)}, 0) - tx3.Nonce = 3 - // Different index number, but the same PrevHash as in tx1. - tx3.Inputs = append(tx3.Inputs, transaction.Input{PrevHash: inhash1, PrevIndex: 1}) - require.Equal(t, true, mp.Verify(tx3, &FeerStub{})) - // The same input as in tx2. - tx3.Inputs = append(tx3.Inputs, transaction.Input{PrevHash: inhash2, PrevIndex: 0}) - require.Equal(t, false, mp.Verify(tx3, &FeerStub{})) - require.Error(t, mp.Add(tx3, &FeerStub{})) -} - func TestOverCapacity(t *testing.T) { var fs = &FeerStub{lowPriority: true} const mempoolSize = 10 diff --git a/pkg/core/spent_coin.go b/pkg/core/spent_coin.go deleted file mode 100644 index 9d42cb8af..000000000 --- a/pkg/core/spent_coin.go +++ /dev/null @@ -1,10 +0,0 @@ -package core - -import "github.com/nspcc-dev/neo-go/pkg/core/transaction" - -// spentCoin represents the state of a single spent coin output. -type spentCoin struct { - Output *transaction.Output - StartHeight uint32 - EndHeight uint32 -} diff --git a/pkg/core/state/unspent_coin.go b/pkg/core/state/unspent_coin.go deleted file mode 100644 index a0f1e635e..000000000 --- a/pkg/core/state/unspent_coin.go +++ /dev/null @@ -1,60 +0,0 @@ -package state - -import ( - "github.com/nspcc-dev/neo-go/pkg/core/transaction" - "github.com/nspcc-dev/neo-go/pkg/io" -) - -// UnspentCoin hold the state of a unspent coin. -type UnspentCoin struct { - Height uint32 - States []OutputState -} - -// OutputState combines transaction output (UTXO) and its state -// (spent/claimed...) along with the height of spend (if it's spent). -type OutputState struct { - transaction.Output - - SpendHeight uint32 - State Coin -} - -// NewUnspentCoin returns a new unspent coin state with N confirmed states. -func NewUnspentCoin(height uint32, tx *transaction.Transaction) *UnspentCoin { - u := &UnspentCoin{ - Height: height, - States: make([]OutputState, len(tx.Outputs)), - } - for i := range tx.Outputs { - u.States[i] = OutputState{Output: tx.Outputs[i]} - } - return u -} - -// EncodeBinary encodes UnspentCoin to the given BinWriter. -func (s *UnspentCoin) EncodeBinary(bw *io.BinWriter) { - bw.WriteU32LE(s.Height) - bw.WriteArray(s.States) - bw.WriteVarUint(uint64(len(s.States))) -} - -// DecodeBinary decodes UnspentCoin from the given BinReader. -func (s *UnspentCoin) DecodeBinary(br *io.BinReader) { - s.Height = br.ReadU32LE() - br.ReadArray(&s.States) -} - -// EncodeBinary implements Serializable interface. -func (o *OutputState) EncodeBinary(w *io.BinWriter) { - o.Output.EncodeBinary(w) - w.WriteU32LE(o.SpendHeight) - w.WriteB(byte(o.State)) -} - -// DecodeBinary implements Serializable interface. -func (o *OutputState) DecodeBinary(r *io.BinReader) { - o.Output.DecodeBinary(r) - o.SpendHeight = r.ReadU32LE() - o.State = Coin(r.ReadB()) -} diff --git a/pkg/core/state/unspent_coin_test.go b/pkg/core/state/unspent_coin_test.go deleted file mode 100644 index 51e778ab7..000000000 --- a/pkg/core/state/unspent_coin_test.go +++ /dev/null @@ -1,47 +0,0 @@ -package state - -import ( - "testing" - - "github.com/nspcc-dev/neo-go/pkg/core/transaction" - "github.com/nspcc-dev/neo-go/pkg/internal/random" - "github.com/nspcc-dev/neo-go/pkg/internal/testserdes" - "github.com/nspcc-dev/neo-go/pkg/util" -) - -func TestDecodeEncodeUnspentCoin(t *testing.T) { - unspent := &UnspentCoin{ - Height: 100500, - States: []OutputState{ - { - Output: transaction.Output{ - AssetID: random.Uint256(), - Amount: util.Fixed8(42), - ScriptHash: random.Uint160(), - }, - SpendHeight: 201000, - State: CoinSpent, - }, - { - Output: transaction.Output{ - AssetID: random.Uint256(), - Amount: util.Fixed8(420), - ScriptHash: random.Uint160(), - }, - SpendHeight: 0, - State: CoinConfirmed, - }, - { - Output: transaction.Output{ - AssetID: random.Uint256(), - Amount: util.Fixed8(4200), - ScriptHash: random.Uint160(), - }, - SpendHeight: 111000, - State: CoinSpent & CoinClaimed, - }, - }, - } - - testserdes.EncodeDecodeBinary(t, unspent, new(UnspentCoin)) -} diff --git a/pkg/core/storage/store.go b/pkg/core/storage/store.go index 12a46dd69..6aab1c9c2 100644 --- a/pkg/core/storage/store.go +++ b/pkg/core/storage/store.go @@ -10,8 +10,6 @@ const ( DataBlock KeyPrefix = 0x01 DataTransaction KeyPrefix = 0x02 STAccount KeyPrefix = 0x40 - STCoin KeyPrefix = 0x44 - STSpentCoin KeyPrefix = 0x45 STValidator KeyPrefix = 0x48 STAsset KeyPrefix = 0x4c STNotification KeyPrefix = 0x4d diff --git a/pkg/core/storage/store_test.go b/pkg/core/storage/store_test.go index 9c9f6ef70..7b90b4d67 100644 --- a/pkg/core/storage/store_test.go +++ b/pkg/core/storage/store_test.go @@ -11,7 +11,6 @@ var ( DataBlock, DataTransaction, STAccount, - STCoin, STValidator, STAsset, STContract, @@ -26,7 +25,6 @@ var ( 0x01, 0x02, 0x40, - 0x44, 0x48, 0x4c, 0x50, diff --git a/pkg/core/transaction/inout.go b/pkg/core/transaction/inout.go deleted file mode 100644 index 75bc026ac..000000000 --- a/pkg/core/transaction/inout.go +++ /dev/null @@ -1,8 +0,0 @@ -package transaction - -// InOut represents an Input bound to its corresponding Output which is a useful -// combination for many purposes. -type InOut struct { - In Input - Out Output -} diff --git a/pkg/core/transaction/input.go b/pkg/core/transaction/input.go deleted file mode 100644 index 40462fba2..000000000 --- a/pkg/core/transaction/input.go +++ /dev/null @@ -1,94 +0,0 @@ -package transaction - -import ( - "sort" - - "github.com/nspcc-dev/neo-go/pkg/io" - "github.com/nspcc-dev/neo-go/pkg/util" -) - -// Input represents a Transaction input (CoinReference). -type Input struct { - // The hash of the previous transaction. - PrevHash util.Uint256 `json:"txid"` - - // The index of the previous transaction. - PrevIndex uint16 `json:"vout"` -} - -// DecodeBinary implements Serializable interface. -func (in *Input) DecodeBinary(br *io.BinReader) { - br.ReadBytes(in.PrevHash[:]) - in.PrevIndex = br.ReadU16LE() -} - -// EncodeBinary implements Serializable interface. -func (in *Input) EncodeBinary(bw *io.BinWriter) { - bw.WriteBytes(in.PrevHash[:]) - bw.WriteU16LE(in.PrevIndex) -} - -// Cmp compares two Inputs by their hash and index allowing to make a set of -// transactions ordered. -func (in *Input) Cmp(other *Input) int { - hashcmp := in.PrevHash.CompareTo(other.PrevHash) - if hashcmp == 0 { - return int(in.PrevIndex) - int(other.PrevIndex) - } - return hashcmp -} - -// MapInputsToSorted maps given slice of inputs into a new slice of pointers -// to inputs sorted by their PrevHash and PrevIndex. -func MapInputsToSorted(ins []Input) []*Input { - ptrs := make([]*Input, len(ins)) - for i := range ins { - ptrs[i] = &ins[i] - } - sort.Slice(ptrs, func(i, j int) bool { - return ptrs[i].Cmp(ptrs[j]) < 0 - }) - return ptrs -} - -// GroupInputsByPrevHash groups all TX inputs by their previous hash into -// several slices (which actually are subslices of one new slice with pointers). -// Each of these slices contains at least one element. -func GroupInputsByPrevHash(ins []Input) [][]*Input { - if len(ins) == 0 { - return nil - } - - ptrs := MapInputsToSorted(ins) - var first int - res := make([][]*Input, 0) - currentHash := ptrs[0].PrevHash - - for i := range ptrs { - if !currentHash.Equals(ptrs[i].PrevHash) { - res = append(res, ptrs[first:i]) - first = i - currentHash = ptrs[i].PrevHash - } - } - res = append(res, ptrs[first:]) - return res -} - -// HaveDuplicateInputs checks inputs for duplicates and returns true if there are -// any. -func HaveDuplicateInputs(ins []Input) bool { - if len(ins) < 2 { - return false - } - if len(ins) == 2 { - return ins[0] == ins[1] - } - ptrs := MapInputsToSorted(ins) - for i := 1; i < len(ptrs); i++ { - if *ptrs[i] == *ptrs[i-1] { - return true - } - } - return false -} diff --git a/pkg/core/transaction/input_test.go b/pkg/core/transaction/input_test.go deleted file mode 100644 index c8b9fad06..000000000 --- a/pkg/core/transaction/input_test.go +++ /dev/null @@ -1,144 +0,0 @@ -package transaction - -import ( - "testing" - - "github.com/nspcc-dev/neo-go/pkg/util" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -func TestGroupInputsByPrevHash0(t *testing.T) { - inputs := make([]Input, 0) - res := GroupInputsByPrevHash(inputs) - require.Equal(t, 0, len(res)) -} - -func TestGroupInputsByPrevHash1(t *testing.T) { - inputs := make([]Input, 0) - hash, err := util.Uint256DecodeStringLE("46168f963d6d8168a870405f66cc9e13a235791013b8ee2f90cc20a8293bd1af") - require.NoError(t, err) - inputs = append(inputs, Input{PrevHash: hash, PrevIndex: 42}) - res := GroupInputsByPrevHash(inputs) - require.Equal(t, 1, len(res)) - require.Equal(t, 1, len(res[0])) - assert.Equal(t, hash, res[0][0].PrevHash) - assert.Equal(t, uint16(42), res[0][0].PrevIndex) -} - -func TestGroupInputsByPrevHashMany(t *testing.T) { - hash1, err := util.Uint256DecodeStringBE("a83ba6ede918a501558d3170a124324aedc89909e64c4ff2c6f863094f980b25") - require.NoError(t, err) - hash2, err := util.Uint256DecodeStringBE("629397158f852e838077bb2715b13a2e29b0a51c2157e5466321b70ed7904ce9") - require.NoError(t, err) - hash3, err := util.Uint256DecodeStringBE("caa41245c3e48ddc13dabe989ba8fbc59418e9228fef9efb62855b0b17d7448b") - require.NoError(t, err) - inputs := make([]Input, 0) - for i := 0; i < 10; i++ { - inputs = append(inputs, Input{PrevHash: hash1, PrevIndex: uint16(i)}) - inputs = append(inputs, Input{PrevHash: hash2, PrevIndex: uint16(i)}) - inputs = append(inputs, Input{PrevHash: hash3, PrevIndex: uint16(i)}) - } - for i := 15; i < 20; i++ { - inputs = append(inputs, Input{PrevHash: hash3, PrevIndex: uint16(i)}) - } - for i := 10; i < 15; i++ { - inputs = append(inputs, Input{PrevHash: hash2, PrevIndex: uint16(i)}) - inputs = append(inputs, Input{PrevHash: hash3, PrevIndex: uint16(i)}) - } - seen := make(map[uint16]bool) - res := GroupInputsByPrevHash(inputs) - require.Equal(t, 3, len(res)) - assert.Equal(t, hash2, res[0][0].PrevHash) - assert.Equal(t, 15, len(res[0])) - for i := range res[0] { - assert.Equal(t, res[0][i].PrevHash, res[0][0].PrevHash) - assert.Equal(t, false, seen[res[0][i].PrevIndex]) - seen[res[0][i].PrevIndex] = true - } - seen = make(map[uint16]bool) - assert.Equal(t, hash1, res[1][0].PrevHash) - assert.Equal(t, 10, len(res[1])) - for i := range res[1] { - assert.Equal(t, res[1][i].PrevHash, res[1][0].PrevHash) - assert.Equal(t, false, seen[res[1][i].PrevIndex]) - seen[res[1][i].PrevIndex] = true - } - seen = make(map[uint16]bool) - assert.Equal(t, hash3, res[2][0].PrevHash) - assert.Equal(t, 20, len(res[2])) - for i := range res[2] { - assert.Equal(t, res[2][i].PrevHash, res[2][0].PrevHash) - assert.Equal(t, false, seen[res[2][i].PrevIndex]) - seen[res[2][i].PrevIndex] = true - } -} - -func TestHaveDuplicateInputs0(t *testing.T) { - inputs := make([]Input, 0) - require.False(t, HaveDuplicateInputs(inputs)) -} - -func TestHaveDuplicateInputs1(t *testing.T) { - inputs := make([]Input, 0) - hash, err := util.Uint256DecodeStringLE("46168f963d6d8168a870405f66cc9e13a235791013b8ee2f90cc20a8293bd1af") - require.NoError(t, err) - inputs = append(inputs, Input{PrevHash: hash, PrevIndex: 42}) - require.False(t, HaveDuplicateInputs(inputs)) -} - -func TestHaveDuplicateInputs2True(t *testing.T) { - inputs := make([]Input, 0) - hash, err := util.Uint256DecodeStringLE("46168f963d6d8168a870405f66cc9e13a235791013b8ee2f90cc20a8293bd1af") - require.NoError(t, err) - inputs = append(inputs, Input{PrevHash: hash, PrevIndex: 42}) - inputs = append(inputs, Input{PrevHash: hash, PrevIndex: 42}) - require.True(t, HaveDuplicateInputs(inputs)) -} - -func TestHaveDuplicateInputs2FalseInd(t *testing.T) { - inputs := make([]Input, 0) - hash, err := util.Uint256DecodeStringLE("46168f963d6d8168a870405f66cc9e13a235791013b8ee2f90cc20a8293bd1af") - require.NoError(t, err) - inputs = append(inputs, Input{PrevHash: hash, PrevIndex: 42}) - inputs = append(inputs, Input{PrevHash: hash, PrevIndex: 41}) - require.False(t, HaveDuplicateInputs(inputs)) -} - -func TestHaveDuplicateInputs2FalseHash(t *testing.T) { - inputs := make([]Input, 0) - hash1, err := util.Uint256DecodeStringBE("a83ba6ede918a501558d3170a124324aedc89909e64c4ff2c6f863094f980b25") - require.NoError(t, err) - hash2, err := util.Uint256DecodeStringBE("629397158f852e838077bb2715b13a2e29b0a51c2157e5466321b70ed7904ce9") - require.NoError(t, err) - inputs = append(inputs, Input{PrevHash: hash1, PrevIndex: 42}) - inputs = append(inputs, Input{PrevHash: hash2, PrevIndex: 42}) - require.False(t, HaveDuplicateInputs(inputs)) -} - -func TestHaveDuplicateInputsMFalse(t *testing.T) { - inputs := make([]Input, 0) - hash1, err := util.Uint256DecodeStringBE("a83ba6ede918a501558d3170a124324aedc89909e64c4ff2c6f863094f980b25") - require.NoError(t, err) - hash2, err := util.Uint256DecodeStringBE("629397158f852e838077bb2715b13a2e29b0a51c2157e5466321b70ed7904ce9") - require.NoError(t, err) - for i := 0; i < 10; i++ { - inputs = append(inputs, Input{PrevHash: hash1, PrevIndex: uint16(i)}) - inputs = append(inputs, Input{PrevHash: hash2, PrevIndex: uint16(i)}) - } - require.False(t, HaveDuplicateInputs(inputs)) -} - -func TestHaveDuplicateInputsMTrue(t *testing.T) { - inputs := make([]Input, 0) - hash1, err := util.Uint256DecodeStringBE("a83ba6ede918a501558d3170a124324aedc89909e64c4ff2c6f863094f980b25") - require.NoError(t, err) - hash2, err := util.Uint256DecodeStringBE("629397158f852e838077bb2715b13a2e29b0a51c2157e5466321b70ed7904ce9") - require.NoError(t, err) - for i := 0; i < 10; i++ { - inputs = append(inputs, Input{PrevHash: hash1, PrevIndex: uint16(i)}) - inputs = append(inputs, Input{PrevHash: hash2, PrevIndex: uint16(i)}) - } - inputs = append(inputs, Input{PrevHash: hash1, PrevIndex: 0}) - require.True(t, HaveDuplicateInputs(inputs)) -} diff --git a/pkg/core/transaction/output.go b/pkg/core/transaction/output.go deleted file mode 100644 index 11ad85b2e..000000000 --- a/pkg/core/transaction/output.go +++ /dev/null @@ -1,82 +0,0 @@ -package transaction - -import ( - "encoding/json" - - "github.com/nspcc-dev/neo-go/pkg/encoding/address" - "github.com/nspcc-dev/neo-go/pkg/io" - "github.com/nspcc-dev/neo-go/pkg/util" -) - -// Output represents a Transaction output. -type Output struct { - // The NEO asset id used in the transaction. - AssetID util.Uint256 `json:"asset"` - - // Amount of AssetType send or received. - Amount util.Fixed8 `json:"value"` - - // The address of the recipient. - ScriptHash util.Uint160 `json:"address"` - - // The position of the Output in slice []Output. This is actually set in NewTransactionOutputRaw - // and used for displaying purposes. - Position int `json:"n"` -} - -type outputAux struct { - AssetID util.Uint256 `json:"asset"` - Amount util.Fixed8 `json:"value"` - ScriptHash string `json:"address"` - Position int `json:"n"` -} - -// NewOutput returns a new transaction output. -func NewOutput(assetID util.Uint256, amount util.Fixed8, scriptHash util.Uint160) *Output { - return &Output{ - AssetID: assetID, - Amount: amount, - ScriptHash: scriptHash, - } -} - -// DecodeBinary implements Serializable interface. -func (out *Output) DecodeBinary(br *io.BinReader) { - br.ReadBytes(out.AssetID[:]) - out.Amount.DecodeBinary(br) - br.ReadBytes(out.ScriptHash[:]) -} - -// EncodeBinary implements Serializable interface. -func (out *Output) EncodeBinary(bw *io.BinWriter) { - bw.WriteBytes(out.AssetID[:]) - out.Amount.EncodeBinary(bw) - bw.WriteBytes(out.ScriptHash[:]) -} - -// MarshalJSON implements the Marshaler interface. -func (out *Output) MarshalJSON() ([]byte, error) { - return json.Marshal(map[string]interface{}{ - "asset": out.AssetID, - "value": out.Amount, - "address": address.Uint160ToString(out.ScriptHash), - "n": out.Position, - }) -} - -// UnmarshalJSON implements json.Unmarshaler interface. -func (out *Output) UnmarshalJSON(data []byte) error { - var outAux outputAux - err := json.Unmarshal(data, &outAux) - if err != nil { - return err - } - out.ScriptHash, err = address.StringToUint160(outAux.ScriptHash) - if err != nil { - return err - } - out.Amount = outAux.Amount - out.AssetID = outAux.AssetID - out.Position = outAux.Position - return nil -} diff --git a/pkg/core/transaction/transaction.go b/pkg/core/transaction/transaction.go index f3923b35f..f0d1f8763 100644 --- a/pkg/core/transaction/transaction.go +++ b/pkg/core/transaction/transaction.go @@ -54,12 +54,6 @@ type Transaction struct { // Transaction cosigners (not include Sender). Cosigners []Cosigner - // The inputs of the transaction. - Inputs []Input - - // The outputs of the transaction. - Outputs []Output - // The scripts that comes with this transaction. // Scripts exist out of the verification script // and invocation script. @@ -95,8 +89,6 @@ func New(script []byte, gas util.Fixed8) *Transaction { SystemFee: gas, Attributes: []Attribute{}, Cosigners: []Cosigner{}, - Inputs: []Input{}, - Outputs: []Output{}, Scripts: []Witness{}, } } @@ -121,16 +113,6 @@ func (t *Transaction) VerificationHash() util.Uint256 { return t.verificationHash } -// AddOutput adds the given output to the transaction outputs. -func (t *Transaction) AddOutput(out *Output) { - t.Outputs = append(t.Outputs, *out) -} - -// AddInput adds the given input to the transaction inputs. -func (t *Transaction) AddInput(in *Input) { - t.Inputs = append(t.Inputs, *in) -} - // DecodeBinary implements Serializable interface. func (t *Transaction) DecodeBinary(br *io.BinReader) { t.Version = uint8(br.ReadB()) @@ -174,14 +156,6 @@ func (t *Transaction) DecodeBinary(br *io.BinReader) { return } - br.ReadArray(&t.Inputs) - br.ReadArray(&t.Outputs) - for i := range t.Outputs { - if t.Outputs[i].Amount.LessThan(0) { - br.Err = errors.New("negative output") - return - } - } br.ReadArray(&t.Scripts) // Create the hash of the transaction at decode, so we dont need @@ -218,11 +192,6 @@ func (t *Transaction) encodeHashableFields(bw *io.BinWriter) { bw.WriteArray(t.Cosigners) bw.WriteVarBytes(t.Script) - // Inputs - bw.WriteArray(t.Inputs) - - // Outputs - bw.WriteArray(t.Outputs) } // createHash creates the hash of the transaction. @@ -240,16 +209,6 @@ func (t *Transaction) createHash() error { return nil } -// GroupOutputByAssetID groups all TX outputs by their assetID. -func (t Transaction) GroupOutputByAssetID() map[util.Uint256][]*Output { - m := make(map[util.Uint256][]*Output) - for i := range t.Outputs { - hash := t.Outputs[i].AssetID - m[hash] = append(m[hash], &t.Outputs[i]) - } - return m -} - // GetSignedPart returns a part of the transaction which must be signed. func (t *Transaction) GetSignedPart() []byte { buf := io.NewBufBinWriter() @@ -301,8 +260,6 @@ type transactionJSON struct { Attributes []Attribute `json:"attributes"` Cosigners []Cosigner `json:"cosigners"` Script string `json:"script"` - Inputs []Input `json:"vin"` - Outputs []Output `json:"vout"` Scripts []Witness `json:"scripts"` } @@ -318,8 +275,6 @@ func (t *Transaction) MarshalJSON() ([]byte, error) { Attributes: t.Attributes, Cosigners: t.Cosigners, Script: hex.EncodeToString(t.Script), - Inputs: t.Inputs, - Outputs: t.Outputs, Scripts: t.Scripts, SystemFee: t.SystemFee, NetworkFee: t.NetworkFee, @@ -338,8 +293,6 @@ func (t *Transaction) UnmarshalJSON(data []byte) error { t.ValidUntilBlock = tx.ValidUntilBlock t.Attributes = tx.Attributes t.Cosigners = tx.Cosigners - t.Inputs = tx.Inputs - t.Outputs = tx.Outputs t.Scripts = tx.Scripts t.SystemFee = tx.SystemFee t.NetworkFee = tx.NetworkFee diff --git a/pkg/core/transaction/transaction_test.go b/pkg/core/transaction/transaction_test.go index 2ea9bea19..bbc082d18 100644 --- a/pkg/core/transaction/transaction_test.go +++ b/pkg/core/transaction/transaction_test.go @@ -88,18 +88,8 @@ func TestMarshalUnmarshalJSONInvocationTX(t *testing.T) { Version: 0, Script: []byte{1, 2, 3, 4}, Attributes: []Attribute{}, - Inputs: []Input{{ - PrevHash: util.Uint256{5, 6, 7, 8}, - PrevIndex: uint16(12), - }}, - Outputs: []Output{{ - AssetID: util.Uint256{1, 2, 3}, - Amount: util.Fixed8FromInt64(1), - ScriptHash: util.Uint160{1, 2, 3}, - Position: 0, - }}, - Scripts: []Witness{}, - Trimmed: false, + Scripts: []Witness{}, + Trimmed: false, } testserdes.MarshalUnmarshalJSON(t, tx, new(Transaction)) diff --git a/pkg/core/util_test.go b/pkg/core/util_test.go index b49bd3d49..da254c162 100644 --- a/pkg/core/util_test.go +++ b/pkg/core/util_test.go @@ -20,7 +20,7 @@ func TestGenesisBlockMainNet(t *testing.T) { // have been changed. Consequently, hash of the genesis block has been changed. // Update expected genesis block hash for better times. // Old hash is "d42561e3d30e15be6400b6df2f328e02d2bf6354c41dce433bc57687c82144bf" - expect := "2535d4b8b244c8a036ed356ee4448e041dc6e8f1d81abdcc7e3d0640c66f6cc8" + expect := "e4cfc549c87d4ab7b570c368d05853ffb70eb9ef0f7d9c7a2e6e9e5d713ebbf4" assert.Equal(t, expect, block.Hash().StringLE()) } diff --git a/pkg/interop/input/input.go b/pkg/interop/input/input.go deleted file mode 100644 index e577f2815..000000000 --- a/pkg/interop/input/input.go +++ /dev/null @@ -1,22 +0,0 @@ -/* -Package input provides functions dealing with transaction inputs. -*/ -package input - -// Input is an opaque data structure that can only be created by -// transaction.GetInputs and it represents transaction's input. It's similar -// to Neo .net framework's TransactionInput. -type Input struct{} - -// GetHash returns the hash stored in the given input (which also is a -// transaction ID represented as 32 byte slice containing 256 bit BE value). -// It uses `Neo.Input.GetHash` syscall. -func GetHash(in Input) []byte { - return nil -} - -// GetIndex returns the index stored in the given input (which is a -// transaction's output number). It uses `Neo.Input.GetIndex` syscall. -func GetIndex(in Input) int { - return 0 -} diff --git a/pkg/interop/output/output.go b/pkg/interop/output/output.go deleted file mode 100644 index 01ad0c828..000000000 --- a/pkg/interop/output/output.go +++ /dev/null @@ -1,28 +0,0 @@ -/* -Package output provides functions dealing with transaction outputs. -*/ -package output - -// Output is an opaque data structure that can only be created by -// transaction.GetOutputs and it represents transaction's output. It's similar -// to Neo .net framework's TransactionOutput. -type Output struct{} - -// GetAssetID returns the asset ID (256 bit BE value in a 32 byte slice) of the -// given output. It uses `Neo.Output.GetAssetId` syscall. -func GetAssetID(out Output) []byte { - return nil -} - -// GetValue returns the value (asset quantity) of the given output. It uses -// `Neo.Output.GetValue` syscall. -func GetValue(out Output) int { - return 0 -} - -// GetScriptHash returns the script hash (receiver's address represented as -// 20 byte slice containing 160 bit BE value) of the given output. It uses -// `Neo.Output.GetScriptHash` syscall. -func GetScriptHash(out Output) []byte { - return nil -} diff --git a/pkg/interop/transaction/transaction.go b/pkg/interop/transaction/transaction.go index 4f975fd8e..fc44f37c4 100644 --- a/pkg/interop/transaction/transaction.go +++ b/pkg/interop/transaction/transaction.go @@ -5,8 +5,6 @@ package transaction import ( "github.com/nspcc-dev/neo-go/pkg/interop/attribute" - "github.com/nspcc-dev/neo-go/pkg/interop/input" - "github.com/nspcc-dev/neo-go/pkg/interop/output" "github.com/nspcc-dev/neo-go/pkg/interop/witness" ) @@ -28,35 +26,6 @@ func GetAttributes(t Transaction) []attribute.Attribute { return []attribute.Attribute{} } -// GetReferences returns a slice of references for a given Transaction. Elements -// of this slice can be casted to any of input.Input or output.Output, depending -// on which information you're interested in (as reference technically contains -// both input and corresponding output), refer to input and output package on -// how to use them. This function uses `Neo.Transaction.GetReferences` syscall. -func GetReferences(t Transaction) []interface{} { - return []interface{}{} -} - -// GetUnspentCoins returns a slice of not yet spent ouputs of a given transaction. -// This function uses `Neo.Transaction.GetUnspentCoint` syscall. -func GetUnspentCoins(t Transaction) []output.Output { - return []output.Output{} -} - -// GetInputs returns a slice of inputs of a given Transaction. Refer to input -// package on how to use them. This function uses `Neo.Transaction.GetInputs` -// syscall. -func GetInputs(t Transaction) []input.Input { - return []input.Input{} -} - -// GetOutputs returns a slice of outputs of a given Transaction. Refer to output -// package on how to use them. This function uses `Neo.Transaction.GetOutputs` -// syscall. -func GetOutputs(t Transaction) []output.Output { - return []output.Output{} -} - // GetWitnesses returns a slice of witnesses of a given Transaction. Refer to // witness package on how to use them. This function uses // `Neo.Transaction.GetWitnesses` syscall. diff --git a/pkg/network/helper_test.go b/pkg/network/helper_test.go index 8beed2bf3..d8ffaabde 100644 --- a/pkg/network/helper_test.go +++ b/pkg/network/helper_test.go @@ -35,10 +35,6 @@ func (chain testChain) CalculateClaimable(int64, uint32, uint32) util.Fixed8 { panic("TODO") } -func (chain testChain) References(t *transaction.Transaction) ([]transaction.InOut, error) { - panic("TODO") -} - func (chain testChain) FeePerByte() util.Fixed8 { panic("TODO") } @@ -126,10 +122,6 @@ func (chain testChain) GetTransaction(util.Uint256) (*transaction.Transaction, u panic("TODO") } -func (chain testChain) GetUnspentCoinState(util.Uint256) *state.UnspentCoin { - panic("TODO") -} - func (chain testChain) GetMemPool() *mempool.Pool { panic("TODO") } diff --git a/pkg/rpc/client/client.go b/pkg/rpc/client/client.go index d9ead3469..1f2c1cad2 100644 --- a/pkg/rpc/client/client.go +++ b/pkg/rpc/client/client.go @@ -8,16 +8,12 @@ import ( "net" "net/http" "net/url" - "sort" "sync" "time" - "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/rpc/request" "github.com/nspcc-dev/neo-go/pkg/rpc/response" - "github.com/nspcc-dev/neo-go/pkg/util" "github.com/pkg/errors" ) @@ -197,34 +193,3 @@ func (c *Client) Ping() error { _ = conn.Close() return nil } - -// unspentsToInputs uses UnspentBalances to create a slice of inputs for a new -// transcation containing the required amount of asset. -func unspentsToInputs(utxos state.UnspentBalances, required util.Fixed8) ([]transaction.Input, util.Fixed8, error) { - var ( - num, i uint16 - selected = util.Fixed8(0) - ) - sort.Sort(utxos) - - for _, us := range utxos { - if selected >= required { - break - } - selected += us.Value - num++ - } - if selected < required { - return nil, util.Fixed8(0), errors.New("cannot compose inputs for transaction; check sender balance") - } - - inputs := make([]transaction.Input, 0, num) - for i = 0; i < num; i++ { - inputs = append(inputs, transaction.Input{ - PrevHash: utxos[i].Tx, - PrevIndex: utxos[i].Index, - }) - } - - return inputs, selected, nil -} diff --git a/pkg/rpc/client/rpc_test.go b/pkg/rpc/client/rpc_test.go index aa657036e..c10f2e1df 100644 --- a/pkg/rpc/client/rpc_test.go +++ b/pkg/rpc/client/rpc_test.go @@ -31,17 +31,17 @@ type rpcClientTestCase struct { check func(t *testing.T, c *Client, result interface{}) } -const hexB1 = "000000001409900d6f330df2624b9ad49e4e68c04bab6757b684b4ae46e995ec9278002d6aa5da3b3922db2ae0fb51e6058d123d441650db8a187e7b7a34c55927fae217b91274847201000001000000abec5362f11e75b6e02e407bb98d63675d14384101fd08010c40bac8992a77bd21ba670f2bf5097387a42b227878b361c69bfeeeb55c4b68bdff7db5c93b8f6d84876e473bba84bf27dc7de8d35b8179e120a60a6bc01562ac740c401c876fdb2fbffc599ac9ffbc85f7e6087855fd40e12b23888718e381c93de2614cce5bdfb1108ff72a73b85d4a6556dad6578a59bfa0e61b93c775cb1c1924f20c40fd992b9d776da1d2da390915e743f4213ce8a6db862b6354cccbcb3bf8b4edd14562cb546cbbcb3e2d096c9e527d4ee7879c5bbfd01d9a2bb00a1986820e1c320c40fcf3d76b809078a872970bd3bde5836589a7f62660098bbfb82a1cb470b75cc480d527a3829de89c897bacc6c29dfc3e4b84368aa1f69c9bce704fb3399fc04e94130c2102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e0c2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd620c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20c2103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699140b413073b3bb030057040000000000000002000000abec5362f11e75b6e02e407bb98d63675d14384100000000000000000e670d0000000000b00400000001abec5362f11e75b6e02e407bb98d63675d14384101590218ddf5050c14316e851039019d39dfc2c37d6c3fee19fd5809870c14abec5362f11e75b6e02e407bb98d63675d14384113c00c087472616e736665720c14897720d8cd76f4f00abfa37c0edd889c208fde9b41627d5b5238000001fd08010c4015b24aa11983bbf098384be4ebf5c283c3b4b2d2f6bf17b1a2a32f59627c7eb6370748b231acce2eb1ab5db3cdbf6943084634d12f69bf7b0aa447f96ebaf7d40c40a6777566463018e3f82fbbd370eef65b8454e50978401d1d97df05d9eda3b2bd5f5f882a94f8adbeaa2a55f64bd4ec23398fca26e8b364e5f57c771d71b3ec3d0c4032f5b1e3af669f4f14c2579de8f7ce46e30b35f7ed70892389251d50779477d2506b330dc9dd47f8c406218656d60b669479433bd9f762888091dc94415de5690c404b6ca943c34be335466c25ed442d17abc24d6a78db407a8c2a2c43fb911f0cbdbb28ec791b5f9de01b2db26105aa35193113a3a382c1ed02fbaf82b42468853a94130c2102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e0c2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd620c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20c2103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699140b413073b3bb0003000000abec5362f11e75b6e02e407bb98d63675d1438410000000000000000ae760d0000000000b00400000001abec5362f11e75b6e02e407bb98d63675d143841015d0300e87648170000000c14316e851039019d39dfc2c37d6c3fee19fd5809870c14abec5362f11e75b6e02e407bb98d63675d14384113c00c087472616e736665720c143b7d3711c6f0ccf9b1dca903d1bfa1d896f1238c41627d5b5238000001fd08010c4001c81faa8317a390c211d5e03451ed852ff02ec6c401c450558bc90c60a01912c3e1018de98e7458f6f96c68aad71ffb0e92327fcdfa4aabb5ea5834ec7afbf10c40a84e9bc36ffbf18a1ee79254182d2939dd3a7b9278e13893856f187ab44dec259c8a15d4f449a21aa6970234d79d81fee0aca1807341b977ff66d503a78c82920c4085495bb8d86b95a4afc1659ce1d993e1a7843e3dcb19696ce0422294dadddc73438780d5bc629560f576e0e75cff062c03e237d4e609dfaa9869135e23a487650c40ae25f2c563b978f931c3a8b5a18854d9bb77abf48c7554f2008f97696caca180cd40d4d0e47b3f4d86082e631547d1a4729c7ed60dda64fab9cd9a2270dd113294130c2102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e0c2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd620c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20c2103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699140b413073b3bb" +const hexB1 = "00000000e862e7907fc987cd58ddb3abb754aeb8812c9377c45e737a036fe88a622c3b8f301f2e84a86b207270830e7929530ccb841a3df7379fe6f0ac8865b33316839501cdd0847201000001000000abec5362f11e75b6e02e407bb98d63675d14384101fd08010c40ab634ce91590e77b246cee8b204e8a270268ee1ef32434cece73f425a7dbc90f1bed1dbe914edcaa2653167ad170ae10e16a9b2c6b7e0af1f711fb848fbb1b7f0c40232de6ad07ee3846bafa96302d37602349501a556df575e7df0743e45b076d6a0c6c6dd4cad3898f9e8848dd054abd303b229fd12984042f241f0e668f39a0fb0c408b4af43057df189a9d471010b5150bab442040403147c5e502bda38cde3ff8bce803f01245e07e2bfb95d57349c55dcc27e3710b82f2735d0f40eb4342908e330c40cda66f743d4ed8d856f5376953f9169581c668a9370245aef16202ebef9bb3f7f81234be62ec287d701ad7d8bf5042648019af9fe5baa0a8e05d279bfdb1d4c994130c2102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e0c2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd620c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20c2103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699140b413073b3bb030057040000000000000002000000abec5362f11e75b6e02e407bb98d63675d14384100000000000000003e5f0d0000000000b00400000001abec5362f11e75b6e02e407bb98d63675d14384101590218ddf5050c14316e851039019d39dfc2c37d6c3fee19fd5809870c14abec5362f11e75b6e02e407bb98d63675d14384113c00c087472616e736665720c14897720d8cd76f4f00abfa37c0edd889c208fde9b41627d5b523801fd08010c402d96d8fde4ba266f89bc71ef117361967e0d11ed84cd60942a27bc99994dc58adf36a0e74ce976aac657a87a3c19c38e8ca450c67420046b81d98c60fd8feb040c40b3c15d5d23e0403a36cf559caee2979ca6ef00fe255df0e5c3daac4da051016b41eba42668934cd3308359451bafdd5419d059179fd40859684a3b91388bf9d80c407ac048cf8540b091955a374a0f36dae560c92c0134886507a589edf58b9dfbb4e3dbd5450be34e269d2e5454eb14eb7d6280d6101b4529410f829d37634849be0c403bba4113a687ff8507c1753f8519557531cf9df51ecc20deeb2c2b003ec5a1f7588cdd50b99e40b4f8039bb56c5df7ec9e7d6ea4b02fe23792510da21c7557f394130c2102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e0c2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd620c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20c2103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699140b413073b3bb0003000000abec5362f11e75b6e02e407bb98d63675d1438410000000000000000de6e0d0000000000b00400000001abec5362f11e75b6e02e407bb98d63675d143841015d0300e87648170000000c14316e851039019d39dfc2c37d6c3fee19fd5809870c14abec5362f11e75b6e02e407bb98d63675d14384113c00c087472616e736665720c143b7d3711c6f0ccf9b1dca903d1bfa1d896f1238c41627d5b523801fd08010c4063fb12aa9f3fb83f6324ea9c7ec11fa9e995b51140f480409d68cf4d625e598b0632d6610602984bfa2f5e5ea9bcc62a0e6d818dd271b38530c0d1b8a71b4e0c0c4013e091eac6f304668d647c5c032fd1020597ea5204545e21c38655a6343d58492118f1231ede91af848af7e1d987d1a8816966f5fc1a7821c6c6f62734267bde0c40daadd04a7a4141d96c58de2d373e672ca071e2b82138ef52df016ac522710385db2ac73743d2fe73061fa5d6cb0ff73a7ec7f0667e4c8bff6aa0d5783128d36e0c40dab85cd87d3f92be9532292bdc6f420b0ecbf2f877c70c6a9921ee0fc900dfc53998cf020a51fa9af3d0608f6a2b9048cea3c0b586485802bbd278b261eee8a494130c2102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e0c2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd620c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20c2103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699140b413073b3bb" -const hexTxMoveNeo = "0002000000abec5362f11e75b6e02e407bb98d63675d14384100000000000000000e670d0000000000b00400000001abec5362f11e75b6e02e407bb98d63675d14384101590218ddf5050c14316e851039019d39dfc2c37d6c3fee19fd5809870c14abec5362f11e75b6e02e407bb98d63675d14384113c00c087472616e736665720c14897720d8cd76f4f00abfa37c0edd889c208fde9b41627d5b5238000001fd08010c4015b24aa11983bbf098384be4ebf5c283c3b4b2d2f6bf17b1a2a32f59627c7eb6370748b231acce2eb1ab5db3cdbf6943084634d12f69bf7b0aa447f96ebaf7d40c40a6777566463018e3f82fbbd370eef65b8454e50978401d1d97df05d9eda3b2bd5f5f882a94f8adbeaa2a55f64bd4ec23398fca26e8b364e5f57c771d71b3ec3d0c4032f5b1e3af669f4f14c2579de8f7ce46e30b35f7ed70892389251d50779477d2506b330dc9dd47f8c406218656d60b669479433bd9f762888091dc94415de5690c404b6ca943c34be335466c25ed442d17abc24d6a78db407a8c2a2c43fb911f0cbdbb28ec791b5f9de01b2db26105aa35193113a3a382c1ed02fbaf82b42468853a94130c2102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e0c2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd620c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20c2103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699140b413073b3bb" +const hexTxMoveNeo = "0002000000abec5362f11e75b6e02e407bb98d63675d14384100000000000000003e5f0d0000000000b00400000001abec5362f11e75b6e02e407bb98d63675d14384101590218ddf5050c14316e851039019d39dfc2c37d6c3fee19fd5809870c14abec5362f11e75b6e02e407bb98d63675d14384113c00c087472616e736665720c14897720d8cd76f4f00abfa37c0edd889c208fde9b41627d5b523801fd08010c402d96d8fde4ba266f89bc71ef117361967e0d11ed84cd60942a27bc99994dc58adf36a0e74ce976aac657a87a3c19c38e8ca450c67420046b81d98c60fd8feb040c40b3c15d5d23e0403a36cf559caee2979ca6ef00fe255df0e5c3daac4da051016b41eba42668934cd3308359451bafdd5419d059179fd40859684a3b91388bf9d80c407ac048cf8540b091955a374a0f36dae560c92c0134886507a589edf58b9dfbb4e3dbd5450be34e269d2e5454eb14eb7d6280d6101b4529410f829d37634849be0c403bba4113a687ff8507c1753f8519557531cf9df51ecc20deeb2c2b003ec5a1f7588cdd50b99e40b4f8039bb56c5df7ec9e7d6ea4b02fe23792510da21c7557f394130c2102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e0c2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd620c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20c2103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699140b413073b3bb" -const b1Verbose = `{"id":5,"jsonrpc":"2.0","result":{"size":1685,"nextblockhash":"0x14a61952de5bf47e2550bb97439de44ea60f79e052419e8b263b1b41d7065b0f","confirmations":4,"hash":"0xc826db8aa7a05fbd336eb0fca66efea7330cdc09cc8cf8e3cd9a3d9a87b751ac","version":0,"previousblockhash":"0x2d007892ec95e946aeb484b65767ab4bc0684e9ed49a4b62f20d336f0d900914","merkleroot":"0x17e2fa2759c5347a7b7e188adb5016443d128d05e651fbe02adb22393bdaa56a","time":1591360099001,"index":1,"nextconsensus":"AXSvJVzydxXuL9da4GVwK25zdesCrVKkHL","witnesses":[{"invocation":"0c40bac8992a77bd21ba670f2bf5097387a42b227878b361c69bfeeeb55c4b68bdff7db5c93b8f6d84876e473bba84bf27dc7de8d35b8179e120a60a6bc01562ac740c401c876fdb2fbffc599ac9ffbc85f7e6087855fd40e12b23888718e381c93de2614cce5bdfb1108ff72a73b85d4a6556dad6578a59bfa0e61b93c775cb1c1924f20c40fd992b9d776da1d2da390915e743f4213ce8a6db862b6354cccbcb3bf8b4edd14562cb546cbbcb3e2d096c9e527d4ee7879c5bbfd01d9a2bb00a1986820e1c320c40fcf3d76b809078a872970bd3bde5836589a7f62660098bbfb82a1cb470b75cc480d527a3829de89c897bacc6c29dfc3e4b84368aa1f69c9bce704fb3399fc04e","verification":"130c2102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e0c2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd620c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20c2103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699140b413073b3bb"}],"consensus_data":{"primary":0,"nonce":"0000000000000457"},"tx":[{"txid":"0xd24f8ab43462f8a2f788fa9073b8b32b4417aeddea19dfcc8dfb543d68e90de5","size":577,"version":0,"nonce":2,"sender":"AXSvJVzydxXuL9da4GVwK25zdesCrVKkHL","sys_fee":"0","net_fee":"0.0087835","valid_until_block":1200,"attributes":[],"cosigners":[{"account":"0x4138145d67638db97b402ee0b6751ef16253ecab","scopes":1}],"script":"0218ddf5050c14316e851039019d39dfc2c37d6c3fee19fd5809870c14abec5362f11e75b6e02e407bb98d63675d14384113c00c087472616e736665720c14897720d8cd76f4f00abfa37c0edd889c208fde9b41627d5b5238","vin":[],"vout":[],"scripts":[{"invocation":"0c4015b24aa11983bbf098384be4ebf5c283c3b4b2d2f6bf17b1a2a32f59627c7eb6370748b231acce2eb1ab5db3cdbf6943084634d12f69bf7b0aa447f96ebaf7d40c40a6777566463018e3f82fbbd370eef65b8454e50978401d1d97df05d9eda3b2bd5f5f882a94f8adbeaa2a55f64bd4ec23398fca26e8b364e5f57c771d71b3ec3d0c4032f5b1e3af669f4f14c2579de8f7ce46e30b35f7ed70892389251d50779477d2506b330dc9dd47f8c406218656d60b669479433bd9f762888091dc94415de5690c404b6ca943c34be335466c25ed442d17abc24d6a78db407a8c2a2c43fb911f0cbdbb28ec791b5f9de01b2db26105aa35193113a3a382c1ed02fbaf82b42468853a","verification":"130c2102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e0c2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd620c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20c2103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699140b413073b3bb"}]},{"txid":"0xf3304d751f7f6e871a610644529aa4f8fcc60a31592352eea54b86be472614f1","size":581,"version":0,"nonce":3,"sender":"AXSvJVzydxXuL9da4GVwK25zdesCrVKkHL","sys_fee":"0","net_fee":"0.0088235","valid_until_block":1200,"attributes":[],"cosigners":[{"account":"0x4138145d67638db97b402ee0b6751ef16253ecab","scopes":1}],"script":"0300e87648170000000c14316e851039019d39dfc2c37d6c3fee19fd5809870c14abec5362f11e75b6e02e407bb98d63675d14384113c00c087472616e736665720c143b7d3711c6f0ccf9b1dca903d1bfa1d896f1238c41627d5b5238","vin":[],"vout":[],"scripts":[{"invocation":"0c4001c81faa8317a390c211d5e03451ed852ff02ec6c401c450558bc90c60a01912c3e1018de98e7458f6f96c68aad71ffb0e92327fcdfa4aabb5ea5834ec7afbf10c40a84e9bc36ffbf18a1ee79254182d2939dd3a7b9278e13893856f187ab44dec259c8a15d4f449a21aa6970234d79d81fee0aca1807341b977ff66d503a78c82920c4085495bb8d86b95a4afc1659ce1d993e1a7843e3dcb19696ce0422294dadddc73438780d5bc629560f576e0e75cff062c03e237d4e609dfaa9869135e23a487650c40ae25f2c563b978f931c3a8b5a18854d9bb77abf48c7554f2008f97696caca180cd40d4d0e47b3f4d86082e631547d1a4729c7ed60dda64fab9cd9a2270dd1132","verification":"130c2102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e0c2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd620c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20c2103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699140b413073b3bb"}]}]}}` +const b1Verbose = `{"id":5,"jsonrpc":"2.0","result":{"size":1681,"nextblockhash":"0xf2afe371a27c9dbac4f4a8ad8eba750898b7c04aa298e64fe9e488e947976045","confirmations":4,"hash":"0xbd178d8d4a28ec082c034f817ce2423221281a31e7e00014dbf732c4053033d2","version":0,"previousblockhash":"0x8f3b2c628ae86f037a735ec477932c81b8ae54b7abb3dd58cd87c97f90e762e8","merkleroot":"0x95831633b36588acf0e69f37f73d1a84cb0c5329790e837072206ba8842e1f30","time":1591366176001,"index":1,"nextconsensus":"AXSvJVzydxXuL9da4GVwK25zdesCrVKkHL","witnesses":[{"invocation":"0c40ab634ce91590e77b246cee8b204e8a270268ee1ef32434cece73f425a7dbc90f1bed1dbe914edcaa2653167ad170ae10e16a9b2c6b7e0af1f711fb848fbb1b7f0c40232de6ad07ee3846bafa96302d37602349501a556df575e7df0743e45b076d6a0c6c6dd4cad3898f9e8848dd054abd303b229fd12984042f241f0e668f39a0fb0c408b4af43057df189a9d471010b5150bab442040403147c5e502bda38cde3ff8bce803f01245e07e2bfb95d57349c55dcc27e3710b82f2735d0f40eb4342908e330c40cda66f743d4ed8d856f5376953f9169581c668a9370245aef16202ebef9bb3f7f81234be62ec287d701ad7d8bf5042648019af9fe5baa0a8e05d279bfdb1d4c9","verification":"130c2102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e0c2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd620c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20c2103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699140b413073b3bb"}],"consensus_data":{"primary":0,"nonce":"0000000000000457"},"tx":[{"txid":"0x8af9ccb8e7e0f0a73e77b78dc52750e77c50f78b09ecc2f0669c0b459cc7dd89","size":575,"version":0,"nonce":2,"sender":"AXSvJVzydxXuL9da4GVwK25zdesCrVKkHL","sys_fee":"0","net_fee":"0.0087635","valid_until_block":1200,"attributes":[],"cosigners":[{"account":"0x4138145d67638db97b402ee0b6751ef16253ecab","scopes":1}],"script":"0218ddf5050c14316e851039019d39dfc2c37d6c3fee19fd5809870c14abec5362f11e75b6e02e407bb98d63675d14384113c00c087472616e736665720c14897720d8cd76f4f00abfa37c0edd889c208fde9b41627d5b5238","scripts":[{"invocation":"0c402d96d8fde4ba266f89bc71ef117361967e0d11ed84cd60942a27bc99994dc58adf36a0e74ce976aac657a87a3c19c38e8ca450c67420046b81d98c60fd8feb040c40b3c15d5d23e0403a36cf559caee2979ca6ef00fe255df0e5c3daac4da051016b41eba42668934cd3308359451bafdd5419d059179fd40859684a3b91388bf9d80c407ac048cf8540b091955a374a0f36dae560c92c0134886507a589edf58b9dfbb4e3dbd5450be34e269d2e5454eb14eb7d6280d6101b4529410f829d37634849be0c403bba4113a687ff8507c1753f8519557531cf9df51ecc20deeb2c2b003ec5a1f7588cdd50b99e40b4f8039bb56c5df7ec9e7d6ea4b02fe23792510da21c7557f3","verification":"130c2102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e0c2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd620c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20c2103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699140b413073b3bb"}]},{"txid":"0xe7cff9e4820e53232dae619a3e6f57a9430dc240b5ed7b5c0ea2cfee3e90c985","size":579,"version":0,"nonce":3,"sender":"AXSvJVzydxXuL9da4GVwK25zdesCrVKkHL","sys_fee":"0","net_fee":"0.0088035","valid_until_block":1200,"attributes":[],"cosigners":[{"account":"0x4138145d67638db97b402ee0b6751ef16253ecab","scopes":1}],"script":"0300e87648170000000c14316e851039019d39dfc2c37d6c3fee19fd5809870c14abec5362f11e75b6e02e407bb98d63675d14384113c00c087472616e736665720c143b7d3711c6f0ccf9b1dca903d1bfa1d896f1238c41627d5b5238","scripts":[{"invocation":"0c4063fb12aa9f3fb83f6324ea9c7ec11fa9e995b51140f480409d68cf4d625e598b0632d6610602984bfa2f5e5ea9bcc62a0e6d818dd271b38530c0d1b8a71b4e0c0c4013e091eac6f304668d647c5c032fd1020597ea5204545e21c38655a6343d58492118f1231ede91af848af7e1d987d1a8816966f5fc1a7821c6c6f62734267bde0c40daadd04a7a4141d96c58de2d373e672ca071e2b82138ef52df016ac522710385db2ac73743d2fe73061fa5d6cb0ff73a7ec7f0667e4c8bff6aa0d5783128d36e0c40dab85cd87d3f92be9532292bdc6f420b0ecbf2f877c70c6a9921ee0fc900dfc53998cf020a51fa9af3d0608f6a2b9048cea3c0b586485802bbd278b261eee8a4","verification":"130c2102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e0c2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd620c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20c2103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699140b413073b3bb"}]}]}}` -const hexHeader1 = "000000001409900d6f330df2624b9ad49e4e68c04bab6757b684b4ae46e995ec9278002d6aa5da3b3922db2ae0fb51e6058d123d441650db8a187e7b7a34c55927fae217b91274847201000001000000abec5362f11e75b6e02e407bb98d63675d14384101fd08010c40bac8992a77bd21ba670f2bf5097387a42b227878b361c69bfeeeb55c4b68bdff7db5c93b8f6d84876e473bba84bf27dc7de8d35b8179e120a60a6bc01562ac740c401c876fdb2fbffc599ac9ffbc85f7e6087855fd40e12b23888718e381c93de2614cce5bdfb1108ff72a73b85d4a6556dad6578a59bfa0e61b93c775cb1c1924f20c40fd992b9d776da1d2da390915e743f4213ce8a6db862b6354cccbcb3bf8b4edd14562cb546cbbcb3e2d096c9e527d4ee7879c5bbfd01d9a2bb00a1986820e1c320c40fcf3d76b809078a872970bd3bde5836589a7f62660098bbfb82a1cb470b75cc480d527a3829de89c897bacc6c29dfc3e4b84368aa1f69c9bce704fb3399fc04e94130c2102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e0c2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd620c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20c2103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699140b413073b3bb00" +const hexHeader1 = "00000000e862e7907fc987cd58ddb3abb754aeb8812c9377c45e737a036fe88a622c3b8f301f2e84a86b207270830e7929530ccb841a3df7379fe6f0ac8865b33316839501cdd0847201000001000000abec5362f11e75b6e02e407bb98d63675d14384101fd08010c40ab634ce91590e77b246cee8b204e8a270268ee1ef32434cece73f425a7dbc90f1bed1dbe914edcaa2653167ad170ae10e16a9b2c6b7e0af1f711fb848fbb1b7f0c40232de6ad07ee3846bafa96302d37602349501a556df575e7df0743e45b076d6a0c6c6dd4cad3898f9e8848dd054abd303b229fd12984042f241f0e668f39a0fb0c408b4af43057df189a9d471010b5150bab442040403147c5e502bda38cde3ff8bce803f01245e07e2bfb95d57349c55dcc27e3710b82f2735d0f40eb4342908e330c40cda66f743d4ed8d856f5376953f9169581c668a9370245aef16202ebef9bb3f7f81234be62ec287d701ad7d8bf5042648019af9fe5baa0a8e05d279bfdb1d4c994130c2102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e0c2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd620c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20c2103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699140b413073b3bb00" -const header1Verbose = `{"id":5,"jsonrpc":"2.0","result":{"hash":"0xc826db8aa7a05fbd336eb0fca66efea7330cdc09cc8cf8e3cd9a3d9a87b751ac","size":518,"version":0,"previousblockhash":"0x2d007892ec95e946aeb484b65767ab4bc0684e9ed49a4b62f20d336f0d900914","merkleroot":"0x17e2fa2759c5347a7b7e188adb5016443d128d05e651fbe02adb22393bdaa56a","time":1591360099001,"index":1,"nextconsensus":"AXSvJVzydxXuL9da4GVwK25zdesCrVKkHL","witnesses":[{"invocation":"0c40bac8992a77bd21ba670f2bf5097387a42b227878b361c69bfeeeb55c4b68bdff7db5c93b8f6d84876e473bba84bf27dc7de8d35b8179e120a60a6bc01562ac740c401c876fdb2fbffc599ac9ffbc85f7e6087855fd40e12b23888718e381c93de2614cce5bdfb1108ff72a73b85d4a6556dad6578a59bfa0e61b93c775cb1c1924f20c40fd992b9d776da1d2da390915e743f4213ce8a6db862b6354cccbcb3bf8b4edd14562cb546cbbcb3e2d096c9e527d4ee7879c5bbfd01d9a2bb00a1986820e1c320c40fcf3d76b809078a872970bd3bde5836589a7f62660098bbfb82a1cb470b75cc480d527a3829de89c897bacc6c29dfc3e4b84368aa1f69c9bce704fb3399fc04e","verification":"130c2102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e0c2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd620c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20c2103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699140b413073b3bb"}],"confirmations":6,"nextblockhash":"0x14a61952de5bf47e2550bb97439de44ea60f79e052419e8b263b1b41d7065b0f"}}` +const header1Verbose = `{"id":5,"jsonrpc":"2.0","result":{"hash":"0xbd178d8d4a28ec082c034f817ce2423221281a31e7e00014dbf732c4053033d2","size":518,"version":0,"previousblockhash":"0x8f3b2c628ae86f037a735ec477932c81b8ae54b7abb3dd58cd87c97f90e762e8","merkleroot":"0x95831633b36588acf0e69f37f73d1a84cb0c5329790e837072206ba8842e1f30","time":1591366176001,"index":1,"nextconsensus":"AXSvJVzydxXuL9da4GVwK25zdesCrVKkHL","witnesses":[{"invocation":"0c40ab634ce91590e77b246cee8b204e8a270268ee1ef32434cece73f425a7dbc90f1bed1dbe914edcaa2653167ad170ae10e16a9b2c6b7e0af1f711fb848fbb1b7f0c40232de6ad07ee3846bafa96302d37602349501a556df575e7df0743e45b076d6a0c6c6dd4cad3898f9e8848dd054abd303b229fd12984042f241f0e668f39a0fb0c408b4af43057df189a9d471010b5150bab442040403147c5e502bda38cde3ff8bce803f01245e07e2bfb95d57349c55dcc27e3710b82f2735d0f40eb4342908e330c40cda66f743d4ed8d856f5376953f9169581c668a9370245aef16202ebef9bb3f7f81234be62ec287d701ad7d8bf5042648019af9fe5baa0a8e05d279bfdb1d4c9","verification":"130c2102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e0c2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd620c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20c2103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699140b413073b3bb"}],"confirmations":6,"nextblockhash":"0xf2afe371a27c9dbac4f4a8ad8eba750898b7c04aa298e64fe9e488e947976045"}}` -const txMoveNeoVerbose = `{"id":5,"jsonrpc":"2.0","result":{"blockhash":"0xc826db8aa7a05fbd336eb0fca66efea7330cdc09cc8cf8e3cd9a3d9a87b751ac","confirmations":6,"blocktime":1591360099001,"txid":"0xd24f8ab43462f8a2f788fa9073b8b32b4417aeddea19dfcc8dfb543d68e90de5","size":577,"version":0,"nonce":2,"sender":"AXSvJVzydxXuL9da4GVwK25zdesCrVKkHL","sys_fee":"0","net_fee":"0.0087835","valid_until_block":1200,"attributes":[],"cosigners":[{"account":"0x4138145d67638db97b402ee0b6751ef16253ecab","scopes":1}],"script":"0218ddf5050c14316e851039019d39dfc2c37d6c3fee19fd5809870c14abec5362f11e75b6e02e407bb98d63675d14384113c00c087472616e736665720c14897720d8cd76f4f00abfa37c0edd889c208fde9b41627d5b5238","vin":[],"vout":[],"scripts":[{"invocation":"0c4015b24aa11983bbf098384be4ebf5c283c3b4b2d2f6bf17b1a2a32f59627c7eb6370748b231acce2eb1ab5db3cdbf6943084634d12f69bf7b0aa447f96ebaf7d40c40a6777566463018e3f82fbbd370eef65b8454e50978401d1d97df05d9eda3b2bd5f5f882a94f8adbeaa2a55f64bd4ec23398fca26e8b364e5f57c771d71b3ec3d0c4032f5b1e3af669f4f14c2579de8f7ce46e30b35f7ed70892389251d50779477d2506b330dc9dd47f8c406218656d60b669479433bd9f762888091dc94415de5690c404b6ca943c34be335466c25ed442d17abc24d6a78db407a8c2a2c43fb911f0cbdbb28ec791b5f9de01b2db26105aa35193113a3a382c1ed02fbaf82b42468853a","verification":"130c2102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e0c2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd620c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20c2103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699140b413073b3bb"}]}}` +const txMoveNeoVerbose = `{"id":5,"jsonrpc":"2.0","result":{"blockhash":"0xbd178d8d4a28ec082c034f817ce2423221281a31e7e00014dbf732c4053033d2","confirmations":6,"blocktime":1591366176001,"txid":"0x8af9ccb8e7e0f0a73e77b78dc52750e77c50f78b09ecc2f0669c0b459cc7dd89","size":575,"version":0,"nonce":2,"sender":"AXSvJVzydxXuL9da4GVwK25zdesCrVKkHL","sys_fee":"0","net_fee":"0.0087635","valid_until_block":1200,"attributes":[],"cosigners":[{"account":"0x4138145d67638db97b402ee0b6751ef16253ecab","scopes":1}],"script":"0218ddf5050c14316e851039019d39dfc2c37d6c3fee19fd5809870c14abec5362f11e75b6e02e407bb98d63675d14384113c00c087472616e736665720c14897720d8cd76f4f00abfa37c0edd889c208fde9b41627d5b5238","scripts":[{"invocation":"0c402d96d8fde4ba266f89bc71ef117361967e0d11ed84cd60942a27bc99994dc58adf36a0e74ce976aac657a87a3c19c38e8ca450c67420046b81d98c60fd8feb040c40b3c15d5d23e0403a36cf559caee2979ca6ef00fe255df0e5c3daac4da051016b41eba42668934cd3308359451bafdd5419d059179fd40859684a3b91388bf9d80c407ac048cf8540b091955a374a0f36dae560c92c0134886507a589edf58b9dfbb4e3dbd5450be34e269d2e5454eb14eb7d6280d6101b4529410f829d37634849be0c403bba4113a687ff8507c1753f8519557531cf9df51ecc20deeb2c2b003ec5a1f7588cdd50b99e40b4f8039bb56c5df7ec9e7d6ea4b02fe23792510da21c7557f3","verification":"130c2102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e0c2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd620c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20c2103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699140b413073b3bb"}]}}` // getResultBlock1 returns data for block number 1 which is used by several tests. func getResultBlock1() *result.Block { @@ -54,14 +54,14 @@ func getResultBlock1() *result.Block { if err != nil { panic(err) } - b2Hash, err := util.Uint256DecodeStringLE("14a61952de5bf47e2550bb97439de44ea60f79e052419e8b263b1b41d7065b0f") + b2Hash, err := util.Uint256DecodeStringLE("f2afe371a27c9dbac4f4a8ad8eba750898b7c04aa298e64fe9e488e947976045") if err != nil { panic(err) } return &result.Block{ Block: b, BlockMetadata: result.BlockMetadata{ - Size: 1685, + Size: 1681, NextBlockHash: &b2Hash, Confirmations: 4, }, diff --git a/pkg/rpc/client/wsclient_test.go b/pkg/rpc/client/wsclient_test.go index 445eb05e8..6050c35f3 100644 --- a/pkg/rpc/client/wsclient_test.go +++ b/pkg/rpc/client/wsclient_test.go @@ -117,8 +117,8 @@ func TestWSClientEvents(t *testing.T) { var events = []string{ `{"jsonrpc":"2.0","method":"transaction_executed","params":[{"txid":"0xe1cd5e57e721d2a2e05fb1f08721b12057b25ab1dd7fd0f33ee1639932fdfad7","executions":[{"trigger":"Application","contract":"0x0000000000000000000000000000000000000000","vmstate":"HALT","gas_consumed":"2.291","stack":[],"notifications":[{"contract":"0x1b4357bff5a01bdf2a6581247cf9ed1e24629176","state":{"type":"Array","value":[{"type":"ByteArray","value":"636f6e74726163742063616c6c"},{"type":"ByteArray","value":"7472616e73666572"},{"type":"Array","value":[{"type":"ByteArray","value":"769162241eedf97c2481652adf1ba0f5bf57431b"},{"type":"ByteArray","value":"316e851039019d39dfc2c37d6c3fee19fd580987"},{"type":"Integer","value":"1000"}]}]}},{"contract":"0x1b4357bff5a01bdf2a6581247cf9ed1e24629176","state":{"type":"Array","value":[{"type":"ByteArray","value":"7472616e73666572"},{"type":"ByteArray","value":"769162241eedf97c2481652adf1ba0f5bf57431b"},{"type":"ByteArray","value":"316e851039019d39dfc2c37d6c3fee19fd580987"},{"type":"Integer","value":"1000"}]}}]}]}]}`, `{"jsonrpc":"2.0","method":"notification_from_execution","params":[{"contract":"0x1b4357bff5a01bdf2a6581247cf9ed1e24629176","state":{"type":"Array","value":[{"type":"ByteArray","value":"636f6e74726163742063616c6c"},{"type":"ByteArray","value":"7472616e73666572"},{"type":"Array","value":[{"type":"ByteArray","value":"769162241eedf97c2481652adf1ba0f5bf57431b"},{"type":"ByteArray","value":"316e851039019d39dfc2c37d6c3fee19fd580987"},{"type":"Integer","value":"1000"}]}]}}]}`, - `{"jsonrpc":"2.0","method":"transaction_added","params":[{"txid":"0xe1e0200a69f3096010c75dd003653e5bd945e414d0b0a3b95e3dfe291534c8e5","size":267,"version":0,"nonce":9,"sender":"ALHF9wsXZVEuCGgmDA6ZNsCLtrb4A1g4yG","sys_fee":"0","net_fee":"0.0036721","valid_until_block":1200,"attributes":[],"cosigners":[{"account":"0x870958fd19ee3f6c7dc3c2df399d013910856e31","scopes":1}],"script":"007b0c1420728274afafc36f43a071d328cfa3e629d9cbb00c14316e851039019d39dfc2c37d6c3fee19fd58098713c00c087472616e736665720c14769162241eedf97c2481652adf1ba0f5bf57431b41627d5b5238","vin":[],"vout":[],"scripts":[{"invocation":"0c40b61d89290451852143490194e09a547d79b8b6cda05691c085160cc0ddebc6e3a508defae7ac04e015c85af6b6fcb487a954c2a884d4cc147c9959f776844b3c","verification":"0c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20b410a906ad4"}]}]}`, - `{"jsonrpc":"2.0","method":"block_added","params":[{"hash":"0x73f4157bc918f0af115522380b13dadf505773f91e818288edb0de4fcce104b4","version":0,"previousblockhash":"0x3c664cf156f2f418e92fd24621ac3b56da4a4c1e56c443fe360d52324d8f060f","merkleroot":"0xfa9e8e7a506c1a38fa1f090237156debd055c8cf41d743ae4f37fe3c278ff2e0","time":1591360099006,"index":6,"nextconsensus":"AXSvJVzydxXuL9da4GVwK25zdesCrVKkHL","witnesses":[{"invocation":"0c40d7690b2335898b192d408f3565fb8da0f994a305999f1b7b87000934831f76d680442ea2c44200c2b154c12a0ee587046eeec45f749b73ce3bc97ac172487f350c400835fd349d184a691087b24a827d82bad3026ffa0e7f2841e85fb91f5c9549e6a1430883586cbbfba3a450a0198608e19c0b1630677bbd9495e3f48c8c4835c40c400fd2d4dfee36f99de6df35b1c857eb7c8b9b26574a781114081b066b806a1bcae129d05329298b0e6b4728da90928d4a375157dd7472fb37351a20d1a84996790c404b58d5f6374bf6c2ab12f51e6f78a07852e027279879a5fb25b5e6371ad9d89749127e7b8f8eae3df45bfe187ae226aa1aeead061006da7c4e665d97950c9a3e","verification":"130c2102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e0c2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd620c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20c2103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699140b413073b3bb"}],"consensus_data":{"primary":0,"nonce":"0000000000000457"},"tx":[{"txid":"0xe1e0200a69f3096010c75dd003653e5bd945e414d0b0a3b95e3dfe291534c8e5","size":267,"version":0,"nonce":9,"sender":"ALHF9wsXZVEuCGgmDA6ZNsCLtrb4A1g4yG","sys_fee":"0","net_fee":"0.0036721","valid_until_block":1200,"attributes":[],"cosigners":[{"account":"0x870958fd19ee3f6c7dc3c2df399d013910856e31","scopes":1}],"script":"007b0c1420728274afafc36f43a071d328cfa3e629d9cbb00c14316e851039019d39dfc2c37d6c3fee19fd58098713c00c087472616e736665720c14769162241eedf97c2481652adf1ba0f5bf57431b41627d5b5238","vin":[],"vout":[],"scripts":[{"invocation":"0c40b61d89290451852143490194e09a547d79b8b6cda05691c085160cc0ddebc6e3a508defae7ac04e015c85af6b6fcb487a954c2a884d4cc147c9959f776844b3c","verification":"0c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20b410a906ad4"}]}]}]}`, + `{"jsonrpc":"2.0","method":"transaction_added","params":[{"txid":"0x1c615d4043c98fc0e285c2f40cc3601cf4ebe1cf9d2b404dfc67c9cd085444ec","size":265,"version":0,"nonce":9,"sender":"ALHF9wsXZVEuCGgmDA6ZNsCLtrb4A1g4yG","sys_fee":"0","net_fee":"0.0036521","valid_until_block":1200,"attributes":[],"cosigners":[{"account":"0x870958fd19ee3f6c7dc3c2df399d013910856e31","scopes":1}],"script":"007b0c1420728274afafc36f43a071d328cfa3e629d9cbb00c14316e851039019d39dfc2c37d6c3fee19fd58098713c00c087472616e736665720c14769162241eedf97c2481652adf1ba0f5bf57431b41627d5b5238","scripts":[{"invocation":"0c4034d02f3b97a220ffe79640e482b887ec0e44dcc95e719f5e2b43b29987f0c9822b9af0499d90094c6ad3ba191e434a3df5dd378d3b73318cf47c9f2d6d801cc8","verification":"0c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20b410a906ad4"}]}]}`, + `{"jsonrpc":"2.0","method":"block_added","params":[{"hash":"0x765ea65b4de6addfee29b1c90ac922d1901c8d7ab7f2366da9a8ad3dd71ca703","version":0,"previousblockhash":"0xbdeed527a43ab72d5d8cecf1dc6ee142112ff8a8eaaaebc7206d3df3bf3c1169","merkleroot":"0xa1b321f59b127cddd23b0cd47fc9ec7920647d30d7ab23318a106597b9c9abad","time":1591366176006,"index":6,"nextconsensus":"AXSvJVzydxXuL9da4GVwK25zdesCrVKkHL","witnesses":[{"invocation":"0c40da1f4b546a8a60e96596351234d7709391866bb3590a290133bc0c45837f1dac6351ee32506a7e0bbf6fcbcc3ec01222ccfe84bc1d4071221f4c432ebf569b620c40ee5906328012a8a4a411e7fa23aa8ba21fedb81b11581e5a287cad961fa36d2a20b2069549a5a14860d9e9ae3640ea20f9191d60ab7c2aeddf43edd6dabe558c0c40f5391e79e7d62f7ccaa900511d530f89de183fa51bc4af744bda81f763e14ddd7fb953e69b0901660d4752f240d5269344d0b64b50b124d1a316ad72486da15e0c40012f773faef2aee4af59e083b443ebe6cf404d12f49d32966c5f48f2c203e284429615aa2d34c827356d55c3be1612f67a5b725f6ff49b9b95b1f60306a72b71","verification":"130c2102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e0c2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd620c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20c2103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699140b413073b3bb"}],"consensus_data":{"primary":0,"nonce":"0000000000000457"},"tx":[{"txid":"0x1c615d4043c98fc0e285c2f40cc3601cf4ebe1cf9d2b404dfc67c9cd085444ec","size":265,"version":0,"nonce":9,"sender":"ALHF9wsXZVEuCGgmDA6ZNsCLtrb4A1g4yG","sys_fee":"0","net_fee":"0.0036521","valid_until_block":1200,"attributes":[],"cosigners":[{"account":"0x870958fd19ee3f6c7dc3c2df399d013910856e31","scopes":1}],"script":"007b0c1420728274afafc36f43a071d328cfa3e629d9cbb00c14316e851039019d39dfc2c37d6c3fee19fd58098713c00c087472616e736665720c14769162241eedf97c2481652adf1ba0f5bf57431b41627d5b5238","scripts":[{"invocation":"0c4034d02f3b97a220ffe79640e482b887ec0e44dcc95e719f5e2b43b29987f0c9822b9af0499d90094c6ad3ba191e434a3df5dd378d3b73318cf47c9f2d6d801cc8","verification":"0c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20b410a906ad4"}]}]}]}`, `{"jsonrpc":"2.0","method":"event_missed","params":[]}`, } srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { diff --git a/pkg/rpc/response/result/tx_output.go b/pkg/rpc/response/result/tx_output.go deleted file mode 100644 index 4078de755..000000000 --- a/pkg/rpc/response/result/tx_output.go +++ /dev/null @@ -1,27 +0,0 @@ -package result - -import ( - "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/util" -) - -// TransactionOutput is a wrapper to represent transaction's output. -type TransactionOutput struct { - N int `json:"n"` - Asset string `json:"asset"` - Value util.Fixed8 `json:"value"` - Address string `json:"address"` -} - -// NewTxOutput converts out to a TransactionOutput. -func NewTxOutput(out *transaction.Output) *TransactionOutput { - addr := address.Uint160ToString(out.ScriptHash) - - return &TransactionOutput{ - N: out.Position, - Asset: "0x" + out.AssetID.String(), - Value: out.Amount, - Address: addr, - } -} diff --git a/pkg/rpc/response/result/tx_raw_output.go b/pkg/rpc/response/result/tx_raw_output.go index ae47dda50..e3372019d 100644 --- a/pkg/rpc/response/result/tx_raw_output.go +++ b/pkg/rpc/response/result/tx_raw_output.go @@ -28,10 +28,6 @@ type TransactionMetadata struct { func NewTransactionOutputRaw(tx *transaction.Transaction, header *block.Header, chain blockchainer.Blockchainer) TransactionOutputRaw { // confirmations formula confirmations := int(chain.BlockHeight() - header.Base.Index + 1) - // set index position - for i, o := range tx.Outputs { - o.Position = i - } return TransactionOutputRaw{ Transaction: tx, TransactionMetadata: TransactionMetadata{ diff --git a/pkg/rpc/server/server_test.go b/pkg/rpc/server/server_test.go index 81afdc448..ca1d11690 100644 --- a/pkg/rpc/server/server_test.go +++ b/pkg/rpc/server/server_test.go @@ -55,12 +55,12 @@ var rpcTestCases = map[string][]rpcTestCase{ "getapplicationlog": { { name: "positive", - params: `["2a6bf372fb96d05735eeb685805396818ac3f21e748528f4d6ebdecfd07ddce4"]`, + params: `["5878052c7e9843786d64a9aeab16e74fabffd5abad9a0404aaf4f4bf2b6213e9"]`, result: func(e *executor) interface{} { return &result.ApplicationLog{} }, check: func(t *testing.T, e *executor, acc interface{}) { res, ok := acc.(*result.ApplicationLog) require.True(t, ok) - expectedTxHash, err := util.Uint256DecodeStringLE("2a6bf372fb96d05735eeb685805396818ac3f21e748528f4d6ebdecfd07ddce4") + expectedTxHash, err := util.Uint256DecodeStringLE("5878052c7e9843786d64a9aeab16e74fabffd5abad9a0404aaf4f4bf2b6213e9") require.NoError(t, err) assert.Equal(t, expectedTxHash, res.TxHash) assert.Equal(t, 1, len(res.Executions)) @@ -484,7 +484,7 @@ var rpcTestCases = map[string][]rpcTestCase{ "gettransactionheight": { { name: "positive", - params: `["2a6bf372fb96d05735eeb685805396818ac3f21e748528f4d6ebdecfd07ddce4"]`, + params: `["5878052c7e9843786d64a9aeab16e74fabffd5abad9a0404aaf4f4bf2b6213e9"]`, result: func(e *executor) interface{} { h := 0 return &h @@ -678,7 +678,7 @@ var rpcTestCases = map[string][]rpcTestCase{ "sendrawtransaction": { { name: "positive", - params: `["000a000000316e851039019d39dfc2c37d6c3fee19fd5809870000000000000000c2b5050000000000b00400000001316e851039019d39dfc2c37d6c3fee19fd580987015d0300e87648170000000c1420728274afafc36f43a071d328cfa3e629d9cbb00c14316e851039019d39dfc2c37d6c3fee19fd58098713c00c087472616e736665720c14897720d8cd76f4f00abfa37c0edd889c208fde9b41627d5b5238000001420c4070b2b74b193b574fede47432a9bfa192726603a7f1ef6f6589f192943eb5978f47d25a7834ae7f42a0ebf4e013d1d1c2d1bb61417890335e9804ef26a94d2c00290c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20b410a906ad4"]`, + params: `["000a000000316e851039019d39dfc2c37d6c3fee19fd5809870000000000000000f2ad050000000000b00400000001316e851039019d39dfc2c37d6c3fee19fd580987015d0300e87648170000000c1420728274afafc36f43a071d328cfa3e629d9cbb00c14316e851039019d39dfc2c37d6c3fee19fd58098713c00c087472616e736665720c14897720d8cd76f4f00abfa37c0edd889c208fde9b41627d5b523801420c40df953141271169421cebab5d27a0163e294d7c7f2d0525b4498745344814fd3d6c5c591c9b1723d05d42856f409adb084cf67acc921cfafc629133a5eb5e7a7e290c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20b410a906ad4"]`, result: func(e *executor) interface{} { v := true return &v @@ -686,7 +686,7 @@ var rpcTestCases = map[string][]rpcTestCase{ }, { name: "negative", - params: `["000a000000316e851039019d39dfc2c37d6c3fee19fd5809870000000000000000c2b5050000000000b00400000001316e851039019d39dfc2c37d6c3fee19fd580987015d0300e87648170000000c1420728274afafc36f43a071d328cfa3e629d9cbb00c14316e851039019d39dfc2c37d6c3fee19fd58098713c00c087472616e736665720c14897720d8cd76f4f00abfa37c0edd889c208fde9b41627d5b5238000001420c4070b2b74b193b574fede47432a9bfa192726603a7f1ef6f6589f192943eb5978f47d25a7834ae7f42a0ebf4e013d1d1c2d1bb61417890335e9804ef26a94d2c00290c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20b410a906aff"]`, + params: `["000a000000316e851039019d39dfc2c37d6c3fee19fd5809870000000000000000f2ad050000000000b00400000001316e851039019d39dfc2c37d6c3fee19fd580987015d0300e87648170000000c1420728274afafc36f43a071d328cfa3e629d9cbb00c14316e851039019d39dfc2c37d6c3fee19fd58098713c00c087472616e736665720c14897720d8cd76f4f00abfa37c0edd889c208fde9b41627d5b523801420c40df953141271169421cebab5d27a0163e294d7c7f2d0525b4498745344814fd3d6c5c591c9b1723d05d42856f409adb084cf67acc921cfafc629133a5eb5e7a7e290c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20b410a906aff"]`, fail: true, }, { diff --git a/pkg/rpc/server/testdata/testblocks.acc b/pkg/rpc/server/testdata/testblocks.acc index c8d5926be..b24ef7a0e 100644 Binary files a/pkg/rpc/server/testdata/testblocks.acc and b/pkg/rpc/server/testdata/testblocks.acc differ diff --git a/pkg/smartcontract/context/context_test.go b/pkg/smartcontract/context/context_test.go index efa7e82ac..ecd26e3e1 100644 --- a/pkg/smartcontract/context/context_test.go +++ b/pkg/smartcontract/context/context_test.go @@ -166,15 +166,6 @@ func newParam(typ smartcontract.ParamType, name string) wallet.ContractParam { func getContractTx() *transaction.Transaction { tx := transaction.New([]byte{byte(opcode.PUSH1)}, 0) - tx.AddInput(&transaction.Input{ - PrevHash: util.Uint256{1, 2, 3, 4}, - PrevIndex: 5, - }) - tx.AddOutput(&transaction.Output{ - AssetID: util.Uint256{7, 8, 9}, - Amount: 10, - ScriptHash: util.Uint160{11, 12}, - }) tx.Attributes = make([]transaction.Attribute, 0) tx.Scripts = make([]transaction.Witness, 0) tx.Hash()