diff --git a/pkg/core/blockchain.go b/pkg/core/blockchain.go index 6aac93be0..06056de01 100644 --- a/pkg/core/blockchain.go +++ b/pkg/core/blockchain.go @@ -599,19 +599,6 @@ func (bc *Blockchain) storeBlock(block *block.Block) error { return err } - if prevTXOutput.AssetID.Equals(GoverningTokenID()) { - err = account.Unclaimed.Put(&state.UnclaimedBalance{ - Tx: input.PrevHash, - Index: input.PrevIndex, - Start: unspent.Height, - End: block.Index, - Value: prevTXOutput.Amount, - }) - if err != nil { - return err - } - } - balancesLen := len(account.Balances[prevTXOutput.AssetID]) if balancesLen <= 1 { delete(account.Balances, prevTXOutput.AssetID) @@ -669,54 +656,6 @@ func (bc *Blockchain) storeBlock(block *block.Block) error { } } } - case *transaction.ClaimTX: - // Remove claimed NEO from spent coins making it unavalaible for - // additional claims. - for _, input := range t.Claims { - scs, err := cache.GetUnspentCoinState(input.PrevHash) - if err == nil { - if len(scs.States) <= int(input.PrevIndex) { - err = errors.New("invalid claim index") - } else if scs.States[input.PrevIndex].State&state.CoinClaimed != 0 { - err = errors.New("double claim") - } - } - if err != nil { - // We can't really do anything about it - // as it's a transaction in a signed block. - bc.log.Warn("FALSE OR DOUBLE CLAIM", - zap.String("PrevHash", input.PrevHash.StringLE()), - zap.Uint16("PrevIndex", input.PrevIndex), - zap.String("tx", tx.Hash().StringLE()), - zap.Uint32("block", block.Index), - ) - // "Strict" mode. - if bc.config.VerifyTransactions { - return err - } - break - } - - acc, err := cache.GetAccountState(scs.States[input.PrevIndex].ScriptHash) - if err != nil { - return err - } - - scs.States[input.PrevIndex].State |= state.CoinClaimed - if err = cache.PutUnspentCoinState(input.PrevHash, scs); err != nil { - return err - } - - changed := acc.Unclaimed.Remove(input.PrevHash, input.PrevIndex) - if !changed { - bc.log.Warn("no spent coin in the account", - zap.String("tx", tx.Hash().StringLE()), - zap.String("input", input.PrevHash.StringLE()), - zap.String("account", acc.ScriptHash.String())) - } else if err := cache.PutAccountState(acc); err != nil { - return err - } - } case *transaction.InvocationTX: systemInterop := bc.newInteropContext(trigger.Application, cache, block, tx) v := SpawnVM(systemInterop) @@ -1383,87 +1322,9 @@ func (bc *Blockchain) verifyTx(t *transaction.Transaction, block *block.Block) e } } - switch t.Type { - case transaction.ClaimType: - claim := t.Data.(*transaction.ClaimTX) - if transaction.HaveDuplicateInputs(claim.Claims) { - return errors.New("duplicate claims") - } - if bc.dao.IsDoubleClaim(claim) { - return errors.New("double claim") - } - if err := bc.verifyClaims(t, results); err != nil { - return err - } - } - return bc.verifyTxWitnesses(t, block) } -func (bc *Blockchain) verifyClaims(tx *transaction.Transaction, results []*transaction.Result) (err error) { - t := tx.Data.(*transaction.ClaimTX) - var result *transaction.Result - for i := range results { - if results[i].AssetID == UtilityTokenID() { - result = results[i] - break - } - } - - if result == nil || result.Amount.GreaterThan(0) { - return errors.New("invalid output in claim tx") - } - - bonus, err := bc.calculateBonus(t.Claims) - if err == nil && bonus != -result.Amount { - return fmt.Errorf("wrong bonus calculated in claim tx: %s != %s", - bonus.String(), (-result.Amount).String()) - } - - return err -} - -func (bc *Blockchain) calculateBonus(claims []transaction.Input) (util.Fixed8, error) { - unclaimed := []*spentCoin{} - inputs := transaction.GroupInputsByPrevHash(claims) - - for _, group := range inputs { - h := group[0].PrevHash - unspent, err := bc.dao.GetUnspentCoinState(h) - if err != nil { - return 0, err - } - - for _, c := range group { - if len(unspent.States) <= int(c.PrevIndex) { - return 0, fmt.Errorf("can't find spent coins for %s (%d)", c.PrevHash.StringLE(), c.PrevIndex) - } - if unspent.States[c.PrevIndex].State&state.CoinSpent == 0 { - return 0, fmt.Errorf("not spent yet: %s/%d", c.PrevHash.StringLE(), c.PrevIndex) - } - if unspent.States[c.PrevIndex].State&state.CoinClaimed != 0 { - return 0, fmt.Errorf("already claimed: %s/%d", c.PrevHash.StringLE(), c.PrevIndex) - } - unclaimed = append(unclaimed, &spentCoin{ - Output: &unspent.States[c.PrevIndex].Output, - StartHeight: unspent.Height, - EndHeight: unspent.States[c.PrevIndex].SpendHeight, - }) - } - } - - return bc.calculateBonusInternal(unclaimed) -} - -func (bc *Blockchain) calculateBonusInternal(scs []*spentCoin) (util.Fixed8, error) { - var claimed util.Fixed8 - for _, sc := range scs { - claimed += bc.CalculateClaimable(sc.Output.Amount.IntegralValue(), sc.StartHeight, sc.EndHeight) - } - - return claimed, nil -} - // isTxStillRelevant is a callback for mempool transaction filtering after the // new block addition. It returns false for transactions already present in the // chain (added by the new block), transactions using some inputs that are @@ -1480,12 +1341,6 @@ func (bc *Blockchain) isTxStillRelevant(t *transaction.Transaction) bool { if bc.dao.IsDoubleSpend(t) { return false } - if t.Type == transaction.ClaimType { - claim := t.Data.(*transaction.ClaimTX) - if bc.dao.IsDoubleClaim(claim) { - return false - } - } for i := range t.Scripts { if !vm.IsStandardContract(t.Scripts[i].VerificationScript) { recheckWitness = true @@ -1521,14 +1376,12 @@ func (bc *Blockchain) PoolTx(t *transaction.Transaction) error { return err } // Policying. - if t.Type != transaction.ClaimType { - txSize := io.GetVarSize(t) - maxFree := bc.config.MaxFreeTransactionSize - if maxFree != 0 && txSize > maxFree { - if bc.IsLowPriority(t.NetworkFee) || - t.NetworkFee < util.Fixed8FromFloat(bc.config.FeePerExtraByte)*util.Fixed8(txSize-maxFree) { - return ErrPolicy - } + txSize := io.GetVarSize(t) + maxFree := bc.config.MaxFreeTransactionSize + if maxFree != 0 && txSize > maxFree { + if bc.IsLowPriority(t.NetworkFee) || + t.NetworkFee < util.Fixed8FromFloat(bc.config.FeePerExtraByte)*util.Fixed8(txSize-maxFree) { + return ErrPolicy } } if err := bc.memPool.Add(t, bc); err != nil { @@ -1585,13 +1438,6 @@ func (bc *Blockchain) verifyResults(t *transaction.Transaction, results []*trans } switch t.Type { - case transaction.ClaimType: - for _, r := range resultsIssue { - if r.AssetID != UtilityTokenID() { - return errors.New("miner or claim tx issues non-utility tokens") - } - } - break case transaction.IssueType: for _, r := range resultsIssue { if r.AssetID == UtilityTokenID() { @@ -1701,15 +1547,6 @@ func (bc *Blockchain) GetScriptHashesForVerifying(t *transaction.Transaction) ([ hashes[c.Account] = true } switch t.Type { - case transaction.ClaimType: - claim := t.Data.(*transaction.ClaimTX) - refs, err := bc.references(claim.Claims) - if err != nil { - return nil, err - } - for i := range refs { - hashes[refs[i].Out.ScriptHash] = true - } case transaction.IssueType: for _, res := range refsAndOutsToResults(references, t.Outputs) { if res.Amount < 0 { diff --git a/pkg/core/dao/dao.go b/pkg/core/dao/dao.go index 5699b4d25..363aa9244 100644 --- a/pkg/core/dao/dao.go +++ b/pkg/core/dao/dao.go @@ -40,7 +40,6 @@ type DAO interface { GetVersion() (string, error) GetWrapped() DAO HasTransaction(hash util.Uint256) bool - IsDoubleClaim(claim *transaction.ClaimTX) bool IsDoubleSpend(tx *transaction.Transaction) bool Persist() (int, error) PutAccountState(as *state.Account) error @@ -573,11 +572,6 @@ func (dao *Simple) IsDoubleSpend(tx *transaction.Transaction) bool { return dao.checkUsedInputs(tx.Inputs, state.CoinSpent) } -// IsDoubleClaim verifies that given claim inputs are not already claimed by another tx. -func (dao *Simple) IsDoubleClaim(claim *transaction.ClaimTX) bool { - return dao.checkUsedInputs(claim.Claims, state.CoinClaimed) -} - func (dao *Simple) checkUsedInputs(inputs []transaction.Input, coin state.Coin) bool { if len(inputs) == 0 { return false diff --git a/pkg/core/mempool/mem_pool.go b/pkg/core/mempool/mem_pool.go index bd566936a..fdcee59eb 100644 --- a/pkg/core/mempool/mem_pool.go +++ b/pkg/core/mempool/mem_pool.go @@ -52,7 +52,6 @@ type Pool struct { verifiedMap map[util.Uint256]*item verifiedTxes items inputs []*transaction.Input - claims []*transaction.Input fees map[util.Uint160]utilityBalanceAndFees capacity int @@ -79,20 +78,6 @@ func (p *item) CompareTo(otherP *item) int { return -1 } - if p.isLowPrio && otherP.isLowPrio { - thisIsClaimTx := p.txn.Type == transaction.ClaimType - otherIsClaimTx := otherP.txn.Type == transaction.ClaimType - - if thisIsClaimTx != otherIsClaimTx { - // This is a claim Tx and other isn't. - if thisIsClaimTx { - return 1 - } - // The other is claim Tx and this isn't. - return -1 - } - } - // Fees sorted ascending. if ret := p.txn.FeePerByte().CompareTo(otherP.txn.FeePerByte()); ret != 0 { return ret @@ -249,12 +234,6 @@ func (mp *Pool) Add(t *transaction.Transaction, fee Feer) error { for i := range t.Inputs { pushInputToSortedSlice(&mp.inputs, &t.Inputs[i]) } - if t.Type == transaction.ClaimType { - claim := t.Data.(*transaction.ClaimTX) - for i := range claim.Claims { - pushInputToSortedSlice(&mp.claims, &claim.Claims[i]) - } - } updateMempoolMetrics(len(mp.verifiedTxes)) mp.lock.Unlock() @@ -284,12 +263,6 @@ func (mp *Pool) Remove(hash util.Uint256) { for i := range it.txn.Inputs { dropInputFromSortedSlice(&mp.inputs, &it.txn.Inputs[i]) } - if it.txn.Type == transaction.ClaimType { - claim := it.txn.Data.(*transaction.ClaimTX) - for i := range claim.Claims { - dropInputFromSortedSlice(&mp.claims, &claim.Claims[i]) - } - } } updateMempoolMetrics(len(mp.verifiedTxes)) mp.lock.Unlock() @@ -304,7 +277,6 @@ func (mp *Pool) RemoveStale(isOK func(*transaction.Transaction) bool, feer Feer) // because items are iterated one-by-one in increasing order. newVerifiedTxes := mp.verifiedTxes[:0] newInputs := mp.inputs[:0] - newClaims := mp.claims[: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) { @@ -312,12 +284,6 @@ func (mp *Pool) RemoveStale(isOK func(*transaction.Transaction) bool, feer Feer) for i := range itm.txn.Inputs { newInputs = append(newInputs, &itm.txn.Inputs[i]) } - if itm.txn.Type == transaction.ClaimType { - claim := itm.txn.Data.(*transaction.ClaimTX) - for i := range claim.Claims { - newClaims = append(newClaims, &claim.Claims[i]) - } - } } else { delete(mp.verifiedMap, itm.txn.Hash()) } @@ -325,12 +291,8 @@ func (mp *Pool) RemoveStale(isOK func(*transaction.Transaction) bool, feer Feer) sort.Slice(newInputs, func(i, j int) bool { return newInputs[i].Cmp(newInputs[j]) < 0 }) - sort.Slice(newClaims, func(i, j int) bool { - return newClaims[i].Cmp(newClaims[j]) < 0 - }) mp.verifiedTxes = newVerifiedTxes mp.inputs = newInputs - mp.claims = newClaims mp.lock.Unlock() } @@ -392,11 +354,6 @@ func (mp *Pool) checkTxConflicts(tx *transaction.Transaction, fee Feer) bool { return false } switch tx.Type { - case transaction.ClaimType: - claim := tx.Data.(*transaction.ClaimTX) - if areInputsInPool(claim.Claims, mp.claims) { - return false - } case transaction.IssueType: // It's a hack, because technically we could check for // available asset amount, but these transactions are so rare diff --git a/pkg/core/mempool/mem_pool_test.go b/pkg/core/mempool/mem_pool_test.go index c4dbfec75..843627082 100644 --- a/pkg/core/mempool/mem_pool_test.go +++ b/pkg/core/mempool/mem_pool_test.go @@ -55,7 +55,7 @@ func TestMemPoolAddRemove(t *testing.T) { t.Run("high priority", func(t *testing.T) { testMemPoolAddRemoveWithFeer(t, fs) }) } -func TestMemPoolAddRemoveWithInputsAndClaims(t *testing.T) { +func TestMemPoolAddRemoveWithInputs(t *testing.T) { mp := NewMemPool(50) hash1, err := util.Uint256DecodeStringBE("a83ba6ede918a501558d3170a124324aedc89909e64c4ff2c6f863094f980b25") require.NoError(t, err) @@ -64,62 +64,41 @@ func TestMemPoolAddRemoveWithInputsAndClaims(t *testing.T) { mpLessInputs := func(i, j int) bool { return mp.inputs[i].Cmp(mp.inputs[j]) < 0 } - mpLessClaims := func(i, j int) bool { - return mp.claims[i].Cmp(mp.claims[j]) < 0 - } txm1 := transaction.NewContractTX() txm1.Nonce = 1 - txc1, claim1 := newClaimTX() for i := 0; i < 5; i++ { txm1.Inputs = append(txm1.Inputs, transaction.Input{PrevHash: hash1, PrevIndex: uint16(100 - i)}) - claim1.Claims = append(claim1.Claims, transaction.Input{PrevHash: hash1, PrevIndex: uint16(100 - i)}) } require.NoError(t, mp.Add(txm1, &FeerStub{})) - require.NoError(t, mp.Add(txc1, &FeerStub{})) // Look inside. assert.Equal(t, len(txm1.Inputs), len(mp.inputs)) assert.True(t, sort.SliceIsSorted(mp.inputs, mpLessInputs)) - assert.Equal(t, len(claim1.Claims), len(mp.claims)) - assert.True(t, sort.SliceIsSorted(mp.claims, mpLessClaims)) txm2 := transaction.NewContractTX() txm2.Nonce = 1 - txc2, claim2 := newClaimTX() for i := 0; i < 10; i++ { txm2.Inputs = append(txm2.Inputs, transaction.Input{PrevHash: hash2, PrevIndex: uint16(i)}) - claim2.Claims = append(claim2.Claims, transaction.Input{PrevHash: hash2, PrevIndex: uint16(i)}) } require.NoError(t, mp.Add(txm2, &FeerStub{})) - require.NoError(t, mp.Add(txc2, &FeerStub{})) assert.Equal(t, len(txm1.Inputs)+len(txm2.Inputs), len(mp.inputs)) assert.True(t, sort.SliceIsSorted(mp.inputs, mpLessInputs)) - assert.Equal(t, len(claim1.Claims)+len(claim2.Claims), len(mp.claims)) - assert.True(t, sort.SliceIsSorted(mp.claims, mpLessClaims)) mp.Remove(txm1.Hash()) - mp.Remove(txc2.Hash()) assert.Equal(t, len(txm2.Inputs), len(mp.inputs)) assert.True(t, sort.SliceIsSorted(mp.inputs, mpLessInputs)) - assert.Equal(t, len(claim1.Claims), len(mp.claims)) - assert.True(t, sort.SliceIsSorted(mp.claims, mpLessClaims)) require.NoError(t, mp.Add(txm1, &FeerStub{})) - require.NoError(t, mp.Add(txc2, &FeerStub{})) assert.Equal(t, len(txm1.Inputs)+len(txm2.Inputs), len(mp.inputs)) assert.True(t, sort.SliceIsSorted(mp.inputs, mpLessInputs)) - assert.Equal(t, len(claim1.Claims)+len(claim2.Claims), len(mp.claims)) - assert.True(t, sort.SliceIsSorted(mp.claims, mpLessClaims)) mp.RemoveStale(func(t *transaction.Transaction) bool { - if t.Hash() == txc1.Hash() || t.Hash() == txm2.Hash() { + 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)) - assert.Equal(t, len(claim2.Claims), len(mp.claims)) - assert.True(t, sort.SliceIsSorted(mp.claims, mpLessClaims)) } func TestMemPoolVerifyInputs(t *testing.T) { @@ -149,33 +128,6 @@ func TestMemPoolVerifyInputs(t *testing.T) { require.Error(t, mp.Add(tx3, &FeerStub{})) } -func TestMemPoolVerifyClaims(t *testing.T) { - mp := NewMemPool(50) - tx1, claim1 := newClaimTX() - hash1, err := util.Uint256DecodeStringBE("a83ba6ede918a501558d3170a124324aedc89909e64c4ff2c6f863094f980b25") - require.NoError(t, err) - hash2, err := util.Uint256DecodeStringBE("629397158f852e838077bb2715b13a2e29b0a51c2157e5466321b70ed7904ce9") - require.NoError(t, err) - for i := 0; i < 10; i++ { - claim1.Claims = append(claim1.Claims, transaction.Input{PrevHash: hash1, PrevIndex: uint16(i)}) - claim1.Claims = append(claim1.Claims, transaction.Input{PrevHash: hash2, PrevIndex: uint16(i)}) - } - require.Equal(t, true, mp.Verify(tx1, &FeerStub{})) - require.NoError(t, mp.Add(tx1, &FeerStub{})) - - tx2, claim2 := newClaimTX() - for i := 0; i < 10; i++ { - claim2.Claims = append(claim2.Claims, transaction.Input{PrevHash: hash2, PrevIndex: uint16(i + 10)}) - } - require.Equal(t, true, mp.Verify(tx2, &FeerStub{})) - require.NoError(t, mp.Add(tx2, &FeerStub{})) - - tx3, claim3 := newClaimTX() - claim3.Claims = append(claim3.Claims, transaction.Input{PrevHash: hash1, PrevIndex: 0}) - require.Equal(t, false, mp.Verify(tx3, &FeerStub{})) - require.Error(t, mp.Add(tx3, &FeerStub{})) -} - func TestMemPoolVerifyIssue(t *testing.T) { mp := NewMemPool(50) tx1 := newIssueTX() @@ -199,11 +151,6 @@ func newIssueTX() *transaction.Transaction { return tx } -func newClaimTX() (*transaction.Transaction, *transaction.ClaimTX) { - cl := &transaction.ClaimTX{} - return transaction.NewClaimTX(cl), cl -} - func TestOverCapacity(t *testing.T) { var fs = &FeerStub{lowPriority: true} const mempoolSize = 10 @@ -218,18 +165,8 @@ func TestOverCapacity(t *testing.T) { require.Equal(t, mempoolSize, mp.Count()) require.Equal(t, true, sort.IsSorted(sort.Reverse(mp.verifiedTxes))) - // Claim TX has more priority than ordinary lowprio, so it should easily - // fit into the pool. - claim := &transaction.Transaction{ - Type: transaction.ClaimType, - Data: &transaction.ClaimTX{}, - } - require.NoError(t, mp.Add(claim, fs)) - require.Equal(t, mempoolSize, mp.Count()) - require.Equal(t, true, sort.IsSorted(sort.Reverse(mp.verifiedTxes))) - // Fees are also prioritized. - for i := 0; i < mempoolSize-1; i++ { + for i := 0; i < mempoolSize; i++ { tx := transaction.NewContractTX() tx.Attributes = append(tx.Attributes, transaction.Attribute{ Usage: transaction.Hash1, @@ -249,16 +186,13 @@ func TestOverCapacity(t *testing.T) { Usage: transaction.Hash1, Data: util.Uint256{1, 2, 3, 4}.BytesBE(), }) - tx.NetworkFee = util.Fixed8FromFloat(0.00001) + tx.NetworkFee = util.Fixed8FromFloat(0.000001) tx.Nonce = txcnt txcnt++ require.Error(t, mp.Add(tx, fs)) require.Equal(t, mempoolSize, mp.Count()) require.Equal(t, true, sort.IsSorted(sort.Reverse(mp.verifiedTxes))) - // But claim tx should still be there. - require.True(t, mp.ContainsKey(claim.Hash())) - // Low net fee, but higher per-byte fee is still a better combination. tx = transaction.NewContractTX() tx.Nonce = txcnt diff --git a/pkg/core/state/account.go b/pkg/core/state/account.go index 4e65ec27e..a0b82abd0 100644 --- a/pkg/core/state/account.go +++ b/pkg/core/state/account.go @@ -13,16 +13,6 @@ type UnspentBalance struct { Value util.Fixed8 `json:"value"` } -// UnclaimedBalance represents transaction output which was spent and -// can be claimed. -type UnclaimedBalance struct { - Tx util.Uint256 - Index uint16 - Start uint32 - End uint32 - Value util.Fixed8 -} - // UnspentBalances is a slice of UnspentBalance (mostly needed to sort them). type UnspentBalances []UnspentBalance @@ -32,7 +22,6 @@ type Account struct { ScriptHash util.Uint160 IsFrozen bool Balances map[util.Uint256][]UnspentBalance - Unclaimed UnclaimedBalances } // NewAccount returns a new Account object. @@ -42,7 +31,6 @@ func NewAccount(scriptHash util.Uint160) *Account { ScriptHash: scriptHash, IsFrozen: false, Balances: make(map[util.Uint256][]UnspentBalance), - Unclaimed: UnclaimedBalances{Raw: []byte{}}, } } @@ -64,10 +52,6 @@ func (s *Account) DecodeBinary(br *io.BinReader) { } s.Balances[key] = ubs } - - lenBalances = br.ReadVarUint() - s.Unclaimed.Raw = make([]byte, lenBalances*UnclaimedBalanceSize) - br.ReadBytes(s.Unclaimed.Raw) } // EncodeBinary encodes Account to the given BinWriter. @@ -84,9 +68,6 @@ func (s *Account) EncodeBinary(bw *io.BinWriter) { v[i].EncodeBinary(bw) } } - - bw.WriteVarUint(uint64(s.Unclaimed.Size())) - bw.WriteBytes(s.Unclaimed.Raw) } // DecodeBinary implements io.Serializable interface. @@ -103,24 +84,6 @@ func (u *UnspentBalance) EncodeBinary(w *io.BinWriter) { u.Value.EncodeBinary(w) } -// DecodeBinary implements io.Serializable interface. -func (u *UnclaimedBalance) DecodeBinary(r *io.BinReader) { - u.Tx.DecodeBinary(r) - u.Index = r.ReadU16LE() - u.Start = r.ReadU32LE() - u.End = r.ReadU32LE() - u.Value.DecodeBinary(r) -} - -// EncodeBinary implements io.Serializable interface. -func (u *UnclaimedBalance) EncodeBinary(w *io.BinWriter) { - u.Tx.EncodeBinary(w) - w.WriteU16LE(u.Index) - w.WriteU32LE(u.Start) - w.WriteU32LE(u.End) - u.Value.EncodeBinary(w) -} - // GetBalanceValues sums all unspent outputs and returns a map of asset IDs to // overall balances. func (s *Account) GetBalanceValues() map[util.Uint256]util.Fixed8 { diff --git a/pkg/core/state/account_test.go b/pkg/core/state/account_test.go index fab1049d7..32a7a6754 100644 --- a/pkg/core/state/account_test.go +++ b/pkg/core/state/account_test.go @@ -30,7 +30,6 @@ func TestDecodeEncodeAccountState(t *testing.T) { ScriptHash: random.Uint160(), IsFrozen: true, Balances: balances, - Unclaimed: UnclaimedBalances{Raw: []byte{}}, } testserdes.EncodeDecodeBinary(t, a, new(Account)) diff --git a/pkg/core/state/unclaimed.go b/pkg/core/state/unclaimed.go deleted file mode 100644 index c0d3bf11c..000000000 --- a/pkg/core/state/unclaimed.go +++ /dev/null @@ -1,69 +0,0 @@ -package state - -import ( - "bytes" - "encoding/binary" - - "github.com/nspcc-dev/neo-go/pkg/io" - "github.com/nspcc-dev/neo-go/pkg/util" -) - -// UnclaimedBalanceSize is a size of the UnclaimedBalance struct in bytes. -const UnclaimedBalanceSize = util.Uint256Size + 2 + 4 + 4 + 8 - -// UnclaimedBalances is a slice of UnclaimedBalance. -type UnclaimedBalances struct { - Raw []byte -} - -// Size returns an amount of store unclaimed balances. -func (bs *UnclaimedBalances) Size() int { - return len(bs.Raw) / UnclaimedBalanceSize -} - -// ForEach iterates over all unclaimed balances. -func (bs *UnclaimedBalances) ForEach(f func(*UnclaimedBalance) error) error { - b := new(UnclaimedBalance) - for i := 0; i < len(bs.Raw); i += UnclaimedBalanceSize { - r := io.NewBinReaderFromBuf(bs.Raw[i : i+UnclaimedBalanceSize]) - b.DecodeBinary(r) - if r.Err != nil { - return r.Err - } else if err := f(b); err != nil { - return err - } - } - return nil -} - -// Remove removes specified unclaim from the list and returns -// false if it wasn't found. -func (bs *UnclaimedBalances) Remove(tx util.Uint256, index uint16) bool { - const keySize = util.Uint256Size + 2 - key := make([]byte, keySize) - copy(key, tx[:]) - binary.LittleEndian.PutUint16(key[util.Uint256Size:], index) - - for i := 0; i < len(bs.Raw); i += UnclaimedBalanceSize { - if bytes.Equal(bs.Raw[i:i+keySize], key) { - lastIndex := len(bs.Raw) - UnclaimedBalanceSize - if i != lastIndex { - copy(bs.Raw[i:i+UnclaimedBalanceSize], bs.Raw[lastIndex:]) - } - bs.Raw = bs.Raw[:lastIndex] - return true - } - } - return false -} - -// Put puts new unclaim in a list. -func (bs *UnclaimedBalances) Put(b *UnclaimedBalance) error { - w := io.NewBufBinWriter() - b.EncodeBinary(w.BinWriter) - if w.Err != nil { - return w.Err - } - bs.Raw = append(bs.Raw, w.Bytes()...) - return nil -} diff --git a/pkg/core/state/unclaimed_test.go b/pkg/core/state/unclaimed_test.go deleted file mode 100644 index 5972688a6..000000000 --- a/pkg/core/state/unclaimed_test.go +++ /dev/null @@ -1,73 +0,0 @@ -package state - -import ( - "encoding/binary" - "math/rand" - "testing" - - "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" - "github.com/stretchr/testify/require" -) - -func TestUnclaimedBalance_Structure(t *testing.T) { - b := randomUnclaimed(t) - buf, err := testserdes.EncodeBinary(b) - require.NoError(t, err) - require.Equal(t, UnclaimedBalanceSize, len(buf)) - require.Equal(t, b.Tx.BytesBE(), buf[:util.Uint256Size]) - require.Equal(t, b.Index, binary.LittleEndian.Uint16(buf[util.Uint256Size:])) -} - -func TestUnclaimedBalances_Put(t *testing.T) { - bs := new(UnclaimedBalances) - b1 := randomUnclaimed(t) - b2 := randomUnclaimed(t) - b3 := randomUnclaimed(t) - - require.NoError(t, bs.Put(b1)) - require.Equal(t, 1, bs.Size()) - require.NoError(t, bs.Put(b2)) - require.Equal(t, 2, bs.Size()) - require.NoError(t, bs.Put(b3)) - require.Equal(t, 3, bs.Size()) - require.True(t, bs.Remove(b2.Tx, b2.Index)) - require.Equal(t, 2, bs.Size()) - require.False(t, bs.Remove(b2.Tx, b2.Index)) - require.Equal(t, 2, bs.Size()) - require.True(t, bs.Remove(b1.Tx, b1.Index)) - require.Equal(t, 1, bs.Size()) - require.True(t, bs.Remove(b3.Tx, b3.Index)) - require.Equal(t, 0, bs.Size()) -} - -func TestUnclaimedBalances_ForEach(t *testing.T) { - bs := new(UnclaimedBalances) - b1 := randomUnclaimed(t) - b2 := randomUnclaimed(t) - b3 := randomUnclaimed(t) - - require.NoError(t, bs.Put(b1)) - require.NoError(t, bs.Put(b2)) - require.NoError(t, bs.Put(b3)) - - var indices []uint16 - err := bs.ForEach(func(b *UnclaimedBalance) error { - indices = append(indices, b.Index) - return nil - }) - require.NoError(t, err) - require.Equal(t, []uint16{b1.Index, b2.Index, b3.Index}, indices) -} - -func randomUnclaimed(t *testing.T) *UnclaimedBalance { - b := new(UnclaimedBalance) - b.Tx = random.Uint256() - b.Index = uint16(rand.Uint32()) - b.Start = rand.Uint32() - b.End = rand.Uint32() - b.Value = util.Fixed8(rand.Int63()) - - return b -} diff --git a/pkg/core/transaction/claim.go b/pkg/core/transaction/claim.go deleted file mode 100644 index 704d9035b..000000000 --- a/pkg/core/transaction/claim.go +++ /dev/null @@ -1,38 +0,0 @@ -package transaction - -import ( - "math/rand" - - "github.com/nspcc-dev/neo-go/pkg/io" -) - -// ClaimTX represents a claim transaction. -type ClaimTX struct { - Claims []Input -} - -// NewClaimTX creates Transaction of ClaimType type. -func NewClaimTX(claim *ClaimTX) *Transaction { - return &Transaction{ - Type: ClaimType, - Version: 0, - Nonce: rand.Uint32(), - Data: claim, - Attributes: []Attribute{}, - Cosigners: []Cosigner{}, - Inputs: []Input{}, - Outputs: []Output{}, - Scripts: []Witness{}, - Trimmed: false, - } -} - -// DecodeBinary implements Serializable interface. -func (tx *ClaimTX) DecodeBinary(br *io.BinReader) { - br.ReadArray(&tx.Claims) -} - -// EncodeBinary implements Serializable interface. -func (tx *ClaimTX) EncodeBinary(bw *io.BinWriter) { - bw.WriteArray(tx.Claims) -} diff --git a/pkg/core/transaction/helper_test.go b/pkg/core/transaction/helper_test.go index 1f1cae62f..6cbd5e61c 100644 --- a/pkg/core/transaction/helper_test.go +++ b/pkg/core/transaction/helper_test.go @@ -9,8 +9,6 @@ import ( var ( //TODO NEO3.0: Update binary - // https://neotracker.io/tx/2c6a45547b3898318e400e541628990a07acb00f3b9a15a8e966ae49525304da - rawClaimTX = "020004bc67ba325d6412ff4c55b10f7e9afb54bbb2228d201b37363c3d697ac7c198f70300591cd454d7318d2087c0196abfbbd1573230380672f0f0cd004dcb4857e58cbd010031bcfbed573f5318437e95edd603922a4455ff3326a979fdd1c149a84c4cb0290000b51eb6159c58cac4fe23d90e292ad2bcb7002b0da2c474e81e1889c0649d2c490000000001e72d286979ee6cb1b7e65dfddfb2e384100b8d148e7758de42e4168b71792c603b555f00000000005d9de59d99c0d1f6ed1496444473f4a0b538302f014140456349cec43053009accdb7781b0799c6b591c812768804ab0a0b56b5eae7a97694227fcd33e70899c075848b2cee8fae733faac6865b484d3f7df8949e2aadb232103945fae1ed3c31d778f149192b76734fcc951b400ba3598faa81ff92ebe477eacac" // https://neotracker.io/tx/fe4b3af60677204c57e573a57bdc97bc5059b05ad85b1474f84431f88d910f64 rawInvocationTX = "d101590400b33f7114839c33710da24cf8e7d536b8d244f3991cf565c8146063795d3b9b3cd55aef026eae992b91063db0db53c1087472616e7366657267c5cc1cb5392019e2cc4e6d6b5ea54c8d4b6d11acf166cb072961424c54f6000000000000000001206063795d3b9b3cd55aef026eae992b91063db0db0000014140c6a131c55ca38995402dff8e92ac55d89cbed4b98dfebbcb01acbc01bd78fa2ce2061be921b8999a9ab79c2958875bccfafe7ce1bbbaf1f56580815ea3a4feed232102d41ddce2c97be4c9aa571b8a32cbc305aa29afffbcae71b0ef568db0e93929aaac" ) diff --git a/pkg/core/transaction/transaction.go b/pkg/core/transaction/transaction.go index 0afdcd31a..8b4669f65 100644 --- a/pkg/core/transaction/transaction.go +++ b/pkg/core/transaction/transaction.go @@ -176,9 +176,6 @@ func (t *Transaction) decodeData(r *io.BinReader) { case InvocationType: t.Data = &InvocationTX{} t.Data.(*InvocationTX).DecodeBinary(r) - case ClaimType: - t.Data = &ClaimTX{} - t.Data.(*ClaimTX).DecodeBinary(r) case ContractType: t.Data = &ContractTX{} t.Data.(*ContractTX).DecodeBinary(r) @@ -313,7 +310,6 @@ type transactionJSON struct { Outputs []Output `json:"vout"` Scripts []Witness `json:"scripts"` - Claims []Input `json:"claims,omitempty"` Script string `json:"script,omitempty"` Asset *registeredAsset `json:"asset,omitempty"` } @@ -337,8 +333,6 @@ func (t *Transaction) MarshalJSON() ([]byte, error) { NetworkFee: t.NetworkFee, } switch t.Type { - case ClaimType: - tx.Claims = t.Data.(*ClaimTX).Claims case InvocationType: tx.Script = hex.EncodeToString(t.Data.(*InvocationTX).Script) case RegisterType: @@ -378,10 +372,6 @@ func (t *Transaction) UnmarshalJSON(data []byte) error { } t.Sender = sender switch tx.Type { - case ClaimType: - t.Data = &ClaimTX{ - Claims: tx.Claims, - } case InvocationType: bytes, err := hex.DecodeString(tx.Script) if err != nil { diff --git a/pkg/core/transaction/transaction_test.go b/pkg/core/transaction/transaction_test.go index 0a9cd2750..c5cbeb21d 100644 --- a/pkg/core/transaction/transaction_test.go +++ b/pkg/core/transaction/transaction_test.go @@ -36,31 +36,6 @@ func TestWitnessEncodeDecode(t *testing.T) { // TODO NEO3.0: update binary /* -func TestDecodeEncodeClaimTX(t *testing.T) { - tx := decodeTransaction(rawClaimTX, t) - assert.Equal(t, tx.Type, ClaimType) - assert.IsType(t, tx.Data, &ClaimTX{}) - claimTX := tx.Data.(*ClaimTX) - assert.Equal(t, 4, len(claimTX.Claims)) - assert.Equal(t, 0, len(tx.Attributes)) - assert.Equal(t, 0, len(tx.Inputs)) - assert.Equal(t, 1, len(tx.Outputs)) - assert.Equal(t, "AQJseD8iBmCD4sgfHRhMahmoi9zvopG6yz", address.Uint160ToString(tx.Outputs[0].ScriptHash)) - assert.Equal(t, "602c79718b16e442de58778e148d0b1084e3b2dffd5de6b7b16cee7969282de7", tx.Outputs[0].AssetID.StringLE()) - assert.Equal(t, tx.Outputs[0].Amount.String(), "0.06247739") - invoc := "40456349cec43053009accdb7781b0799c6b591c812768804ab0a0b56b5eae7a97694227fcd33e70899c075848b2cee8fae733faac6865b484d3f7df8949e2aadb" - verif := "2103945fae1ed3c31d778f149192b76734fcc951b400ba3598faa81ff92ebe477eacac" - assert.Equal(t, 1, len(tx.Scripts)) - assert.Equal(t, invoc, hex.EncodeToString(tx.Scripts[0].InvocationScript)) - assert.Equal(t, verif, hex.EncodeToString(tx.Scripts[0].VerificationScript)) - - data, err := testserdes.EncodeBinary(tx) - assert.NoError(t, err) - assert.Equal(t, rawClaimTX, hex.EncodeToString(data)) - - hash := "2c6a45547b3898318e400e541628990a07acb00f3b9a15a8e966ae49525304da" - assert.Equal(t, hash, tx.hash.StringLE()) -} func TestDecodeEncodeInvocationTX(t *testing.T) { tx := decodeTransaction(rawInvocationTX, t) @@ -120,34 +95,6 @@ func TestMarshalUnmarshalJSONContractTX(t *testing.T) { testserdes.MarshalUnmarshalJSON(t, tx, new(Transaction)) } -func TestMarshalUnmarshalJSONClaimTX(t *testing.T) { - tx := &Transaction{ - Type: ClaimType, - Version: 0, - Data: &ClaimTX{Claims: []Input{ - { - PrevHash: util.Uint256{1, 2, 3, 4}, - PrevIndex: uint16(56), - }, - }}, - 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, - } - - testserdes.MarshalUnmarshalJSON(t, tx, new(Transaction)) -} - func TestMarshalUnmarshalJSONInvocationTX(t *testing.T) { tx := &Transaction{ Type: InvocationType, diff --git a/pkg/core/transaction/type.go b/pkg/core/transaction/type.go index bf5d34420..9fd07a0e4 100644 --- a/pkg/core/transaction/type.go +++ b/pkg/core/transaction/type.go @@ -12,7 +12,6 @@ type TXType uint8 // Constants for all valid transaction types. const ( IssueType TXType = 0x01 - ClaimType TXType = 0x02 RegisterType TXType = 0x40 ContractType TXType = 0x80 InvocationType TXType = 0xd1 @@ -23,8 +22,6 @@ func (t TXType) String() string { switch t { case IssueType: return "IssueTransaction" - case ClaimType: - return "ClaimTransaction" case RegisterType: return "RegisterTransaction" case ContractType: @@ -57,8 +54,6 @@ func TXTypeFromString(jsonString string) (TXType, error) { switch jsonString = strings.TrimSpace(jsonString); jsonString { case "IssueTransaction": return IssueType, nil - case "ClaimTransaction": - return ClaimType, nil case "RegisterTransaction": return RegisterType, nil case "ContractTransaction": diff --git a/pkg/interop/transaction/transaction.go b/pkg/interop/transaction/transaction.go index e354d7baf..3c47e8be2 100644 --- a/pkg/interop/transaction/transaction.go +++ b/pkg/interop/transaction/transaction.go @@ -24,7 +24,6 @@ func GetHash(t Transaction) []byte { // GetType returns the type of the given transaction. Possible values: // MinerTransaction = 0x00 // IssueTransaction = 0x01 -// ClaimTransaction = 0x02 // EnrollmentTransaction = 0x20 // RegisterTransaction = 0x40 // ContractTransaction = 0x80