ceremonyclient/node/execution/intrinsics/compute/compute_intrinsic_code_deployment.go
Cassandra Heart ce4f77b140
v2.1.0.19 (#515)
* v2.1.0.19

* enhanced error logging, fix seniority marker join blocker, fix sync message size limit defaults

* resolve signature failure

* additional error logging for merge-related signatures

* fix: one-shot sync message size, app shard TC signature size, collector/hotstuff race condition, expired joins blocking new joins due to pruning disable

* remove compat with old 2.0.0 blossomsub

* fix: resolve abandoned prover joins

* reload prover registry

* fix stale worker proposal edge

* add full sanity check on join before submitting to identify bug

* resolve non-fallthrough condition that should be fallthrough

* fix: resolve rare SIGFPE, fix orphan expired joins blocking workers from reallocating

* add reconnect fallback if no peers are found with variable reconnect time (#511)

Co-authored-by: Tyler Sturos <55340199+tjsturos@users.noreply.github.com>

* update base peer count to 1 (#513)

* fix: expired prover join frames, starting port ranges, proposer getting stuck, and seniority on joins

* fix: panic on shutdown, libp2p discovery picking inaccessible peers, coverage event check not in shutdown logic, amend app shard worker behavior to mirror global for prover root reconciliation

* fix: shutdown scenario quirks, reload hanging

* fix: do not bailout early on shutdown of coverage check

* fix: force registry refresh on worker waiting for registration

* add more logging to wait for prover

* fix: worker manager refreshes the filter on allocation, snapshots blocking close on shutdown

* tweak: force shutdown after five seconds for app worker

* fix: don't loop when shutting down

* fix: slight reordering, also added named workers to trace hanging shutdowns

* use deterministic key for peer id of workers to stop flagging workers as sybil attacks

* fix: remove pubsub stop from app consensus engine as it shouldn't manage pubsub lifecycle, integrate shutdown context to PerformSync to prevent stuck syncs from halting respawn

* fix: blossomsub pubsub interface does not properly track subscription status

* fix: subscribe order to avoid nil panic

* switch from dnsaddr to dns4

* add missing quic-v1

* additional logging to isolate respawn quirks

* fix: dnsaddr -> dns4 for blossomsub

* sort-of fix: apply sledgehammer to restart logic

* fix: restore proper respawn logic, fix frozen hypergraph post respawn, unsubscribe from bitmask previously missing

---------

Co-authored-by: winged-pegasus <55340199+winged-pegasus@users.noreply.github.com>
Co-authored-by: Tyler Sturos <55340199+tjsturos@users.noreply.github.com>
2026-02-26 04:20:13 -06:00

194 lines
4.5 KiB
Go

package compute
import (
"bytes"
"math/big"
"slices"
"github.com/iden3/go-iden3-crypto/poseidon"
"github.com/pkg/errors"
hg "source.quilibrium.com/quilibrium/monorepo/node/execution/state/hypergraph"
"source.quilibrium.com/quilibrium/monorepo/types/compiler"
"source.quilibrium.com/quilibrium/monorepo/types/execution/intrinsics"
"source.quilibrium.com/quilibrium/monorepo/types/execution/state"
qcrypto "source.quilibrium.com/quilibrium/monorepo/types/tries"
)
// CodeDeployment represents a code deployment operation
type CodeDeployment struct {
// The QCL circuit to deploy
Circuit []byte
// The QCL types/classes of the main arguments, 0 - garbler, 1 - evaluator
InputTypes [2]string
// The QCL types/classes of the output values
OutputTypes []string
// The app address
Domain [32]byte
inputQCLSource []byte
inputSizes [2][]int
compiler compiler.CircuitCompiler
}
// NewCodeDeployment creates a new code deployment
func NewCodeDeployment(
domain [32]byte,
sourceCode []byte,
inputTypes [2]string,
inputSizes [2][]int,
outputTypes []string,
compiler compiler.CircuitCompiler,
) (*CodeDeployment, error) {
return &CodeDeployment{
inputQCLSource: sourceCode, // buildutils:allow-slice-alias slice is static
Domain: domain,
InputTypes: inputTypes,
OutputTypes: outputTypes, // buildutils:allow-slice-alias slice is static
inputSizes: inputSizes,
compiler: compiler,
}, nil
}
// GetCost implements intrinsics.IntrinsicOperation
func (c *CodeDeployment) GetCost() (*big.Int, error) {
// Cost based on code size
return big.NewInt(int64(len(c.Circuit))), nil
}
// Prove implements intrinsics.IntrinsicOperation
func (c *CodeDeployment) Prove(frameNumber uint64) (err error) {
defer func() {
if r := recover(); r != nil {
err = errors.Wrap(
errors.New("panic encountered while proving code"),
"prove",
)
}
}()
compiledCircuit, err := c.compiler.Compile(
string(c.inputQCLSource),
c.inputSizes[:],
)
if err != nil {
return errors.Wrap(err, "verify")
}
buf := new(bytes.Buffer)
if err = compiledCircuit.Marshal(buf); err != nil {
return errors.Wrap(err, "verify")
}
out := buf.Bytes()
c.Circuit = out
return nil
}
func (c *CodeDeployment) GetReadAddresses(
frameNumber uint64,
) ([][]byte, error) {
return nil, nil
}
func (c *CodeDeployment) GetWriteAddresses(
frameNumber uint64,
) ([][]byte, error) {
// Get the domain from the hypergraph
domain := c.Domain
// Generate a unique address for this code file
codeAddressBI, err := poseidon.HashBytes(
slices.Concat(
domain[:],
c.Circuit,
),
)
if err != nil {
return nil, errors.Wrap(err, "get write addresses")
}
codeAddress := codeAddressBI.FillBytes(make([]byte, 32))
codeFullAddress := [64]byte{}
copy(codeFullAddress[:32], c.Domain[:])
copy(codeFullAddress[32:], codeAddress)
return [][]byte{codeFullAddress[:]}, nil
}
// Verify implements intrinsics.IntrinsicOperation
func (c *CodeDeployment) Verify(frameNumber uint64) (bool, error) {
buf := bytes.NewReader(c.Circuit)
err := c.compiler.ValidateCircuit(buf)
if err != nil {
return false, errors.Wrap(err, "verify: invalid code deployment")
}
return true, nil
}
// Materialize implements intrinsics.IntrinsicOperation
func (c *CodeDeployment) Materialize(
frameNumber uint64,
state state.State,
) (state.State, error) {
hypergraph, ok := state.(*hg.HypergraphState)
if !ok {
return nil, errors.Wrap(errors.New("invalid state type"), "materialize")
}
// Get the domain from the hypergraph
domain := c.Domain
// Generate a unique address for this code file
codeAddressBI, err := poseidon.HashBytes(
slices.Concat(
domain[:],
c.Circuit,
),
)
if err != nil {
return nil, errors.Wrap(err, "materialize")
}
codeAddress := codeAddressBI.FillBytes(make([]byte, 32))
// Create a tree to store the code
codeTree := &qcrypto.VectorCommitmentTree{}
// Store the code content
if err := codeTree.Insert(
[]byte{0 << 2}, // Index 0
c.Circuit,
nil,
big.NewInt(int64(len(c.Circuit))),
); err != nil {
return nil, errors.Wrap(err, "materialize")
}
// Create the materialized state
value := hypergraph.NewVertexAddMaterializedState(
[32]byte(domain),
[32]byte(codeAddress),
frameNumber,
nil,
codeTree,
)
// Set the state
err = hypergraph.Set(
domain[:],
codeAddress,
hg.VertexAddsDiscriminator,
frameNumber,
value,
)
if err != nil {
return nil, errors.Wrap(err, "materialize")
}
return hypergraph, nil
}
var _ intrinsics.IntrinsicOperation = (*CodeDeployment)(nil)