forked from TrueCloudLab/neoneo-go
parent
30e5aa8f48
commit
7d84d44b08
1 changed files with 91 additions and 0 deletions
91
pkg/chain/chain.go
Normal file
91
pkg/chain/chain.go
Normal file
|
@ -0,0 +1,91 @@
|
|||
package chain
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/CityOfZion/neo-go/pkg/wire/payload/transaction"
|
||||
|
||||
"github.com/CityOfZion/neo-go/pkg/database"
|
||||
"github.com/CityOfZion/neo-go/pkg/wire/payload"
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrBlockAlreadyExists happens when you try to save the same block twice
|
||||
ErrBlockAlreadyExists = errors.New("this block has already been saved in the database")
|
||||
)
|
||||
|
||||
// Chain represents a blockchain instance
|
||||
type Chain struct {
|
||||
db *Chaindb
|
||||
}
|
||||
|
||||
//New returns a new chain instance
|
||||
func New(db database.Database) *Chain {
|
||||
return &Chain{
|
||||
db: &Chaindb{db},
|
||||
}
|
||||
}
|
||||
|
||||
// SaveBlock verifies and saves the block in the database
|
||||
// XXX: for now we will just save without verifying the block
|
||||
// This function is called by the server and if an error is returned then
|
||||
// the server informs the sync manager to redownload the block
|
||||
// XXX:We should also check if the header is already saved in the database
|
||||
// If not, then we need to validate the header with the rest of the chain
|
||||
// For now we re-save the header
|
||||
func (c *Chain) SaveBlock(msg payload.BlockMessage) error {
|
||||
err := c.VerifyBlock(msg.Block)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
//XXX(Issue): We can either check the hash here for genesisblock.
|
||||
//We most likely will have it anyways after validation/ We can return it from VerifyBlock
|
||||
// Or we can do it somewhere in startup, performance benefits
|
||||
// won't be that big since it's just a bytes.Equal.
|
||||
// so it's more about which is more readable and where it makes sense to put
|
||||
return c.db.saveBlock(msg.Block, false)
|
||||
}
|
||||
|
||||
// VerifyBlock verifies whether a block is valid according
|
||||
// to the rules of consensus
|
||||
func (c *Chain) VerifyBlock(block payload.Block) error {
|
||||
|
||||
// Check if we already have this block
|
||||
// XXX: We can optimise by implementing a Has method
|
||||
// caching the last block in memory
|
||||
lastBlock, err := c.db.GetLastBlock()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Check if we have already saved this block
|
||||
// by looking if the latest block height is more than
|
||||
// incoming block height
|
||||
if lastBlock.Index > block.Index {
|
||||
return ErrBlockAlreadyExists
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// VerifyTx verifies whether a transaction is valid according
|
||||
// to the rules of consensus
|
||||
func (c *Chain) VerifyTx(tx transaction.Transactioner) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// SaveHeaders will save the set of headers without validating
|
||||
func (c *Chain) SaveHeaders(msg payload.HeadersMessage) error {
|
||||
|
||||
err := c.verifyHeaders(msg.Headers)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return c.db.saveHeaders(msg.Headers)
|
||||
}
|
||||
|
||||
// verifyHeaders will be used to verify a batch of headers
|
||||
// should only ever be called during the initial block download
|
||||
// or when the node receives a HeadersMessage
|
||||
func (c *Chain) verifyHeaders(hdrs []*payload.BlockBase) error {
|
||||
return nil
|
||||
}
|
Loading…
Reference in a new issue