mini-fair-repo/inc/plc/class-operation.php
Ryan McCue a3a5a85baa Initial export of the repository
Signed-off-by: Ryan McCue <me@ryanmccue.info>
2025-06-05 12:06:13 +02:00

115 lines
2.7 KiB
PHP

<?php
namespace MiniFAIR\PLC;
use Elliptic\EC\KeyPair;
use MiniFAIR\Keys;
use Exception;
use JsonSerializable;
class Operation implements JsonSerializable {
public function __construct(
/**
* Operation type (plc_operation or plc_tombstone)
*/
public string $type,
/**
* Rotation keys.
*
* @var KeyPair[]
*/
public array $rotationKeys,
/**
* Verification keys.
*
* @var array<string, KeyPair>
*/
public array $verificationMethods,
/**
* Public key.
*
* @var string[]
*/
public array $alsoKnownAs,
/**
* Services.
*
* @var array<string, string>
*/
public array $services,
/**
* Previous operation.
*
* @var string|null
*/
public ?string $prev = null,
) {
}
public function validate() : bool {
if ( empty( $this->type ) ) {
throw new Exception( 'Operation type is empty' );
}
if ( ! in_array( $this->type, [ 'plc_operation', 'plc_tombstone' ], true ) ) {
throw new Exception( 'Invalid operation type' );
}
if ( empty( $this->rotationKeys ) ) {
throw new Exception( 'Rotation keys are empty' );
}
foreach ( $this->rotationKeys as $keypair ) {
if ( ! $keypair instanceof KeyPair ) {
throw new Exception( 'Rotation key is not a KeyPair object' );
}
}
if ( empty( $this->verificationMethods ) ) {
throw new Exception( 'Verification methods are empty' );
}
foreach ( $this->verificationMethods as $key => $keypair ) {
if ( $key !== VERIFICATION_METHOD_ID ) {
throw new Exception( sprintf( 'Invalid verification method ID: %s', $key ) );
}
if ( ! $keypair instanceof KeyPair ) {
throw new Exception( 'Rotation key is not a KeyPair object' );
}
}
if ( empty( $this->prev ) ) {
// Genesis operation, require rotationKeys and verificationMethods.
if ( empty( $this->rotationKeys ) || empty( $this->verificationMethods ) ) {
throw new Exception( 'Missing rotationKeys or verificationMethods' );
}
if ( empty( $this->verificationMethods[ VERIFICATION_METHOD_ID ] ) ) {
throw new Exception( 'Missing verification method for FAIR' );
}
}
return true;
}
public function sign( KeyPair $rotation_key ) : SignedOperation {
return sign_operation( $this, $rotation_key );
}
public function jsonSerialize() : array {
$methods = [];
foreach ( $this->verificationMethods as $key => $keypair ) {
$methods[ $key ] = Keys\encode_did_key( $keypair, Keys\CURVE_K256 );
}
return [
'type' => $this->type,
'rotationKeys' => array_map( fn ( $key ) => Keys\encode_did_key( $key, Keys\CURVE_K256 ), $this->rotationKeys ),
'verificationMethods' => $methods,
'alsoKnownAs' => $this->alsoKnownAs,
'services' => (object) $this->services,
'prev' => $this->prev,
];
}
}