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.
This commit is contained in:
Roman Khimov 2020-02-14 17:44:46 +03:00
parent b41a5239c6
commit a4294f4b5f
4 changed files with 42 additions and 33 deletions

View file

@ -432,7 +432,7 @@ func (bc *Blockchain) storeBlock(block *block.Block) error {
return err return err
} }
if prevTXOutput.AssetID.Equals(governingTokenTX().Hash()) { if prevTXOutput.AssetID.Equals(GoverningTokenID()) {
spentCoin := NewSpentCoinState(input.PrevHash, prevTXHeight) spentCoin := NewSpentCoinState(input.PrevHash, prevTXHeight)
spentCoin.items[input.PrevIndex] = block.Index spentCoin.items[input.PrevIndex] = block.Index
if err = cache.PutSpentCoinState(input.PrevHash, spentCoin); err != nil { 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 { 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 modAccountVotes(account, dao, output.Amount)
} }
return nil return nil
} }
func processTXWithValidatorsSubtract(output *transaction.Output, account *state.Account, dao *cachedDao) error { 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 modAccountVotes(account, dao, -output.Amount)
} }
return nil return nil
@ -724,7 +724,7 @@ func processAccountStateDescriptor(descriptor *transaction.StateDescriptor, dao
} }
if descriptor.Field == "Votes" { if descriptor.Field == "Votes" {
balance := account.GetBalanceValues()[governingTokenTX().Hash()] balance := account.GetBalanceValues()[GoverningTokenID()]
if err = modAccountVotes(account, dao, -balance); err != nil { if err = modAccountVotes(account, dao, -balance); err != nil {
return err return err
} }
@ -999,14 +999,14 @@ func (bc *Blockchain) FeePerByte(t *transaction.Transaction) util.Fixed8 {
func (bc *Blockchain) NetworkFee(t *transaction.Transaction) util.Fixed8 { func (bc *Blockchain) NetworkFee(t *transaction.Transaction) util.Fixed8 {
inputAmount := util.Fixed8FromInt64(0) inputAmount := util.Fixed8FromInt64(0)
for _, txOutput := range bc.References(t) { for _, txOutput := range bc.References(t) {
if txOutput.AssetID == utilityTokenTX().Hash() { if txOutput.AssetID == UtilityTokenID() {
inputAmount.Add(txOutput.Amount) inputAmount.Add(txOutput.Amount)
} }
} }
outputAmount := util.Fixed8FromInt64(0) outputAmount := util.Fixed8FromInt64(0)
for _, txOutput := range t.Outputs { for _, txOutput := range t.Outputs {
if txOutput.AssetID == utilityTokenTX().Hash() { if txOutput.AssetID == UtilityTokenID() {
outputAmount.Add(txOutput.Amount) outputAmount.Add(txOutput.Amount)
} }
} }
@ -1192,7 +1192,7 @@ func (bc *Blockchain) verifyResults(t *transaction.Transaction) error {
if len(resultsDestroy) > 1 { if len(resultsDestroy) > 1 {
return errors.New("tx has more than 1 destroy output") 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") return errors.New("tx destroys non-utility token")
} }
sysfee := bc.SystemFee(t) sysfee := bc.SystemFee(t)
@ -1208,14 +1208,14 @@ func (bc *Blockchain) verifyResults(t *transaction.Transaction) error {
switch t.Type { switch t.Type {
case transaction.MinerType, transaction.ClaimType: case transaction.MinerType, transaction.ClaimType:
for _, r := range resultsIssue { for _, r := range resultsIssue {
if r.AssetID != utilityTokenTX().Hash() { if r.AssetID != UtilityTokenID() {
return errors.New("miner or claim tx issues non-utility tokens") return errors.New("miner or claim tx issues non-utility tokens")
} }
} }
break break
case transaction.IssueType: case transaction.IssueType:
for _, r := range resultsIssue { for _, r := range resultsIssue {
if r.AssetID == utilityTokenTX().Hash() { if r.AssetID == UtilityTokenID() {
return errors.New("issue tx issues utility tokens") return errors.New("issue tx issues utility tokens")
} }
} }

View file

@ -13,6 +13,17 @@ import (
"github.com/CityOfZion/neo-go/pkg/vm/opcode" "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. // createGenesisBlock creates a genesis block based on the given configuration.
func createGenesisBlock(cfg config.ProtocolConfiguration) (*block.Block, error) { func createGenesisBlock(cfg config.ProtocolConfiguration) (*block.Block, error) {
validators, err := getValidators(cfg) validators, err := getValidators(cfg)
@ -38,8 +49,6 @@ func createGenesisBlock(cfg config.ProtocolConfiguration) (*block.Block, error)
}, },
} }
governingTX := governingTokenTX()
utilityTX := utilityTokenTX()
rawScript, err := smartcontract.CreateMultiSigRedeemScript( rawScript, err := smartcontract.CreateMultiSigRedeemScript(
len(cfg.StandbyValidators)/2+1, len(cfg.StandbyValidators)/2+1,
validators, validators,
@ -62,16 +71,16 @@ func createGenesisBlock(cfg config.ProtocolConfiguration) (*block.Block, error)
Outputs: []transaction.Output{}, Outputs: []transaction.Output{},
Scripts: []transaction.Witness{}, Scripts: []transaction.Witness{},
}, },
governingTX, &governingTokenTX,
utilityTX, &utilityTokenTX,
{ {
Type: transaction.IssueType, Type: transaction.IssueType,
Data: &transaction.IssueTX{}, // no fields. Data: &transaction.IssueTX{}, // no fields.
Inputs: []transaction.Input{}, Inputs: []transaction.Input{},
Outputs: []transaction.Output{ Outputs: []transaction.Output{
{ {
AssetID: governingTX.Hash(), AssetID: governingTokenTX.Hash(),
Amount: governingTX.Data.(*transaction.RegisterTX).Amount, Amount: governingTokenTX.Data.(*transaction.RegisterTX).Amount,
ScriptHash: scriptOut, ScriptHash: scriptOut,
}, },
}, },
@ -92,7 +101,7 @@ func createGenesisBlock(cfg config.ProtocolConfiguration) (*block.Block, error)
return b, nil return b, nil
} }
func governingTokenTX() *transaction.Transaction { func init() {
admin := hash.Hash160([]byte{byte(opcode.PUSHT)}) admin := hash.Hash160([]byte{byte(opcode.PUSHT)})
registerTX := &transaction.RegisterTX{ registerTX := &transaction.RegisterTX{
AssetType: transaction.GoverningToken, AssetType: transaction.GoverningToken,
@ -102,7 +111,7 @@ func governingTokenTX() *transaction.Transaction {
Admin: admin, Admin: admin,
} }
tx := &transaction.Transaction{ governingTokenTX = transaction.Transaction{
Type: transaction.RegisterType, Type: transaction.RegisterType,
Data: registerTX, Data: registerTX,
Attributes: []transaction.Attribute{}, Attributes: []transaction.Attribute{},
@ -111,19 +120,15 @@ func governingTokenTX() *transaction.Transaction {
Scripts: []transaction.Witness{}, Scripts: []transaction.Witness{},
} }
return tx admin = hash.Hash160([]byte{byte(opcode.PUSHF)})
} registerTX = &transaction.RegisterTX{
func utilityTokenTX() *transaction.Transaction {
admin := hash.Hash160([]byte{byte(opcode.PUSHF)})
registerTX := &transaction.RegisterTX{
AssetType: transaction.UtilityToken, AssetType: transaction.UtilityToken,
Name: "[{\"lang\":\"zh-CN\",\"name\":\"小蚁币\"},{\"lang\":\"en\",\"name\":\"AntCoin\"}]", Name: "[{\"lang\":\"zh-CN\",\"name\":\"小蚁币\"},{\"lang\":\"en\",\"name\":\"AntCoin\"}]",
Amount: calculateUtilityAmount(), Amount: calculateUtilityAmount(),
Precision: 8, Precision: 8,
Admin: admin, Admin: admin,
} }
tx := &transaction.Transaction{ utilityTokenTX = transaction.Transaction{
Type: transaction.RegisterType, Type: transaction.RegisterType,
Data: registerTX, Data: registerTX,
Attributes: []transaction.Attribute{}, Attributes: []transaction.Attribute{},
@ -131,8 +136,16 @@ func utilityTokenTX() *transaction.Transaction {
Outputs: []transaction.Output{}, Outputs: []transaction.Output{},
Scripts: []transaction.Witness{}, 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) { func getValidators(cfg config.ProtocolConfiguration) ([]*keys.PublicKey, error) {

View file

@ -50,12 +50,10 @@ func TestGetConsensusAddressMainNet(t *testing.T) {
func TestUtilityTokenTX(t *testing.T) { func TestUtilityTokenTX(t *testing.T) {
expect := "602c79718b16e442de58778e148d0b1084e3b2dffd5de6b7b16cee7969282de7" expect := "602c79718b16e442de58778e148d0b1084e3b2dffd5de6b7b16cee7969282de7"
tx := utilityTokenTX() assert.Equal(t, expect, UtilityTokenID().StringLE())
assert.Equal(t, expect, tx.Hash().StringLE())
} }
func TestGoverningTokenTX(t *testing.T) { func TestGoverningTokenTX(t *testing.T) {
expect := "c56f33fc6ecfcd0c225c4ab356fee59390af8560be0e930faebe74a6daff7c9b" expect := "c56f33fc6ecfcd0c225c4ab356fee59390af8560be0e930faebe74a6daff7c9b"
tx := governingTokenTX() assert.Equal(t, expect, GoverningTokenID().StringLE())
assert.Equal(t, expect, tx.Hash().StringLE())
} }

View file

@ -4,6 +4,7 @@ import (
"encoding/hex" "encoding/hex"
"fmt" "fmt"
"github.com/CityOfZion/neo-go/pkg/core"
"github.com/CityOfZion/neo-go/pkg/core/transaction" "github.com/CityOfZion/neo-go/pkg/core/transaction"
"github.com/CityOfZion/neo-go/pkg/crypto/keys" "github.com/CityOfZion/neo-go/pkg/crypto/keys"
"github.com/CityOfZion/neo-go/pkg/smartcontract" "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 txHash util.Uint256
var err error var err error
gasIDB, _ := hex.DecodeString("602c79718b16e442de58778e148d0b1084e3b2dffd5de6b7b16cee7969282de7")
gasID, _ := util.Uint256DecodeBytesLE(gasIDB)
tx := transaction.NewInvocationTX(script, gas) tx := transaction.NewInvocationTX(script, gas)
fromAddress := wif.PrivateKey.Address() fromAddress := wif.PrivateKey.Address()
if gas > 0 { 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") return txHash, errors.Wrap(err, "failed to add inputs and unspents to transaction")
} }
} }