From a4294f4b5f916e70446785cbd0bac681b7ccdd68 Mon Sep 17 00:00:00 2001 From: Roman Khimov Date: Fri, 14 Feb 2020 17:44:46 +0300 Subject: [PATCH] core: export UtilityTokenID and GoverningTokenID Both are very useful outside of the core, this change also makes respective transactions initialize with the package as they don't depend on any kind of input and it makes no sense recreating them again and again on every use. --- pkg/core/blockchain.go | 18 ++++++++--------- pkg/core/util.go | 45 +++++++++++++++++++++++++++--------------- pkg/core/util_test.go | 6 ++---- pkg/rpc/rpc.go | 6 ++---- 4 files changed, 42 insertions(+), 33 deletions(-) diff --git a/pkg/core/blockchain.go b/pkg/core/blockchain.go index 9d712f16a..1c3869c89 100644 --- a/pkg/core/blockchain.go +++ b/pkg/core/blockchain.go @@ -432,7 +432,7 @@ func (bc *Blockchain) storeBlock(block *block.Block) error { return err } - if prevTXOutput.AssetID.Equals(governingTokenTX().Hash()) { + if prevTXOutput.AssetID.Equals(GoverningTokenID()) { spentCoin := NewSpentCoinState(input.PrevHash, prevTXHeight) spentCoin.items[input.PrevIndex] = block.Index if err = cache.PutSpentCoinState(input.PrevHash, spentCoin); err != nil { @@ -648,14 +648,14 @@ func processOutputs(tx *transaction.Transaction, dao *cachedDao) error { } func processTXWithValidatorsAdd(output *transaction.Output, account *state.Account, dao *cachedDao) error { - if output.AssetID.Equals(governingTokenTX().Hash()) && len(account.Votes) > 0 { + if output.AssetID.Equals(GoverningTokenID()) && len(account.Votes) > 0 { return modAccountVotes(account, dao, output.Amount) } return nil } func processTXWithValidatorsSubtract(output *transaction.Output, account *state.Account, dao *cachedDao) error { - if output.AssetID.Equals(governingTokenTX().Hash()) && len(account.Votes) > 0 { + if output.AssetID.Equals(GoverningTokenID()) && len(account.Votes) > 0 { return modAccountVotes(account, dao, -output.Amount) } return nil @@ -724,7 +724,7 @@ func processAccountStateDescriptor(descriptor *transaction.StateDescriptor, dao } if descriptor.Field == "Votes" { - balance := account.GetBalanceValues()[governingTokenTX().Hash()] + balance := account.GetBalanceValues()[GoverningTokenID()] if err = modAccountVotes(account, dao, -balance); err != nil { return err } @@ -999,14 +999,14 @@ func (bc *Blockchain) FeePerByte(t *transaction.Transaction) util.Fixed8 { func (bc *Blockchain) NetworkFee(t *transaction.Transaction) util.Fixed8 { inputAmount := util.Fixed8FromInt64(0) for _, txOutput := range bc.References(t) { - if txOutput.AssetID == utilityTokenTX().Hash() { + if txOutput.AssetID == UtilityTokenID() { inputAmount.Add(txOutput.Amount) } } outputAmount := util.Fixed8FromInt64(0) for _, txOutput := range t.Outputs { - if txOutput.AssetID == utilityTokenTX().Hash() { + if txOutput.AssetID == UtilityTokenID() { outputAmount.Add(txOutput.Amount) } } @@ -1192,7 +1192,7 @@ func (bc *Blockchain) verifyResults(t *transaction.Transaction) error { if len(resultsDestroy) > 1 { return errors.New("tx has more than 1 destroy output") } - if len(resultsDestroy) == 1 && resultsDestroy[0].AssetID != utilityTokenTX().Hash() { + if len(resultsDestroy) == 1 && resultsDestroy[0].AssetID != UtilityTokenID() { return errors.New("tx destroys non-utility token") } sysfee := bc.SystemFee(t) @@ -1208,14 +1208,14 @@ func (bc *Blockchain) verifyResults(t *transaction.Transaction) error { switch t.Type { case transaction.MinerType, transaction.ClaimType: for _, r := range resultsIssue { - if r.AssetID != utilityTokenTX().Hash() { + 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 == utilityTokenTX().Hash() { + if r.AssetID == UtilityTokenID() { return errors.New("issue tx issues utility tokens") } } diff --git a/pkg/core/util.go b/pkg/core/util.go index 4465a0621..77fcddc22 100644 --- a/pkg/core/util.go +++ b/pkg/core/util.go @@ -13,6 +13,17 @@ import ( "github.com/CityOfZion/neo-go/pkg/vm/opcode" ) +var ( + // governingTokenTX represents transaction that is used to create + // governing (NEO) token. It's a part of the genesis block. + governingTokenTX transaction.Transaction + + // utilityTokenTX represents transaction that is used to create + // utility (GAS) token. It's a part of the genesis block. It's mostly + // useful for its hash that represents GAS asset ID. + utilityTokenTX transaction.Transaction +) + // createGenesisBlock creates a genesis block based on the given configuration. func createGenesisBlock(cfg config.ProtocolConfiguration) (*block.Block, error) { validators, err := getValidators(cfg) @@ -38,8 +49,6 @@ func createGenesisBlock(cfg config.ProtocolConfiguration) (*block.Block, error) }, } - governingTX := governingTokenTX() - utilityTX := utilityTokenTX() rawScript, err := smartcontract.CreateMultiSigRedeemScript( len(cfg.StandbyValidators)/2+1, validators, @@ -62,16 +71,16 @@ func createGenesisBlock(cfg config.ProtocolConfiguration) (*block.Block, error) Outputs: []transaction.Output{}, Scripts: []transaction.Witness{}, }, - governingTX, - utilityTX, + &governingTokenTX, + &utilityTokenTX, { Type: transaction.IssueType, Data: &transaction.IssueTX{}, // no fields. Inputs: []transaction.Input{}, Outputs: []transaction.Output{ { - AssetID: governingTX.Hash(), - Amount: governingTX.Data.(*transaction.RegisterTX).Amount, + AssetID: governingTokenTX.Hash(), + Amount: governingTokenTX.Data.(*transaction.RegisterTX).Amount, ScriptHash: scriptOut, }, }, @@ -92,7 +101,7 @@ func createGenesisBlock(cfg config.ProtocolConfiguration) (*block.Block, error) return b, nil } -func governingTokenTX() *transaction.Transaction { +func init() { admin := hash.Hash160([]byte{byte(opcode.PUSHT)}) registerTX := &transaction.RegisterTX{ AssetType: transaction.GoverningToken, @@ -102,7 +111,7 @@ func governingTokenTX() *transaction.Transaction { Admin: admin, } - tx := &transaction.Transaction{ + governingTokenTX = transaction.Transaction{ Type: transaction.RegisterType, Data: registerTX, Attributes: []transaction.Attribute{}, @@ -111,19 +120,15 @@ func governingTokenTX() *transaction.Transaction { Scripts: []transaction.Witness{}, } - return tx -} - -func utilityTokenTX() *transaction.Transaction { - admin := hash.Hash160([]byte{byte(opcode.PUSHF)}) - registerTX := &transaction.RegisterTX{ + admin = hash.Hash160([]byte{byte(opcode.PUSHF)}) + registerTX = &transaction.RegisterTX{ AssetType: transaction.UtilityToken, Name: "[{\"lang\":\"zh-CN\",\"name\":\"小蚁币\"},{\"lang\":\"en\",\"name\":\"AntCoin\"}]", Amount: calculateUtilityAmount(), Precision: 8, Admin: admin, } - tx := &transaction.Transaction{ + utilityTokenTX = transaction.Transaction{ Type: transaction.RegisterType, Data: registerTX, Attributes: []transaction.Attribute{}, @@ -131,8 +136,16 @@ func utilityTokenTX() *transaction.Transaction { Outputs: []transaction.Output{}, Scripts: []transaction.Witness{}, } +} - return tx +// GoverningTokenID returns the governing token (NEO) hash. +func GoverningTokenID() util.Uint256 { + return governingTokenTX.Hash() +} + +// UtilityTokenID returns the utility token (GAS) hash. +func UtilityTokenID() util.Uint256 { + return utilityTokenTX.Hash() } func getValidators(cfg config.ProtocolConfiguration) ([]*keys.PublicKey, error) { diff --git a/pkg/core/util_test.go b/pkg/core/util_test.go index b2222a56a..aaa39ae63 100644 --- a/pkg/core/util_test.go +++ b/pkg/core/util_test.go @@ -50,12 +50,10 @@ func TestGetConsensusAddressMainNet(t *testing.T) { func TestUtilityTokenTX(t *testing.T) { expect := "602c79718b16e442de58778e148d0b1084e3b2dffd5de6b7b16cee7969282de7" - tx := utilityTokenTX() - assert.Equal(t, expect, tx.Hash().StringLE()) + assert.Equal(t, expect, UtilityTokenID().StringLE()) } func TestGoverningTokenTX(t *testing.T) { expect := "c56f33fc6ecfcd0c225c4ab356fee59390af8560be0e930faebe74a6daff7c9b" - tx := governingTokenTX() - assert.Equal(t, expect, tx.Hash().StringLE()) + assert.Equal(t, expect, GoverningTokenID().StringLE()) } diff --git a/pkg/rpc/rpc.go b/pkg/rpc/rpc.go index 9beaad3d3..8ba1af6c5 100644 --- a/pkg/rpc/rpc.go +++ b/pkg/rpc/rpc.go @@ -4,6 +4,7 @@ import ( "encoding/hex" "fmt" + "github.com/CityOfZion/neo-go/pkg/core" "github.com/CityOfZion/neo-go/pkg/core/transaction" "github.com/CityOfZion/neo-go/pkg/crypto/keys" "github.com/CityOfZion/neo-go/pkg/smartcontract" @@ -160,15 +161,12 @@ func (c *Client) SignAndPushInvocationTx(script []byte, wif *keys.WIF, gas util. var txHash util.Uint256 var err error - gasIDB, _ := hex.DecodeString("602c79718b16e442de58778e148d0b1084e3b2dffd5de6b7b16cee7969282de7") - gasID, _ := util.Uint256DecodeBytesLE(gasIDB) - tx := transaction.NewInvocationTX(script, gas) fromAddress := wif.PrivateKey.Address() if gas > 0 { - if err = AddInputsAndUnspentsToTx(tx, fromAddress, gasID, gas, c); err != nil { + if err = AddInputsAndUnspentsToTx(tx, fromAddress, core.UtilityTokenID(), gas, c); err != nil { return txHash, errors.Wrap(err, "failed to add inputs and unspents to transaction") } }