Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Coinbase is an External Transaction and workshare payout is done using these coinbase transactions #1906

Merged
merged 9 commits into from
Jul 9, 2024
3 changes: 2 additions & 1 deletion consensus/blake3pow/consensus.go
Original file line number Diff line number Diff line change
Expand Up @@ -607,7 +607,7 @@ func (blake3pow *Blake3pow) Finalize(chain consensus.ChainHeaderReader, header *
}
state.CreateAccount(lockupContract)

alloc := core.ReadGenesisAlloc("genallocs/gen_quai_alloc_"+nodeLocation.Name()+".json", blake3pow.logger)
alloc := core.ReadGenesisAlloc("genallocs/gen_alloc_quai_"+nodeLocation.Name()+".json", blake3pow.logger)
blake3pow.logger.WithField("alloc", len(alloc)).Info("Allocating genesis accounts")

for addressString, account := range alloc {
Expand All @@ -632,6 +632,7 @@ func (blake3pow *Blake3pow) Finalize(chain consensus.ChainHeaderReader, header *
core.AddGenesisUtxos(state, nodeLocation, addressOutpointMap, blake3pow.logger)
if chain.Config().IndexAddressUtxos {
chain.WriteAddressOutpoints(addressOutpointMap)
blake3pow.logger.Info("Indexed genesis utxos")
}
}
header.Header().SetUTXORoot(state.UTXORoot())
Expand Down
10 changes: 5 additions & 5 deletions consensus/misc/rewards.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import (
"github.com/dominant-strategies/go-quai/core/types"
)

func CalculateReward(header *types.WorkObject) *big.Int {
func CalculateReward(header *types.WorkObjectHeader) *big.Int {
if header.Coinbase().IsInQiLedgerScope() {
return calculateQiReward(header)
} else {
Expand All @@ -15,24 +15,24 @@ func CalculateReward(header *types.WorkObject) *big.Int {
}

// Calculate the amount of Quai that Qi can be converted to. Expect the current Header and the Qi amount in "qits", returns the quai amount in "its"
func QiToQuai(currentHeader *types.WorkObject, qiAmt *big.Int) *big.Int {
func QiToQuai(currentHeader *types.WorkObjectHeader, qiAmt *big.Int) *big.Int {
quaiPerQi := new(big.Int).Div(calculateQuaiReward(currentHeader), calculateQiReward(currentHeader))
return new(big.Int).Mul(qiAmt, quaiPerQi)
}

// Calculate the amount of Qi that Quai can be converted to. Expect the current Header and the Quai amount in "its", returns the Qi amount in "qits"
func QuaiToQi(currentHeader *types.WorkObject, quaiAmt *big.Int) *big.Int {
func QuaiToQi(currentHeader *types.WorkObjectHeader, quaiAmt *big.Int) *big.Int {
qiPerQuai := new(big.Int).Div(calculateQiReward(currentHeader), calculateQuaiReward(currentHeader))
return new(big.Int).Mul(quaiAmt, qiPerQuai)
}

// CalculateQuaiReward calculates the quai that can be recieved for mining a block and returns value in its
func calculateQuaiReward(header *types.WorkObject) *big.Int {
func calculateQuaiReward(header *types.WorkObjectHeader) *big.Int {
return big.NewInt(1000000000000000000)
}

// CalculateQiReward caculates the qi that can be received for mining a block and returns value in qits
func calculateQiReward(header *types.WorkObject) *big.Int {
func calculateQiReward(header *types.WorkObjectHeader) *big.Int {
return big.NewInt(1000)
}

Expand Down
69 changes: 46 additions & 23 deletions core/chain_indexer.go
Original file line number Diff line number Diff line change
Expand Up @@ -200,11 +200,8 @@ func (c *ChainIndexer) eventLoop(currentHeader *types.WorkObject, events chan Ch

// Fire the initial new head event to start any outstanding processing
c.newHead(currentHeader.NumberU64(nodeCtx), false)

var (
prevHeader = currentHeader
prevHash = currentHeader.Hash()
)
qiIndexerCh := make(chan *types.WorkObject, 10000)
go c.indexerLoop(currentHeader, qiIndexerCh, nodeCtx, config)
for {
select {
case errc := <-c.quit:
Expand All @@ -219,21 +216,40 @@ func (c *ChainIndexer) eventLoop(currentHeader *types.WorkObject, events chan Ch
errc <- nil
return
}
header := ev.Block
select {
case qiIndexerCh <- ev.Block:
default:
c.logger.Warn("qiIndexerCh is full, dropping block")
}
}
}
}

func (c *ChainIndexer) indexerLoop(currentHeader *types.WorkObject, qiIndexerCh chan *types.WorkObject, nodeCtx int, config params.ChainConfig) {
var (
prevHeader = currentHeader
prevHash = currentHeader.Hash()
)
for {
select {
case errc := <-c.quit:
// Chain indexer terminating, report no failure and abort
errc <- nil
gameofpointers marked this conversation as resolved.
Show resolved Hide resolved
return
case block := <-qiIndexerCh:
var validUtxoIndex bool
var addressOutpoints map[string]map[string]*types.OutpointAndDenomination
if c.indexAddressUtxos {
validUtxoIndex = true
addressOutpoints = rawdb.ReadAddressOutpoints(c.chainDb, config.Location)
addressOutpoints = make(map[string]map[string]*types.OutpointAndDenomination)
}

if header.ParentHash(nodeCtx) != prevHash {
if block.ParentHash(nodeCtx) != prevHash {
// Reorg to the common ancestor if needed (might not exist in light sync mode, skip reorg then)
// TODO: This seems a bit brittle, can we detect this case explicitly?

if rawdb.ReadCanonicalHash(c.chainDb, prevHeader.NumberU64(nodeCtx)) != prevHash {
if h := rawdb.FindCommonAncestor(c.chainDb, prevHeader, header, nodeCtx); h != nil {
if h := rawdb.FindCommonAncestor(c.chainDb, prevHeader, block, nodeCtx); h != nil {

// If indexAddressUtxos flag is enabled, update the address utxo map
// TODO: Need to be able to turn on/off indexer and fix corrupted state
Expand All @@ -251,7 +267,7 @@ func (c *ChainIndexer) eventLoop(currentHeader *types.WorkObject, events chan Ch
}

// Add new blocks from current hash back to common ancestor
for curr := header; curr.Hash() != h.Hash(); curr = rawdb.ReadHeader(c.chainDb, curr.ParentHash(nodeCtx)) {
for curr := block; curr.Hash() != h.Hash(); curr = rawdb.ReadHeader(c.chainDb, curr.ParentHash(nodeCtx)) {
block := rawdb.ReadWorkObject(c.chainDb, curr.Hash(), types.BlockObject)
c.addOutpointsToIndexer(addressOutpoints, nodeCtx, config, block)
}
Expand All @@ -263,10 +279,10 @@ func (c *ChainIndexer) eventLoop(currentHeader *types.WorkObject, events chan Ch
}

if c.indexAddressUtxos {
c.addOutpointsToIndexer(addressOutpoints, nodeCtx, config, ev.Block)
c.addOutpointsToIndexer(addressOutpoints, nodeCtx, config, block)
}

c.newHead(header.NumberU64(nodeCtx), false)
c.newHead(block.NumberU64(nodeCtx), false)

if c.indexAddressUtxos && validUtxoIndex {
err := rawdb.WriteAddressOutpoints(c.chainDb, addressOutpoints)
Expand All @@ -275,7 +291,7 @@ func (c *ChainIndexer) eventLoop(currentHeader *types.WorkObject, events chan Ch
}
}

prevHeader, prevHash = header, header.Hash()
prevHeader, prevHash = block, block.Hash()
}
}
}
Expand Down Expand Up @@ -546,20 +562,23 @@ func (c *ChainIndexer) removeSectionHead(section uint64) {

// addOutpointsToIndexer removes the spent outpoints and adds new utxos to the indexer.
func (c *ChainIndexer) addOutpointsToIndexer(addressOutpoints map[string]map[string]*types.OutpointAndDenomination, nodeCtx int, config params.ChainConfig, block *types.WorkObject) {
utxos := block.QiTransactions()
utxos := block.QiTransactions() // TODO: Need to add the coinbase outputs into the Indexer

for _, tx := range utxos {
for _, in := range tx.TxIn() {

// Skip Coinbase TxIns since they do not have a previous outpoint
if types.IsCoinBaseTx(tx, block.ParentHash(nodeCtx), config.Location) {
if types.IsCoinBaseTx(tx) {
continue
}

outpoint := in.PreviousOutPoint

address := crypto.PubkeyBytesToAddress(in.PubKey, config.Location).Hex()
outpointsForAddress := addressOutpoints[address]
outpointsForAddress, exists := addressOutpoints[address]
if !exists {
outpointsForAddress = rawdb.ReadOutpointsForAddress(c.chainDb, address)
addressOutpoints[address] = outpointsForAddress
}

delete(outpointsForAddress, outpoint.Key())
}
Expand All @@ -580,8 +599,8 @@ func (c *ChainIndexer) addOutpointsToIndexer(addressOutpoints map[string]map[str
Denomination: out.Denomination,
}

if _, ok := addressOutpoints[address]; !ok {
addressOutpoints[address] = make(map[string]*types.OutpointAndDenomination)
if _, exists := addressOutpoints[address]; !exists {
addressOutpoints[address] = rawdb.ReadOutpointsForAddress(c.chainDb, address)
}
addressOutpoints[address][outpointAndDenom.Key()] = outpointAndDenom
}
Expand All @@ -600,7 +619,11 @@ func (c *ChainIndexer) reorgUtxoIndexer(headers []*types.WorkObject, addressOutp
address := out.Address

addr := common.BytesToAddress(address, config.Location).Hex()
outpointsForAddress := addressOutpoints[addr]
outpointsForAddress, exists := addressOutpoints[addr]
if !exists {
outpointsForAddress = rawdb.ReadOutpointsForAddress(c.chainDb, addr)
addressOutpoints[addr] = outpointsForAddress
}

// reconstruct outpoint to remove it via outpoint.Key()
outpoint := types.OutPoint{
Expand All @@ -611,7 +634,7 @@ func (c *ChainIndexer) reorgUtxoIndexer(headers []*types.WorkObject, addressOutp
delete(outpointsForAddress, outpoint.Key())
}

if types.IsCoinBaseTx(tx, block.ParentHash(nodeCtx), config.Location) {
if types.IsCoinBaseTx(tx) {
continue
}

Expand All @@ -638,8 +661,8 @@ func (c *ChainIndexer) reorgUtxoIndexer(headers []*types.WorkObject, addressOutp
Denomination: entry.Denomination,
}

if _, ok := addressOutpoints[address]; !ok {
addressOutpoints[address] = make(map[string]*types.OutpointAndDenomination)
if _, exists := addressOutpoints[address]; !exists {
addressOutpoints[address] = rawdb.ReadOutpointsForAddress(c.chainDb, address)
}
addressOutpoints[address][outpointAndDenom.Key()] = outpointAndDenom
}
Expand Down
6 changes: 2 additions & 4 deletions core/core.go
Original file line number Diff line number Diff line change
Expand Up @@ -600,7 +600,7 @@ func (c *Core) WriteBlock(block *types.WorkObject) {
func (c *Core) Append(header *types.WorkObject, manifest types.BlockManifest, domPendingHeader *types.WorkObject, domTerminus common.Hash, domOrigin bool, newInboundEtxs types.Transactions) (types.Transactions, bool, bool, error) {
nodeCtx := c.NodeCtx()
// Set the coinbase into the right interface before calling append in the sub
header.Header().SetCoinbase(common.BytesToAddress(header.Coinbase().Bytes(), c.NodeLocation()))
header.WorkObjectHeader().SetCoinbase(common.BytesToAddress(header.Coinbase().Bytes(), c.NodeLocation()))
jdowning100 marked this conversation as resolved.
Show resolved Hide resolved
newPendingEtxs, subReorg, setHead, err := c.sl.Append(header, domPendingHeader, domTerminus, domOrigin, newInboundEtxs)
if err != nil {
if err.Error() == ErrBodyNotFound.Error() || err.Error() == consensus.ErrUnknownAncestor.Error() || err.Error() == ErrSubNotSyncedToDom.Error() {
Expand Down Expand Up @@ -1155,9 +1155,7 @@ func (c *Core) TrieNode(hash common.Hash) ([]byte, error) {
}

func (c *Core) GetOutpointsByAddress(address common.Address) map[string]*types.OutpointAndDenomination {
outpoints := rawdb.ReadAddressOutpoints(c.sl.hc.bc.db, c.sl.hc.NodeLocation())
outpointsForAddress := outpoints[address.Hex()]
return outpointsForAddress
return rawdb.ReadOutpointsForAddress(c.sl.sliceDb, address.Hex())
}

func (c *Core) GetUTXOsByAddressAtState(state *state.StateDB, address common.Address) ([]*types.UtxoEntry, error) {
Expand Down
19 changes: 14 additions & 5 deletions core/evm.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ type ChainContext interface {
}

// NewEVMBlockContext creates a new context for use in the EVM.
func NewEVMBlockContext(header *types.WorkObject, chain ChainContext, author *common.Address) (vm.BlockContext, error) {
func NewEVMBlockContext(header *types.WorkObject, parent *types.WorkObject, chain ChainContext, author *common.Address) (vm.BlockContext, error) {
var (
beneficiary common.Address
baseFee *big.Int
Expand Down Expand Up @@ -81,10 +81,19 @@ func NewEVMBlockContext(header *types.WorkObject, chain ChainContext, author *co

// Prime terminus determines which location is eligible to accept the etx
primeTerminus := header.PrimeTerminus()
primeTerminusHeader := chain.GetHeaderByHash(primeTerminus)
if primeTerminusHeader == nil {
log.Global.Error("Prime terminus header not found ", " headerHash ", header.Hash(), " primeTerminus ", primeTerminus)
return vm.BlockContext{}, ErrSubNotSyncedToDom
_, parentOrder, err := chain.Engine().CalcOrder(parent)
if err != nil {
return vm.BlockContext{}, fmt.Errorf("parent order cannot be calculated")
}
var primeTerminusHeader *types.WorkObject
if parentOrder == common.PRIME_CTX {
primeTerminusHeader = parent
} else {
primeTerminusHeader = chain.GetHeaderByHash(primeTerminus)
if primeTerminusHeader == nil {
log.Global.Error("Prime terminus header not found", "headerHash", header.Hash(), "primeTerminus", primeTerminus)
return vm.BlockContext{}, ErrSubNotSyncedToDom
}
}
etxEligibleSlices := primeTerminusHeader.EtxEligibleSlices()

Expand Down
2 changes: 1 addition & 1 deletion core/genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,7 @@ func (g *Genesis) ToBlock(startingExpansionNumber uint64) *types.WorkObject {
wo.WorkObjectHeader().SetNonce(types.EncodeNonce(g.Nonce))
wo.WorkObjectHeader().SetDifficulty(g.Difficulty)
wo.WorkObjectHeader().SetTime(g.Timestamp)
wo.WorkObjectHeader().SetCoinbase(common.Zero)
wo.Header().SetExtra(g.ExtraData)
wo.Header().SetGasLimit(g.GasLimit)
wo.Header().SetGasUsed(0)
Expand All @@ -285,7 +286,6 @@ func (g *Genesis) ToBlock(startingExpansionNumber uint64) *types.WorkObject {
} else {
wo.Header().SetEtxEligibleSlices(common.Hash{})
}
wo.Header().SetCoinbase(common.Zero)
wo.Header().SetBaseFee(new(big.Int).SetUint64(params.InitialBaseFee))
wo.Header().SetEtxSetRoot(types.EmptyRootHash)
if g.GasLimit == 0 {
Expand Down
Loading
Loading