micw/server/core/block.go

77 lines
1.8 KiB
Go
Raw Normal View History

2024-11-17 21:24:19 +00:00
package core
import (
"crypto/sha512"
2024-11-24 14:04:52 +00:00
"encoding/binary"
"github.com/matchsystems/werr"
2024-11-17 21:24:19 +00:00
"mic-wallet/common"
2024-11-24 14:04:52 +00:00
"mic-wallet/server/repository/entities"
2024-11-17 21:24:19 +00:00
"sync"
)
type Block struct {
2024-11-24 14:04:52 +00:00
Id int64
PrevHash []byte
Hash []byte
TXs map[string]*common.NewTxOpts
// If there is some transactions added after block is finished
TXsLeftOver map[string]*common.NewTxOpts
2024-11-17 21:24:19 +00:00
IgnoreSignatures map[string]struct{}
Lock *sync.RWMutex
2024-11-24 14:04:52 +00:00
IsFinished bool
2024-11-17 21:24:19 +00:00
}
2024-11-24 14:04:52 +00:00
func NewBlock(id int64, prevHash []byte,
prevTxsLeftOver map[string]*common.NewTxOpts, txsLeftOver map[string]*common.NewTxOpts) *Block {
2024-11-17 21:24:19 +00:00
return &Block{
2024-11-24 14:04:52 +00:00
Id: id,
2024-11-17 21:24:19 +00:00
IgnoreSignatures: make(map[string]struct{}),
2024-11-24 14:04:52 +00:00
TXs: prevTxsLeftOver,
TXsLeftOver: txsLeftOver,
2024-11-17 21:24:19 +00:00
Lock: &sync.RWMutex{},
PrevHash: prevHash,
}
}
func (b *Block) AddTx(tx *common.NewTxOpts) error {
b.Lock.Lock()
sigStr := tx.SignatureString()
2024-11-24 14:04:52 +00:00
hashStr := tx.HashString()
2024-11-17 21:24:19 +00:00
if _, ok := b.IgnoreSignatures[sigStr]; ok {
2024-11-24 14:04:52 +00:00
return werr.Wrapf(common.ErrEntityExists,
"transaction with signature %s already exists", sigStr)
}
if !b.IsFinished {
b.TXs[hashStr] = tx
} else {
b.TXsLeftOver[hashStr] = tx
2024-11-17 21:24:19 +00:00
}
b.Lock.Unlock()
return nil
}
2024-11-24 14:04:52 +00:00
func (b *Block) Finish() ([]byte, error) {
2024-11-17 21:24:19 +00:00
hash := sha512.New()
2024-11-24 14:04:52 +00:00
if err := binary.Write(hash, binary.BigEndian, b.Id); err != nil {
return nil, werr.Wrapf(err, "failed to write block id into hash buffer for block %d", b.Id)
}
2024-11-17 21:24:19 +00:00
b.Lock.Lock()
hash.Write(b.PrevHash)
for _, tx := range b.TXs {
hash.Write(tx.Hash)
}
2024-11-24 14:04:52 +00:00
b.IsFinished = true
b.Lock.Unlock()
2024-11-17 21:24:19 +00:00
b.Hash = hash.Sum(nil)
2024-11-24 14:04:52 +00:00
return b.Hash, nil
}
func (b *Block) ToRepoEntity() *entities.Block {
return &entities.Block{
Id: b.Id,
Hash: b.Hash,
PrevHash: b.PrevHash,
}
2024-11-17 21:24:19 +00:00
}