ceremonyclient/node/rpc/data_worker_ipc_server.go

242 lines
5.7 KiB
Go
Raw Normal View History

package rpc
import (
"context"
"encoding/binary"
"os"
"runtime"
"syscall"
"time"
"source.quilibrium.com/quilibrium/monorepo/node/crypto"
2024-10-14 01:37:19 +00:00
"source.quilibrium.com/quilibrium/monorepo/node/execution/intrinsics/token"
"source.quilibrium.com/quilibrium/monorepo/node/p2p"
"github.com/multiformats/go-multiaddr"
mn "github.com/multiformats/go-multiaddr/net"
"github.com/pkg/errors"
"go.uber.org/zap"
"google.golang.org/grpc"
"google.golang.org/grpc/reflection"
"google.golang.org/protobuf/proto"
"source.quilibrium.com/quilibrium/monorepo/node/protobufs"
)
type DataWorkerIPCServer struct {
protobufs.UnimplementedDataIPCServiceServer
listenAddrGRPC string
logger *zap.Logger
coreId uint32
prover crypto.FrameProver
indices []int
parentProcessId int
}
// GetFrameInfo implements protobufs.NodeServiceServer.
func (r *DataWorkerIPCServer) CalculateChallengeProof(
ctx context.Context,
req *protobufs.ChallengeProofRequest,
) (*protobufs.ChallengeProofResponse, error) {
challenge := []byte{}
challenge = append(challenge, req.PeerId...)
challenge = binary.BigEndian.AppendUint64(
challenge,
req.ClockFrame.FrameNumber,
)
found := false
for _, proof := range req.ClockFrame.AggregateProofs {
for _, c := range proof.InclusionCommitments {
o := &protobufs.IntrinsicExecutionOutput{}
err := proto.Unmarshal(c.Data, o)
if err != nil {
return nil, err
}
outputs := &protobufs.TokenOutputs{}
err = proto.Unmarshal(o.Output, outputs)
if err != nil {
return nil, err
}
inRange:
for _, out := range outputs.Outputs {
switch e := out.Output.(type) {
case *protobufs.TokenOutput_Coin:
2024-10-14 01:37:19 +00:00
addr, err := token.GetAddressOfCoin(
e.Coin,
req.ClockFrame.FrameNumber,
)
if err != nil {
return nil, err
}
for _, idx := range p2p.GetOnesIndices(
p2p.GetBloomFilter(
2024-10-14 01:37:19 +00:00
addr,
1024,
64,
),
) {
for _, i := range r.indices {
if i == idx {
challenge = append(challenge, req.ClockFrame.Filter...)
challenge = append(challenge, req.ClockFrame.Input...)
challenge = append(challenge, c.Data...)
found = true
break inRange
}
}
}
case *protobufs.TokenOutput_DeletedCoin:
for _, idx := range p2p.GetOnesIndices(
p2p.GetBloomFilter(
2024-10-14 01:37:19 +00:00
e.DeletedCoin.Address,
1024,
64,
),
) {
for _, i := range r.indices {
if i == idx {
challenge = append(challenge, req.ClockFrame.Filter...)
challenge = append(challenge, req.ClockFrame.Input...)
challenge = append(challenge, c.Data...)
found = true
break inRange
}
}
}
case *protobufs.TokenOutput_DeletedProof:
for _, idx := range p2p.GetOnesIndices(
p2p.GetBloomFilter(
e.DeletedProof.Owner.GetImplicitAccount().Address,
1024,
64,
),
) {
for _, i := range r.indices {
if i == idx {
challenge = append(challenge, req.ClockFrame.Filter...)
challenge = append(challenge, req.ClockFrame.Input...)
challenge = append(challenge, c.Data...)
found = true
break inRange
}
}
}
case *protobufs.TokenOutput_Proof:
for _, idx := range p2p.GetOnesIndices(
p2p.GetBloomFilter(
e.Proof.Owner.GetImplicitAccount().Address,
1024,
64,
),
) {
for _, i := range r.indices {
if i == idx {
challenge = append(challenge, req.ClockFrame.Filter...)
challenge = append(challenge, req.ClockFrame.Input...)
challenge = append(challenge, c.Data...)
found = true
break inRange
}
}
}
}
}
}
}
if !found {
return nil, errors.Wrap(
errors.New("no applicable challenge"),
"calculate challenge proof",
)
}
2024-06-08 11:32:45 +00:00
proof, err := r.prover.CalculateChallengeProof(
challenge,
req.ClockFrame.Difficulty,
)
if err != nil {
return nil, errors.Wrap(err, "calculate challenge proof")
}
return &protobufs.ChallengeProofResponse{
2024-06-08 11:32:45 +00:00
Output: proof,
}, nil
}
func NewDataWorkerIPCServer(
listenAddrGRPC string,
logger *zap.Logger,
coreId uint32,
prover crypto.FrameProver,
parentProcessId int,
) (*DataWorkerIPCServer, error) {
return &DataWorkerIPCServer{
listenAddrGRPC: listenAddrGRPC,
logger: logger,
coreId: coreId,
prover: prover,
parentProcessId: parentProcessId,
}, nil
}
func (r *DataWorkerIPCServer) Start() error {
s := grpc.NewServer(
2024-10-14 01:37:19 +00:00
grpc.MaxRecvMsgSize(600*1024*1024),
grpc.MaxSendMsgSize(600*1024*1024),
)
protobufs.RegisterDataIPCServiceServer(s, r)
reflection.Register(s)
mg, err := multiaddr.NewMultiaddr(r.listenAddrGRPC)
if err != nil {
return errors.Wrap(err, "start")
}
lis, err := mn.Listen(mg)
if err != nil {
return errors.Wrap(err, "start")
}
go r.monitorParent()
2024-06-08 11:32:45 +00:00
r.logger.Info(
"data worker listening",
zap.String("address", r.listenAddrGRPC),
)
if err := s.Serve(mn.NetListener(lis)); err != nil {
2024-06-08 11:32:45 +00:00
r.logger.Error("terminating server", zap.Error(err))
panic(err)
}
return nil
}
func (r *DataWorkerIPCServer) monitorParent() {
2024-06-08 11:32:45 +00:00
if r.parentProcessId == 0 {
r.logger.Info(
"no parent process id specified, running in detached worker mode",
zap.Uint32("core_id", r.coreId),
)
return
}
for {
time.Sleep(1 * time.Second)
proc, err := os.FindProcess(r.parentProcessId)
if err != nil {
r.logger.Error("parent process not found, terminating")
os.Exit(1)
}
// Windows returns an error if the process is dead, nobody else does
if runtime.GOOS != "windows" {
err := proc.Signal(syscall.Signal(0))
if err != nil {
r.logger.Error("parent process not found, terminating")
os.Exit(1)
}
}
}
}