mirror of
https://github.com/luxfi/chains.git
synced 2026-09-24 00:26:00 +00:00
Continuation of dc31d5b (quantumvm consumer-side leak after consensus
repo migration) — the rename was incomplete; this pass closes it.
Identifier renames in chains/{quantumvm,thresholdvm,dexvm}:
- NTTForwardRingtail / NTTInverseRingtail / BatchNTTForwardRingtail
→ NTTForward/Inverse/BatchNTTForwardCorona (Quasar GPU dispatch)
- LaneRingtail (CertLane enum)
→ LaneCorona
- ProtocolRingtail (Protocol enum)
→ ProtocolCorona (string value already "corona")
- All Ringtail-prefixed local identifiers in quantumvm/{quasar,
quasar_witness,block,vm,vm_test,signer,stamper,service}.go,
thresholdvm/{client,protocols,rpc,types/{ceremony,share},
runtime/m_chain_adapter,cert/lane_test,protocol_executor_test}.go,
dexvm/factory.go
Directory + file rename:
thresholdvm/protocol/ringtail_general/ringtail.go
→ thresholdvm/protocol/corona_general/corona.go
package ringtail_general → package corona_general
evm/main.go: replace single `precompile/ringtail` blank-import with
the canonical LP-4200 unified PQCrypto block (mlkem 0x012201,
mldsa 0x012202, slhdsa 0x012203, pulsar 0x012204, p3q 0x012205,
corona 0x012206) + xwing.
External test that imports threshold's renamed wrapper:
thresholdvm/protocol_executor_test.go now imports
"github.com/luxfi/threshold/protocols/corona" (was protocols/ringtail).
Resolves via the workspace `./threshold` entry pointing at the
local renamed wrapper; downstream chains/go.mod still pins
luxfi/threshold v1.5.5 and will tidy clean once threshold cuts the
next tag.
Build: go build ./... PASS (only harmless duplicate-rpath warnings
from the cevm cgo link).
Tests:
thresholdvm + subpackages PASS
quantumvm PASS
213 lines
5.0 KiB
Go
213 lines
5.0 KiB
Go
// Copyright (C) 2019-2025, Lux Industries Inc. All rights reserved.
|
|
// See the file LICENSE for licensing terms.
|
|
|
|
package quantumvm
|
|
|
|
import (
|
|
"context"
|
|
"encoding/binary"
|
|
"errors"
|
|
"time"
|
|
|
|
"github.com/luxfi/ids"
|
|
"github.com/luxfi/chains/quantumvm/quantum"
|
|
)
|
|
|
|
var (
|
|
errBlockVerificationFailed = errors.New("block verification failed")
|
|
errInvalidBlockHeight = errors.New("invalid block height")
|
|
errInvalidParentID = errors.New("invalid parent ID")
|
|
)
|
|
|
|
// Block represents a QVM block with quantum features
|
|
type Block struct {
|
|
id ids.ID
|
|
timestamp time.Time
|
|
height uint64
|
|
parentID ids.ID
|
|
transactions []Transaction
|
|
quantumSignature *quantum.QuantumSignature
|
|
vm *VM
|
|
bytes []byte
|
|
}
|
|
|
|
// ID returns the block ID
|
|
func (b *Block) ID() ids.ID {
|
|
return b.id
|
|
}
|
|
|
|
// Accept marks the block as accepted
|
|
func (b *Block) Accept(context.Context) error {
|
|
b.vm.lock.Lock()
|
|
defer b.vm.lock.Unlock()
|
|
|
|
// Store block in database
|
|
if err := b.vm.state.Put(b.id[:], b.Bytes()); err != nil {
|
|
return err
|
|
}
|
|
|
|
// Update last accepted
|
|
if err := b.vm.state.Put([]byte("lastAccepted"), b.id[:]); err != nil {
|
|
return err
|
|
}
|
|
|
|
// Update height
|
|
heightBytes := make([]byte, 8)
|
|
binary.BigEndian.PutUint64(heightBytes, b.height)
|
|
if err := b.vm.state.Put([]byte("height"), heightBytes); err != nil {
|
|
return err
|
|
}
|
|
|
|
// Process transactions
|
|
for _, tx := range b.transactions {
|
|
if err := b.vm.txPool.RemoveTransaction(tx.ID()); err != nil {
|
|
b.vm.log.Error("failed to remove tx from pool", "txID", tx.ID(), "error", err)
|
|
}
|
|
}
|
|
|
|
b.vm.log.Info("block accepted",
|
|
"blockID", b.id,
|
|
"height", b.height,
|
|
"txCount", len(b.transactions),
|
|
)
|
|
|
|
return nil
|
|
}
|
|
|
|
// Reject marks the block as rejected
|
|
func (b *Block) Reject(context.Context) error {
|
|
b.vm.lock.Lock()
|
|
defer b.vm.lock.Unlock()
|
|
|
|
// Return transactions to pool
|
|
for _, tx := range b.transactions {
|
|
if err := b.vm.txPool.AddTransaction(tx); err != nil {
|
|
b.vm.log.Error("failed to return tx to pool", "txID", tx.ID(), "error", err)
|
|
}
|
|
}
|
|
|
|
b.vm.log.Debug("block rejected", "blockID", b.id, "height", b.height)
|
|
return nil
|
|
}
|
|
|
|
// Verify verifies the block validity
|
|
func (b *Block) Verify(ctx context.Context) error {
|
|
b.vm.lock.RLock()
|
|
defer b.vm.lock.RUnlock()
|
|
|
|
// Verify height
|
|
if b.height == 0 {
|
|
return errInvalidBlockHeight
|
|
}
|
|
|
|
// Verify parent exists (except for genesis)
|
|
if b.height > 1 {
|
|
if _, err := b.vm.GetBlock(ctx, b.parentID); err != nil {
|
|
return errInvalidParentID
|
|
}
|
|
}
|
|
|
|
// Verify quantum signature if enabled
|
|
if b.vm.Config.QuantumStampEnabled {
|
|
if b.quantumSignature == nil {
|
|
return errInvalidQuantumStamp
|
|
}
|
|
if err := b.vm.quantumSigner.Verify(b.Bytes(), b.quantumSignature); err != nil {
|
|
return errBlockVerificationFailed
|
|
}
|
|
}
|
|
|
|
// Verify transactions in parallel
|
|
if len(b.transactions) > 0 {
|
|
msgs := make([][]byte, len(b.transactions))
|
|
sigs := make([]*quantum.QuantumSignature, len(b.transactions))
|
|
|
|
for i, tx := range b.transactions {
|
|
msgs[i] = tx.Bytes()
|
|
sigs[i] = tx.GetQuantumSignature()
|
|
}
|
|
|
|
if b.vm.Config.CoronaEnabled {
|
|
if err := b.vm.quantumSigner.ParallelVerify(msgs, sigs); err != nil {
|
|
return errBlockVerificationFailed
|
|
}
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// Parent returns the parent block ID
|
|
func (b *Block) Parent() ids.ID {
|
|
return b.parentID
|
|
}
|
|
|
|
// ParentID returns the parent block ID (implements consensus Block interface)
|
|
func (b *Block) ParentID() ids.ID {
|
|
return b.parentID
|
|
}
|
|
|
|
// Height returns the block height
|
|
func (b *Block) Height() uint64 {
|
|
return b.height
|
|
}
|
|
|
|
// Timestamp returns the block timestamp (implements block.Block interface)
|
|
func (b *Block) Timestamp() time.Time {
|
|
return b.timestamp
|
|
}
|
|
|
|
// TimestampUnix returns the block timestamp as Unix seconds.
|
|
func (b *Block) TimestampUnix() int64 {
|
|
return b.timestamp.Unix()
|
|
}
|
|
|
|
// Status returns the block status. Q-Chain does not yet track per-block
|
|
// status separately (all blocks reaching here are processing or accepted),
|
|
// so we return 0 (Unknown) until a status field is added.
|
|
func (b *Block) Status() uint8 {
|
|
return 0
|
|
}
|
|
|
|
// Bytes returns the block bytes
|
|
func (b *Block) Bytes() []byte {
|
|
if b.bytes != nil {
|
|
return b.bytes
|
|
}
|
|
|
|
// Serialize block
|
|
size := 32 + 8 + 8 + 32 + 4 // id + timestamp + height + parentID + tx count
|
|
for _, tx := range b.transactions {
|
|
size += len(tx.Bytes())
|
|
}
|
|
|
|
bytes := make([]byte, 0, size)
|
|
bytes = append(bytes, b.id[:]...)
|
|
|
|
timestampBytes := make([]byte, 8)
|
|
binary.BigEndian.PutUint64(timestampBytes, uint64(b.timestamp.Unix()))
|
|
bytes = append(bytes, timestampBytes...)
|
|
|
|
heightBytes := make([]byte, 8)
|
|
binary.BigEndian.PutUint64(heightBytes, b.height)
|
|
bytes = append(bytes, heightBytes...)
|
|
|
|
bytes = append(bytes, b.parentID[:]...)
|
|
|
|
txCountBytes := make([]byte, 4)
|
|
binary.BigEndian.PutUint32(txCountBytes, uint32(len(b.transactions)))
|
|
bytes = append(bytes, txCountBytes...)
|
|
|
|
for _, tx := range b.transactions {
|
|
bytes = append(bytes, tx.Bytes()...)
|
|
}
|
|
|
|
b.bytes = bytes
|
|
return bytes
|
|
}
|
|
|
|
// String returns a string representation of the block
|
|
func (b *Block) String() string {
|
|
return b.id.String()
|
|
}
|