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
}
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")
}
}

View file

@ -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) {

View file

@ -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())
}

View file

@ -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")
}
}