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