package model import ( "errors" "fmt" "google.golang.org/protobuf/types/known/timestamppb" "go.yandata.net/iod/iod/go-trustlog/api/grpc/pb" ) // FromProtobuf 将protobuf的OperationData转换为model.Operation. func FromProtobuf(pbOp *pb.OperationData) (*Operation, error) { if pbOp == nil { return nil, errors.New("protobuf operation data is nil") } // 转换时间戳 if pbOp.GetTimestamp() == nil { return nil, errors.New("timestamp is required") } timestamp := pbOp.GetTimestamp().AsTime() // 构建Operation operation := &Operation{ OpID: pbOp.GetOpId(), Timestamp: timestamp, OpSource: Source(pbOp.GetOpSource()), OpType: pbOp.GetOpType(), DoPrefix: pbOp.GetDoPrefix(), DoRepository: pbOp.GetDoRepository(), Doid: pbOp.GetDoid(), ProducerID: pbOp.GetProducerId(), OpActor: pbOp.GetOpActor(), // OpAlgorithm和OpMetaHash字段已移除,固定使用Sha256Simd,哈希值由Envelope的OriginalHash提供 } // 处理可选的哈希字段 if reqHash := pbOp.GetRequestBodyHash(); reqHash != "" { operation.RequestBodyHash = &reqHash } if respHash := pbOp.GetResponseBodyHash(); respHash != "" { operation.ResponseBodyHash = &respHash } return operation, nil } // ToProtobuf 将model.Operation转换为protobuf的OperationData. func ToProtobuf(op *Operation) (*pb.OperationData, error) { if op == nil { return nil, errors.New("operation is nil") } // 转换时间戳 timestamp := timestamppb.New(op.Timestamp) pbOp := &pb.OperationData{ OpId: op.OpID, Timestamp: timestamp, OpSource: string(op.OpSource), OpType: op.OpType, DoPrefix: op.DoPrefix, DoRepository: op.DoRepository, Doid: op.Doid, ProducerId: op.ProducerID, OpActor: op.OpActor, // OpAlgorithm、OpMetaHash和OpHash字段已移除,固定使用Sha256Simd,哈希值由Envelope的OriginalHash提供 } // 处理可选的哈希字段 if op.RequestBodyHash != nil { pbOp.RequestBodyHash = *op.RequestBodyHash } if op.ResponseBodyHash != nil { pbOp.ResponseBodyHash = *op.ResponseBodyHash } return pbOp, nil } // FromProtobufValidationResult 将protobuf的ValidationStreamRes转换为model.ValidationResult. func FromProtobufValidationResult(pbRes *pb.ValidationStreamRes) (*ValidationResult, error) { if pbRes == nil { return nil, errors.New("protobuf validation result is nil") } result := &ValidationResult{ Code: pbRes.GetCode(), Msg: pbRes.GetMsg(), Progress: pbRes.GetProgress(), Proof: ProofFromProtobuf(pbRes.GetProof()), // 取证证明 } // 如果有操作数据,则转换 if pbRes.GetData() != nil { op, err := FromProtobuf(pbRes.GetData()) if err != nil { return nil, fmt.Errorf("failed to convert operation data: %w", err) } result.Data = op } return result, nil } // RecordFromProtobuf 将protobuf的RecordData转换为model.Record. func RecordFromProtobuf(pbRec *pb.RecordData) (*Record, error) { if pbRec == nil { return nil, errors.New("protobuf record data is nil") } // 构建Record record := &Record{ ID: pbRec.GetId(), DoPrefix: pbRec.GetDoPrefix(), ProducerID: pbRec.GetProducerId(), Operator: pbRec.GetOperator(), Extra: pbRec.GetExtra(), RCType: pbRec.GetRcType(), } // 转换时间戳 if pbRec.GetTimestamp() != nil { record.Timestamp = pbRec.GetTimestamp().AsTime() } return record, nil } // RecordToProtobuf 将model.Record转换为protobuf的RecordData. func RecordToProtobuf(rec *Record) (*pb.RecordData, error) { if rec == nil { return nil, errors.New("record is nil") } // 转换时间戳 timestamp := timestamppb.New(rec.Timestamp) pbRec := &pb.RecordData{ Id: rec.ID, DoPrefix: rec.DoPrefix, ProducerId: rec.ProducerID, Timestamp: timestamp, Operator: rec.Operator, Extra: rec.Extra, RcType: rec.RCType, } return pbRec, nil } // RecordValidationResult 包装记录验证的流式响应结果. type RecordValidationResult struct { Code int32 // 状态码(100处理中,200完成,500失败) Msg string // 消息描述 Progress string // 当前进度(比如 "50%") Data *Record // 最终完成时返回的记录数据,过程中可为空 Proof *Proof // 取证证明(仅在完成时返回) } // IsProcessing 判断是否正在处理中. func (r *RecordValidationResult) IsProcessing() bool { return r.Code == ValidationCodeProcessing } // IsCompleted 判断是否已完成. func (r *RecordValidationResult) IsCompleted() bool { return r.Code == ValidationCodeCompleted } // IsFailed 判断是否失败. func (r *RecordValidationResult) IsFailed() bool { return r.Code >= ValidationCodeFailed } // RecordFromProtobufValidationResult 将protobuf的RecordValidationStreamRes转换为model.RecordValidationResult. func RecordFromProtobufValidationResult(pbRes *pb.RecordValidationStreamRes) (*RecordValidationResult, error) { if pbRes == nil { return nil, errors.New("protobuf record validation result is nil") } result := &RecordValidationResult{ Code: pbRes.GetCode(), Msg: pbRes.GetMsg(), Progress: pbRes.GetProgress(), Proof: ProofFromProtobuf(pbRes.GetProof()), // 取证证明 } // 如果有记录数据,则转换 if pbRes.GetResult() != nil { rec, err := RecordFromProtobuf(pbRes.GetResult()) if err != nil { return nil, fmt.Errorf("failed to convert record data: %w", err) } result.Data = rec } return result, nil }