baseSubsidy = uint64(41250000000)
InitialBlockSubsidy = uint64(140700041250000000)
+ //config parameter for vote
+ VotePendingBlockNumber = uint64(10000)
+
// config for pow mining
BlocksPerRetarget = uint64(2016)
TargetSecondsPerBlock = uint64(150)
NormalUTXOType uint32 = iota
CoinbaseUTXOType
CrosschainUTXOType
+ VoteUTXOType
)
// NewUtxoEntry will create a new utxo entry
bc.Hash{V0: 1, V1: 1, V2: 3, V3: 4}: &storage.UtxoEntry{Type: storage.NormalUTXOType, BlockHeight: 100, Spent: true},
bc.Hash{V0: 1, V1: 1, V2: 3, V3: 5}: &storage.UtxoEntry{Type: storage.CrosschainUTXOType, BlockHeight: 100, Spent: false},
bc.Hash{V0: 1, V1: 1, V2: 3, V3: 6}: &storage.UtxoEntry{Type: storage.CrosschainUTXOType, BlockHeight: 100, Spent: true},
+ bc.Hash{V0: 1, V1: 3, V2: 3, V3: 7}: &storage.UtxoEntry{Type: storage.VoteUTXOType, BlockHeight: 100, Spent: false},
+ bc.Hash{V0: 1, V1: 3, V2: 3, V3: 7}: &storage.UtxoEntry{Type: storage.VoteUTXOType, BlockHeight: 100, Spent: true},
},
}
if (utxo.Type == storage.CrosschainUTXOType) && (!utxo.Spent) {
continue
}
+ if (utxo.Type == storage.VoteUTXOType) && (utxo.Spent) {
+ continue
+ }
gotUtxo, err := store.GetUtxo(&hash)
if err != nil {
continue
}
- if (entry.Type == storage.NormalUTXOType) && (entry.Spent) {
+ if (entry.Type == storage.NormalUTXOType || entry.Type == storage.VoteUTXOType) && (entry.Spent) {
batch.Delete(calcUtxoKey(&key))
continue
}
func TestSaveUtxoView(t *testing.T) {
testDB := dbm.NewDB("testdb", "leveldb", "temp")
batch := testDB.NewBatch()
- defer os.RemoveAll("temp")
+ defer func() {
+ testDB.Close()
+ os.RemoveAll("temp")
+ }()
cases := []struct {
hash bc.Hash
utxoEntry: storage.NewUtxoEntry(storage.CrosschainUTXOType, 0, false),
exist: false,
},
+ {
+ hash: bc.Hash{V0: 6},
+ utxoEntry: storage.NewUtxoEntry(storage.VoteUTXOType, 0, true),
+ exist: false,
+ },
+ {
+ hash: bc.Hash{V0: 7},
+ utxoEntry: storage.NewUtxoEntry(storage.VoteUTXOType, 0, false),
+ exist: true,
+ },
}
view := state.NewUtxoViewpoint()
if !ok {
return errors.New("fail to find utxo entry")
}
- if entry.Type == storage.CrosschainUTXOType {
- return errors.New("look up spentOutputID but find utxo from mainchain")
- }
+
if entry.Spent {
return errors.New("utxo has been spent")
}
- if (entry.Type == storage.CoinbaseUTXOType) && ((entry.BlockHeight + consensus.CoinbasePendingBlockNumber) > block.Height) {
- return errors.New("coinbase utxo is not ready for use")
+
+ switch entry.Type {
+ case storage.CrosschainUTXOType:
+ return errors.New("look up spentOutputID but find utxo from mainchain")
+
+ case storage.CoinbaseUTXOType:
+ if (entry.BlockHeight + consensus.CoinbasePendingBlockNumber) > block.Height {
+ return errors.New("coinbase utxo is not ready for use")
+ }
+
+ case storage.VoteUTXOType:
+ if (entry.BlockHeight + consensus.VotePendingBlockNumber) > block.Height {
+ return errors.New("Coin is within the voting lock time")
+ }
}
+
entry.SpendOutput()
}
continue
}
+ utxoType := storage.NormalUTXOType
+
switch output := entryOutput.(type) {
case *bc.IntraChainOutput:
assetID = *output.Source.Value.AssetId
case *bc.VoteOutput:
assetID = *output.Source.Value.AssetId
+ utxoType = storage.VoteUTXOType
default:
// due to it's a retirement, utxo doesn't care this output type so skip it
continue
continue
}
- utxoType := storage.NormalUTXOType
if block != nil && len(block.Transactions) > 0 && block.Transactions[0].ID == tx.ID {
utxoType = storage.CoinbaseUTXOType
}
return err
}
+ utxoType := storage.NormalUTXOType
switch output := entryOutput.(type) {
case *bc.IntraChainOutput:
assetID = *output.Source.Value.AssetId
case *bc.VoteOutput:
assetID = *output.Source.Value.AssetId
+ utxoType = storage.VoteUTXOType
default:
return errors.Wrapf(bc.ErrEntryType, "entry %x has unexpected type %T", prevout.Bytes(), entryOutput)
}
}
if !ok {
- view.Entries[prevout] = storage.NewUtxoEntry(storage.NormalUTXOType, 0, false)
+ view.Entries[prevout] = storage.NewUtxoEntry(utxoType, 0, false)
continue
}
entry.UnspendOutput()
continue
}
+ utxoType := storage.NormalUTXOType
switch output := entryOutput.(type) {
case *bc.IntraChainOutput:
assetID = *output.Source.Value.AssetId
case *bc.VoteOutput:
assetID = *output.Source.Value.AssetId
+ utxoType = storage.VoteUTXOType
default:
// due to it's a retirement, utxo doesn't care this output type so skip it
continue
continue
}
- view.Entries[*id] = storage.NewUtxoEntry(storage.NormalUTXOType, 0, true)
+ view.Entries[*id] = storage.NewUtxoEntry(utxoType, 0, true)
}
return nil
}
},
}
+var voteEntry = map[bc.Hash]bc.Entry{
+ bc.Hash{V0: 0}: &bc.VoteOutput{
+ Source: &bc.ValueSource{
+ Value: &bc.AssetAmount{
+ AssetId: &bc.AssetID{V0: 0},
+ },
+ },
+ },
+}
+
var gasOnlyTxEntry = map[bc.Hash]bc.Entry{
bc.Hash{V1: 0}: &bc.IntraChainOutput{
Source: &bc.ValueSource{
gasOnlyTx: true,
err: false,
},
+ {
+ block: &bc.Block{
+ BlockHeader: &bc.BlockHeader{
+ TransactionStatus: bc.NewTransactionStatus(),
+ },
+ Transactions: []*bc.Tx{
+ &bc.Tx{
+ TxHeader: &bc.TxHeader{
+ ResultIds: []*bc.Hash{},
+ },
+ SpentOutputIDs: []bc.Hash{
+ bc.Hash{V0: 0},
+ },
+ Entries: voteEntry,
+ },
+ },
+ },
+ inputView: &UtxoViewpoint{
+ Entries: map[bc.Hash]*storage.UtxoEntry{
+ bc.Hash{V0: 0}: storage.NewUtxoEntry(storage.VoteUTXOType, 0, false),
+ },
+ },
+ fetchView: &UtxoViewpoint{
+ Entries: map[bc.Hash]*storage.UtxoEntry{
+ bc.Hash{V0: 0}: storage.NewUtxoEntry(storage.VoteUTXOType, 0, true),
+ },
+ },
+ err: true,
+ },
+ {
+ block: &bc.Block{
+ BlockHeader: &bc.BlockHeader{
+ Height: 10001,
+ TransactionStatus: bc.NewTransactionStatus(),
+ },
+ Transactions: []*bc.Tx{
+ &bc.Tx{
+ TxHeader: &bc.TxHeader{
+ ResultIds: []*bc.Hash{},
+ },
+ SpentOutputIDs: []bc.Hash{
+ bc.Hash{V0: 0},
+ },
+ Entries: voteEntry,
+ },
+ },
+ },
+ inputView: &UtxoViewpoint{
+ Entries: map[bc.Hash]*storage.UtxoEntry{
+ bc.Hash{V0: 0}: storage.NewUtxoEntry(storage.VoteUTXOType, 1, false),
+ },
+ },
+ fetchView: &UtxoViewpoint{
+ Entries: map[bc.Hash]*storage.UtxoEntry{
+ bc.Hash{V0: 0}: storage.NewUtxoEntry(storage.VoteUTXOType, 1, true),
+ },
+ },
+ err: false,
+ },
}
for i, c := range cases {
gasOnlyTx: true,
err: false,
},
+ {
+ block: &bc.Block{
+ BlockHeader: &bc.BlockHeader{
+ TransactionStatus: bc.NewTransactionStatus(),
+ },
+ Transactions: []*bc.Tx{
+ &bc.Tx{
+ TxHeader: &bc.TxHeader{
+ ResultIds: []*bc.Hash{},
+ },
+ SpentOutputIDs: []bc.Hash{
+ bc.Hash{V0: 0},
+ },
+ Entries: voteEntry,
+ },
+ },
+ },
+ inputView: NewUtxoViewpoint(),
+ fetchView: &UtxoViewpoint{
+ Entries: map[bc.Hash]*storage.UtxoEntry{
+ bc.Hash{V0: 0}: storage.NewUtxoEntry(storage.VoteUTXOType, 0, false),
+ },
+ },
+ err: false,
+ },
}
for i, c := range cases {