Updated
This commit is contained in:
@@ -2,36 +2,72 @@
|
||||
|
||||
/**
|
||||
* g1wallet_spool.php — POST handlers for g1wallet.
|
||||
* pubkey store: receives public key after unlock, stores in channel settings.
|
||||
* pubkey store: receives public key (SS58 g1... address) after unlock, stores in channel settings.
|
||||
* broadcast relay: receives signed Duniter transaction, relays to orchestrator.
|
||||
*
|
||||
* At skeleton stage both handlers return placeholder responses.
|
||||
* The private key never reaches this file. Ever.
|
||||
*/
|
||||
|
||||
function g1wallet_handle_pubkey_post($access) {
|
||||
// Stores the participant's Ğ1 public key in their Hubzilla channel settings.
|
||||
// Called once after first wallet unlock (and on re-unlock if key changes).
|
||||
// Stores the participant's Ğ1 public key (SS58 address) in their Hubzilla
|
||||
// channel settings. Called once after each wallet unlock (server deduplicates
|
||||
// by checking the existing value before writing).
|
||||
// The public key is the only wallet-related thing the server ever stores.
|
||||
|
||||
$pubkey = trim($_POST['g1_pubkey'] ?? '');
|
||||
|
||||
if (!$pubkey) {
|
||||
return g1wallet_render_error('Public key is required.');
|
||||
header('Content-Type: application/json');
|
||||
echo json_encode(['status' => 'error', 'message' => 'Public key is required.']);
|
||||
killme();
|
||||
}
|
||||
|
||||
// Basic length check — Ğ1 public keys are 43–44 characters in base58.
|
||||
if (strlen($pubkey) < 43 || strlen($pubkey) > 64) {
|
||||
return g1wallet_render_error('Invalid public key format.');
|
||||
// Ğ1 SS58 addresses: base58-encoded, 36 bytes decoded, begin with "g1".
|
||||
// Encoded length is 46–47 characters. Reject anything outside that range.
|
||||
$len = strlen($pubkey);
|
||||
if ($len < 46 || $len > 48) {
|
||||
header('Content-Type: application/json');
|
||||
echo json_encode(['status' => 'error', 'message' => 'Invalid public key format.']);
|
||||
killme();
|
||||
}
|
||||
|
||||
// TODO: store $pubkey in Hubzilla channel settings using set_pconfig() or equivalent.
|
||||
// Placeholder: log and return success shell.
|
||||
// set_pconfig(local_channel(), 'g1wallet', 'g1_pubkey', $pubkey);
|
||||
// Must begin with "g1" (SS58 with Ğ1 network prefix).
|
||||
if (strncmp($pubkey, 'g1', 2) !== 0) {
|
||||
header('Content-Type: application/json');
|
||||
echo json_encode(['status' => 'error', 'message' => 'Invalid public key prefix.']);
|
||||
killme();
|
||||
}
|
||||
|
||||
// Only base58 characters (Bitcoin alphabet, no 0/O/I/l).
|
||||
if (!preg_match('/^[1-9A-HJ-NP-Za-km-z]+$/', $pubkey)) {
|
||||
header('Content-Type: application/json');
|
||||
echo json_encode(['status' => 'error', 'message' => 'Invalid public key characters.']);
|
||||
killme();
|
||||
}
|
||||
|
||||
// Determine channel_id to write against.
|
||||
// Operators use their own channel_id. Participants also use local_channel().
|
||||
// We do not write other channels' keys — only the caller's own.
|
||||
$channel_id = local_channel();
|
||||
if (!$channel_id) {
|
||||
header('Content-Type: application/json');
|
||||
echo json_encode(['status' => 'error', 'message' => 'Not authenticated.']);
|
||||
killme();
|
||||
}
|
||||
|
||||
// Deduplicate: if the stored key matches, return ok without writing.
|
||||
$existing = get_pconfig($channel_id, 'g1wallet', 'g1_pubkey');
|
||||
if ($existing === $pubkey) {
|
||||
header('Content-Type: application/json');
|
||||
echo json_encode(['status' => 'ok', 'note' => 'Key unchanged.']);
|
||||
killme();
|
||||
}
|
||||
|
||||
// Store the public key.
|
||||
set_pconfig($channel_id, 'g1wallet', 'g1_pubkey', $pubkey);
|
||||
|
||||
// Return JSON for fetch() caller in g1wallet.js.
|
||||
header('Content-Type: application/json');
|
||||
echo json_encode(['status' => 'ok', 'note' => 'Pubkey storage not yet implemented.']);
|
||||
echo json_encode(['status' => 'ok']);
|
||||
killme();
|
||||
}
|
||||
|
||||
@@ -51,13 +87,66 @@ function g1wallet_handle_broadcast_post() {
|
||||
killme();
|
||||
}
|
||||
|
||||
// TODO: load config, relay to orchestrator POST /g1wallet/broadcast.
|
||||
// $config = g1wallet_load_config();
|
||||
// $orchestrator_url = $config['orchestrator_url'] ?? '';
|
||||
// $node_token = $config['node_token'] ?? '';
|
||||
// ... HTTP relay to orchestrator ...
|
||||
// Validate doc_type is a known type.
|
||||
$allowed_types = ['transfer', 'certification'];
|
||||
if (!in_array($doc_type, $allowed_types, true)) {
|
||||
header('Content-Type: application/json');
|
||||
echo json_encode(['status' => 'error', 'message' => 'Unknown doc_type.']);
|
||||
killme();
|
||||
}
|
||||
|
||||
// Load config for orchestrator endpoint.
|
||||
$config = g1wallet_load_config();
|
||||
$orchestrator_url = rtrim($config['orchestrator_url'] ?? '', '/');
|
||||
$node_token = $config['node_token'] ?? '';
|
||||
|
||||
if (!$orchestrator_url || !$node_token) {
|
||||
header('Content-Type: application/json');
|
||||
echo json_encode(['status' => 'error', 'message' => 'Orchestrator not configured.']);
|
||||
killme();
|
||||
}
|
||||
|
||||
// Relay to orchestrator POST /g1wallet/broadcast.
|
||||
$payload = json_encode([
|
||||
'signed_doc' => $signed_doc,
|
||||
'doc_type' => $doc_type,
|
||||
]);
|
||||
|
||||
$ch = curl_init($orchestrator_url . '/g1wallet/broadcast');
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($ch, CURLOPT_POST, true);
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, [
|
||||
'Content-Type: application/json',
|
||||
'X-Node-Token: ' . $node_token,
|
||||
]);
|
||||
curl_setopt($ch, CURLOPT_TIMEOUT, 15);
|
||||
|
||||
$raw = curl_exec($ch);
|
||||
$http = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||
$err = curl_error($ch);
|
||||
curl_close($ch);
|
||||
|
||||
if ($err) {
|
||||
header('Content-Type: application/json');
|
||||
echo json_encode(['status' => 'error', 'message' => 'Orchestrator unreachable.']);
|
||||
killme();
|
||||
}
|
||||
|
||||
if ($http !== 200) {
|
||||
header('Content-Type: application/json');
|
||||
echo json_encode(['status' => 'error', 'message' => 'Orchestrator returned HTTP ' . intval($http) . '.']);
|
||||
killme();
|
||||
}
|
||||
|
||||
$result = json_decode($raw, true);
|
||||
if (json_last_error() !== JSON_ERROR_NONE || !isset($result['status'])) {
|
||||
header('Content-Type: application/json');
|
||||
echo json_encode(['status' => 'error', 'message' => 'Invalid orchestrator response.']);
|
||||
killme();
|
||||
}
|
||||
|
||||
header('Content-Type: application/json');
|
||||
echo json_encode(['status' => 'ok', 'note' => 'Broadcast relay not yet implemented.']);
|
||||
echo json_encode($result);
|
||||
killme();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user