1- use alloy_primitives:: { FixedBytes , B256 } ;
1+ use alloy_primitives:: { Address , FixedBytes , B256 } ;
22use anyhow:: anyhow;
33use async_trait:: async_trait;
44use cert:: types:: { CertificateSigningRequestDetails , QuibleSignature , SignedCertificate } ;
@@ -11,6 +11,7 @@ use hyper::Method;
1111use jsonrpsee:: core:: async_trait as jsonrpsee_async_trait;
1212use jsonrpsee:: types:: error:: CALL_EXECUTION_FAILED_CODE ;
1313use jsonrpsee:: { server:: Server , types:: ErrorObjectOwned } ;
14+ use k256:: ecdsa:: SigningKey ;
1415use libp2p:: { multiaddr, noise, ping, swarm:: SwarmEvent , tcp, yamux} ;
1516use quible_ecdsa_utils:: sign_message;
1617use serde:: { Deserialize , Serialize } ;
@@ -215,6 +216,7 @@ async fn digest_object_output(
215216async fn propose_block (
216217 block_number : u64 ,
217218 db_arc : & Arc < Surreal < AnyDb > > ,
219+ node_signing_key : & SigningKey ,
218220) -> anyhow:: Result < BlockRow > {
219221 println ! ( "preparing block {}" , block_number) ;
220222
@@ -281,8 +283,16 @@ async fn propose_block(
281283 outputs : vec ! [ TransactionOutput :: Value {
282284 value: 5 ,
283285
284- // TODO: https://linear.app/quible/issue/QUI-103/ensure-coinbase-transactions-can-only-be-spent-by-block-proposer
285- pubkey_script: vec![ ] ,
286+ pubkey_script: vec![
287+ TransactionOpCode :: Dup ,
288+ TransactionOpCode :: Push {
289+ data: Address :: from_private_key( & node_signing_key)
290+ . into_array( )
291+ . to_vec( ) ,
292+ } ,
293+ TransactionOpCode :: EqualVerify ,
294+ TransactionOpCode :: CheckSigVerify ,
295+ ] ,
286296 } ] ,
287297 locktime : 0 ,
288298 } ;
@@ -619,6 +629,7 @@ async fn main() -> anyhow::Result<()> {
619629 ) ;
620630 let mut signing_key_decoded = [ 0u8 ; 32 ] ;
621631 hex:: decode_to_slice ( signing_key_hex, & mut signing_key_decoded) ?;
632+ let signing_key = SigningKey :: from_slice ( & signing_key_decoded) ?;
622633
623634 let p2p_port: u16 = env:: var ( "QUIBLE_P2P_PORT" )
624635 . unwrap_or_else ( |_| "9014" . to_owned ( ) )
@@ -686,7 +697,7 @@ async fn main() -> anyhow::Result<()> {
686697 _ => { }
687698 }
688699
689- let result = propose_block ( block_number, & db_arc) . await ;
700+ let result = propose_block ( block_number, & db_arc, & signing_key ) . await ;
690701
691702 if let Err ( e) = result {
692703 eprintln ! ( "Error in propose_block: {:#?}" , e) ;
@@ -698,7 +709,7 @@ async fn main() -> anyhow::Result<()> {
698709 block_timestamp = block_timestamp + SLOT_DURATION ;
699710 block_number += 1 ;
700711
701- let result = propose_block( block_number, & db_arc) . await ;
712+ let result = propose_block( block_number, & db_arc, & signing_key ) . await ;
702713
703714 if let Err ( e) = result {
704715 eprintln!( "Error in propose_block: {:#?}" , e) ;
@@ -747,16 +758,17 @@ mod tests {
747758 use super :: { db, run_derive_server} ;
748759 use crate :: db:: types:: { BlockRow , ObjectRow , PendingTransactionRow } ;
749760 use crate :: propose_block;
750- use crate :: quible_ecdsa_utils:: recover_signer_unchecked;
761+ use crate :: quible_ecdsa_utils:: { recover_signer_unchecked, sign_message } ;
751762 use crate :: rpc:: QuibleRpcClient ;
752763 use crate :: tx:: engine:: compute_object_id;
753764 use crate :: tx:: types:: {
754765 Hashable , ObjectIdentifier , ObjectMode , Transaction , TransactionInput , TransactionOpCode ,
755766 TransactionOutpoint , TransactionOutput ,
756767 } ;
757- use alloy_primitives:: Address ;
768+ use alloy_primitives:: { Address , B256 } ;
758769 use anyhow:: anyhow;
759770 use jsonrpsee:: http_client:: HttpClient ;
771+ use k256:: ecdsa:: SigningKey ;
760772 use std:: sync:: Arc ;
761773 use surrealdb:: engine:: any;
762774
@@ -817,16 +829,15 @@ mod tests {
817829
818830 let db_arc = Arc :: new ( db) ;
819831
820- let server_addr = run_derive_server (
821- hex_literal:: hex!( "ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80" ) ,
822- & db_arc,
823- 0 ,
824- )
825- . await ?;
832+ let node_signing_key_bytes =
833+ hex_literal:: hex!( "ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80" ) ;
834+ let node_signing_key = SigningKey :: from_slice ( & node_signing_key_bytes) ?;
835+
836+ let server_addr = run_derive_server ( node_signing_key_bytes, & db_arc, 0 ) . await ?;
826837 let url = format ! ( "http://{}" , server_addr) ;
827838 println ! ( "server listening at {}" , url) ;
828839
829- propose_block ( 1 , & db_arc) . await ?;
840+ propose_block ( 1 , & db_arc, & node_signing_key ) . await ?;
830841
831842 // Query pending transactions from SurrealDB
832843 let block_rows: Vec < BlockRow > = db_arc. select ( "blocks" ) . await ?;
@@ -852,12 +863,11 @@ mod tests {
852863
853864 let db_arc = Arc :: new ( db) ;
854865
855- let server_addr = run_derive_server (
856- hex_literal:: hex!( "ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80" ) ,
857- & db_arc,
858- 0 ,
859- )
860- . await ?;
866+ let node_signing_key_bytes =
867+ hex_literal:: hex!( "ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80" ) ;
868+ let node_signing_key = SigningKey :: from_slice ( & node_signing_key_bytes) ?;
869+
870+ let server_addr = run_derive_server ( node_signing_key_bytes, & db_arc, 0 ) . await ?;
861871 let url = format ! ( "http://{}" , server_addr) ;
862872 println ! ( "server listening at {}" , url) ;
863873 let client = HttpClient :: builder ( ) . build ( url) ?;
@@ -895,7 +905,7 @@ mod tests {
895905 . await
896906 . unwrap ( ) ;
897907
898- propose_block ( 1 , & db_arc) . await ?;
908+ propose_block ( 1 , & db_arc, & node_signing_key ) . await ?;
899909
900910 // Query pending transactions from SurrealDB
901911 let block_rows: Vec < BlockRow > = db_arc. select ( "blocks" ) . await ?;
@@ -939,25 +949,24 @@ mod tests {
939949
940950 let db_arc = Arc :: new ( db) ;
941951
942- let server_addr = run_derive_server (
943- hex_literal:: hex!( "ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80" ) ,
944- & db_arc,
945- 0 ,
946- )
947- . await ?;
952+ let node_signing_key_bytes =
953+ hex_literal:: hex!( "ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80" ) ;
954+ let node_signing_key = SigningKey :: from_slice ( & node_signing_key_bytes) ?;
955+
956+ let server_addr = run_derive_server ( node_signing_key_bytes, & db_arc, 0 ) . await ?;
948957 let url = format ! ( "http://{}" , server_addr) ;
949958 println ! ( "server listening at {}" , url) ;
950959
951- let block_row = propose_block ( 1 , & db_arc) . await ?;
960+ let block_row = propose_block ( 1 , & db_arc, & node_signing_key ) . await ?;
952961
953962 let coinbase_transaction_hash = match & block_row. transactions [ ..] {
954963 [ ( hash, _) ] => Ok ( * hash) ,
955964 _ => Err ( anyhow ! ( "missing coinbase transaction" ) ) ,
956965 } ?;
957966
958967 let client = HttpClient :: builder ( ) . build ( url) ?;
959- // let signer_secret = k256::ecdsa::SigningKey::random(&mut rand::thread_rng());
960- let sample_first_transaction = Transaction :: Version1 {
968+
969+ let sample_first_transaction = & mut Transaction :: Version1 {
961970 inputs : vec ! [ TransactionInput {
962971 outpoint: TransactionOutpoint {
963972 txid: coinbase_transaction_hash,
@@ -972,12 +981,38 @@ mod tests {
972981 locktime : 0 ,
973982 } ;
974983
984+ let signature = sign_message (
985+ B256 :: from_slice ( & node_signing_key_bytes) ,
986+ sample_first_transaction. hash ( ) ?. into ( ) ,
987+ ) ?
988+ . to_vec ( ) ;
989+
990+ match sample_first_transaction {
991+ Transaction :: Version1 { inputs, .. } => {
992+ for input in inputs. iter_mut ( ) {
993+ * input = TransactionInput {
994+ outpoint : input. clone ( ) . outpoint ,
995+ signature_script : vec ! [
996+ TransactionOpCode :: Push {
997+ data: signature. clone( ) ,
998+ } ,
999+ TransactionOpCode :: Push {
1000+ data: Address :: from_private_key( & node_signing_key)
1001+ . into_array( )
1002+ . to_vec( ) ,
1003+ } ,
1004+ ] ,
1005+ }
1006+ }
1007+ }
1008+ }
1009+
9751010 client
9761011 . send_transaction ( sample_first_transaction. clone ( ) )
9771012 . await
9781013 . unwrap ( ) ;
9791014
980- propose_block ( 2 , & db_arc) . await ?;
1015+ propose_block ( 2 , & db_arc, & node_signing_key ) . await ?;
9811016
9821017 // Query pending transactions from SurrealDB
9831018 let mut result = db_arc
@@ -1018,12 +1053,11 @@ mod tests {
10181053
10191054 let db_arc = Arc :: new ( db) ;
10201055
1021- let server_addr = run_derive_server (
1022- hex_literal:: hex!( "ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80" ) ,
1023- & db_arc,
1024- 0 ,
1025- )
1026- . await ?;
1056+ let node_signing_key_bytes =
1057+ hex_literal:: hex!( "ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80" ) ;
1058+ let node_signing_key = SigningKey :: from_slice ( & node_signing_key_bytes) ?;
1059+
1060+ let server_addr = run_derive_server ( node_signing_key_bytes, & db_arc, 0 ) . await ?;
10271061 let url = format ! ( "http://{}" , server_addr) ;
10281062 println ! ( "server listening at {}" , url) ;
10291063 let client = HttpClient :: builder ( ) . build ( url) ?;
@@ -1061,7 +1095,7 @@ mod tests {
10611095 . await
10621096 . unwrap ( ) ;
10631097
1064- propose_block ( 1 , & db_arc) . await ?;
1098+ propose_block ( 1 , & db_arc, & node_signing_key ) . await ?;
10651099
10661100 // Query pending transactions from SurrealDB
10671101 let block_rows: Vec < BlockRow > = db_arc. select ( "blocks" ) . await ?;
@@ -1114,16 +1148,13 @@ mod tests {
11141148
11151149 let db_arc = Arc :: new ( db) ;
11161150
1117- let server_signer_key = k256:: ecdsa:: SigningKey :: from_slice ( & hex_literal:: hex!(
1118- "ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80"
1119- ) ) ?;
1151+ let server_signing_key_bytes =
1152+ hex_literal:: hex!( "ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80" ) ;
1153+
1154+ let server_signing_key = k256:: ecdsa:: SigningKey :: from_slice ( & server_signing_key_bytes) ?;
1155+
1156+ let server_addr = run_derive_server ( server_signing_key_bytes, & db_arc, 0 ) . await ?;
11201157
1121- let server_addr = run_derive_server (
1122- server_signer_key. to_bytes ( ) . as_slice ( ) . try_into ( ) ?,
1123- & db_arc,
1124- 0 ,
1125- )
1126- . await ?;
11271158 let url = format ! ( "http://{}" , server_addr) ;
11281159 println ! ( "server listening at {}" , url) ;
11291160 let client = HttpClient :: builder ( ) . build ( url) ?;
@@ -1146,7 +1177,7 @@ mod tests {
11461177
11471178 client. send_transaction ( sample_transaction. clone ( ) ) . await ?;
11481179
1149- propose_block ( 1 , & db_arc) . await ?;
1180+ propose_block ( 1 , & db_arc, & server_signing_key ) . await ?;
11501181
11511182 let cert = client
11521183 . request_certificate ( object_id_raw, vec ! [ 1 , 2 , 3 ] )
@@ -1156,7 +1187,7 @@ mod tests {
11561187 assert_eq ! ( cert. details. claim, vec![ 1 , 2 , 3 ] ) ;
11571188 assert_eq ! (
11581189 recover_signer_unchecked( & cert. signature. raw, & cert. details. hash( ) ?) ?,
1159- Address :: from_public_key ( server_signer_key . verifying_key ( ) )
1190+ Address :: from_private_key ( & server_signing_key )
11601191 ) ;
11611192
11621193 Ok ( ( ) )
@@ -1171,12 +1202,12 @@ mod tests {
11711202
11721203 let db_arc = Arc :: new ( db) ;
11731204
1174- let server_signer_key = k256 :: ecdsa :: SigningKey :: from_slice ( & hex_literal :: hex! (
1175- "ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80"
1176- ) ) ?;
1205+ let server_signing_key_bytes =
1206+ hex_literal :: hex! ( "ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80" ) ;
1207+ let server_signing_key = k256 :: ecdsa :: SigningKey :: from_slice ( & server_signing_key_bytes ) ?;
11771208
11781209 let server_addr = run_derive_server (
1179- server_signer_key . to_bytes ( ) . as_slice ( ) . try_into ( ) ?,
1210+ server_signing_key . to_bytes ( ) . as_slice ( ) . try_into ( ) ?,
11801211 & db_arc,
11811212 0 ,
11821213 )
@@ -1203,7 +1234,7 @@ mod tests {
12031234
12041235 client. send_transaction ( sample_transaction. clone ( ) ) . await ?;
12051236
1206- propose_block ( 1 , & db_arc) . await ?;
1237+ propose_block ( 1 , & db_arc, & server_signing_key ) . await ?;
12071238
12081239 let failure_response = client
12091240 . request_certificate ( object_id_raw, vec ! [ 4 , 5 , 6 ] )
@@ -1231,30 +1262,31 @@ mod tests {
12311262
12321263 let db_arc = Arc :: new ( db) ;
12331264
1234- let server_signer_key = k256:: ecdsa:: SigningKey :: from_slice ( & hex_literal:: hex!(
1235- "ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80"
1236- ) ) ?;
1265+ let server_signing_key_bytes =
1266+ hex_literal:: hex!( "ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80" ) ;
12371267
1238- let server_addr = run_derive_server (
1239- server_signer_key. to_bytes ( ) . as_slice ( ) . try_into ( ) ?,
1240- & db_arc,
1241- 0 ,
1242- )
1243- . await ?;
1268+ let server_signing_key = k256:: ecdsa:: SigningKey :: from_slice ( & server_signing_key_bytes) ?;
1269+ let server_signing_key_bytes: [ u8 ; 32 ] =
1270+ server_signing_key. to_bytes ( ) . as_slice ( ) . try_into ( ) ?;
1271+
1272+ let user_signing_key = k256:: ecdsa:: SigningKey :: random ( & mut rand:: thread_rng ( ) ) ;
1273+
1274+ let server_addr = run_derive_server ( server_signing_key_bytes, & db_arc, 0 ) . await ?;
12441275 let url = format ! ( "http://{}" , server_addr) ;
12451276 println ! ( "server listening at {}" , url) ;
12461277 let client = HttpClient :: builder ( ) . build ( url) ?;
12471278
1248- let block_row = propose_block ( 1 , & db_arc) . await ?;
1279+ let block_row = propose_block ( 1 , & db_arc, & server_signing_key ) . await ?;
12491280
12501281 let coinbase_transaction_hash = match & block_row. transactions [ ..] {
12511282 [ ( hash, _) ] => Ok ( * hash) ,
12521283 _ => Err ( anyhow ! ( "missing coinbase transaction" ) ) ,
12531284 } ?;
12541285
1255- let owner_address = Address :: from_private_key ( & server_signer_key) ;
1286+ let owner_address = Address :: from_private_key ( & server_signing_key. clone ( ) ) ;
1287+ let user_address = Address :: from_private_key ( & user_signing_key. clone ( ) ) ;
12561288
1257- let sample_transaction = Transaction :: Version1 {
1289+ let sample_transaction = & mut Transaction :: Version1 {
12581290 inputs : vec ! [ TransactionInput {
12591291 outpoint: TransactionOutpoint {
12601292 txid: coinbase_transaction_hash,
@@ -1267,7 +1299,7 @@ mod tests {
12671299 pubkey_script: vec![
12681300 TransactionOpCode :: Dup ,
12691301 TransactionOpCode :: Push {
1270- data: owner_address . to_vec( ) ,
1302+ data: user_address . to_vec( ) ,
12711303 } ,
12721304 TransactionOpCode :: EqualVerify ,
12731305 TransactionOpCode :: CheckSigVerify ,
@@ -1276,12 +1308,36 @@ mod tests {
12761308 locktime : 0 ,
12771309 } ;
12781310
1311+ let signature = sign_message (
1312+ B256 :: from_slice ( & server_signing_key_bytes) ,
1313+ sample_transaction. hash ( ) ?. into ( ) ,
1314+ ) ?
1315+ . to_vec ( ) ;
1316+
1317+ match sample_transaction {
1318+ Transaction :: Version1 { inputs, .. } => {
1319+ for input in inputs. iter_mut ( ) {
1320+ * input = TransactionInput {
1321+ outpoint : input. clone ( ) . outpoint ,
1322+ signature_script : vec ! [
1323+ TransactionOpCode :: Push {
1324+ data: signature. clone( ) ,
1325+ } ,
1326+ TransactionOpCode :: Push {
1327+ data: owner_address. into_array( ) . to_vec( ) ,
1328+ } ,
1329+ ] ,
1330+ }
1331+ }
1332+ }
1333+ }
1334+
12791335 client. send_transaction ( sample_transaction. clone ( ) ) . await ?;
12801336
1281- propose_block ( 2 , & db_arc) . await ?;
1337+ propose_block ( 2 , & db_arc, & server_signing_key ) . await ?;
12821338
12831339 let payload = client
1284- . fetch_unspent_value_outputs_by_owner ( owner_address . into_array ( ) )
1340+ . fetch_unspent_value_outputs_by_owner ( user_address . into_array ( ) )
12851341 . await ?;
12861342
12871343 assert_eq ! ( payload. total_value, 5 ) ;
0 commit comments