lbcd/claimtrie/change/change.go

114 lines
2.7 KiB
Go

package change
import (
"bytes"
"encoding/binary"
"github.com/lbryio/lbcd/chaincfg/chainhash"
"github.com/lbryio/lbcd/wire"
)
type ChangeType uint32
const (
AddClaim ChangeType = iota
SpendClaim
UpdateClaim
AddSupport
SpendSupport
)
type Change struct {
Type ChangeType
Height int32
Name []byte
ClaimID ClaimID
OutPoint wire.OutPoint
Amount int64
ActiveHeight int32
VisibleHeight int32 // aka, CreatedAt; used for normalization fork
SpentChildren map[string]bool
}
func NewChange(typ ChangeType) Change {
return Change{Type: typ}
}
func (c Change) SetHeight(height int32) Change {
c.Height = height
return c
}
func (c Change) SetName(name []byte) Change {
c.Name = name // need to clone it?
return c
}
func (c Change) SetOutPoint(op *wire.OutPoint) Change {
c.OutPoint = *op
return c
}
func (c Change) SetAmount(amt int64) Change {
c.Amount = amt
return c
}
func (c *Change) Marshal(enc *bytes.Buffer) error {
enc.Write(c.ClaimID[:])
enc.Write(c.OutPoint.Hash[:])
var temp [8]byte
binary.BigEndian.PutUint32(temp[:4], c.OutPoint.Index)
enc.Write(temp[:4])
binary.BigEndian.PutUint32(temp[:4], uint32(c.Type))
enc.Write(temp[:4])
binary.BigEndian.PutUint32(temp[:4], uint32(c.Height))
enc.Write(temp[:4])
binary.BigEndian.PutUint32(temp[:4], uint32(c.ActiveHeight))
enc.Write(temp[:4])
binary.BigEndian.PutUint32(temp[:4], uint32(c.VisibleHeight))
enc.Write(temp[:4])
binary.BigEndian.PutUint64(temp[:], uint64(c.Amount))
enc.Write(temp[:])
if c.SpentChildren != nil {
binary.BigEndian.PutUint32(temp[:4], uint32(len(c.SpentChildren)))
enc.Write(temp[:4])
for key := range c.SpentChildren {
keySize := uint16(len(key))
binary.BigEndian.PutUint16(temp[:2], keySize) // technically limited to 255; not sure we trust it
enc.Write(temp[:2])
enc.WriteString(key[:keySize])
}
} else {
binary.BigEndian.PutUint32(temp[:4], 0)
enc.Write(temp[:4])
}
return nil
}
func (c *Change) Unmarshal(dec *bytes.Buffer) error {
copy(c.ClaimID[:], dec.Next(ClaimIDSize))
copy(c.OutPoint.Hash[:], dec.Next(chainhash.HashSize))
c.OutPoint.Index = binary.BigEndian.Uint32(dec.Next(4))
c.Type = ChangeType(binary.BigEndian.Uint32(dec.Next(4)))
c.Height = int32(binary.BigEndian.Uint32(dec.Next(4)))
c.ActiveHeight = int32(binary.BigEndian.Uint32(dec.Next(4)))
c.VisibleHeight = int32(binary.BigEndian.Uint32(dec.Next(4)))
c.Amount = int64(binary.BigEndian.Uint64(dec.Next(8)))
keys := binary.BigEndian.Uint32(dec.Next(4))
if keys > 0 {
c.SpentChildren = map[string]bool{}
}
for keys > 0 {
keys--
keySize := int(binary.BigEndian.Uint16(dec.Next(2)))
key := string(dec.Next(keySize))
c.SpentChildren[key] = true
}
return nil
}