@@ -18,16 +18,22 @@ use crate::{
18
18
routes:: { campaign:: fetch_campaign_ids_for_channel, routers:: RouteParams } ,
19
19
Application , Auth ,
20
20
} ;
21
- use adapter:: { client:: Locked , Adapter , Dummy } ;
21
+ use adapter:: {
22
+ client:: Locked ,
23
+ util:: { get_balance_leaf, get_signable_state_root} ,
24
+ Adapter , Dummy ,
25
+ } ;
22
26
use axum:: { extract:: Path , Extension , Json } ;
23
27
use futures:: future:: try_join_all;
24
28
use hyper:: { Body , Request , Response } ;
25
29
use primitives:: {
26
30
balances:: { Balances , CheckedState , UncheckedState } ,
31
+ merkle_tree:: MerkleTree ,
27
32
sentry:: {
28
33
channel_list:: { ChannelListQuery , ChannelListResponse } ,
29
- AccountingResponse , AllSpendersQuery , AllSpendersResponse , ChannelPayRequest , LastApproved ,
30
- LastApprovedQuery , LastApprovedResponse , SpenderResponse , SuccessResponse ,
34
+ AccountingResponse , AllSpendersQuery , AllSpendersResponse , ChannelPayRequest ,
35
+ GetLeafResponse , LastApproved , LastApprovedQuery , LastApprovedResponse , SpenderResponse ,
36
+ SuccessResponse ,
31
37
} ,
32
38
spender:: { Spendable , Spender } ,
33
39
validator:: NewState ,
@@ -799,6 +805,106 @@ pub async fn channel_payout_axum<C: Locked + 'static>(
799
805
Ok ( Json ( SuccessResponse { success : true } ) )
800
806
}
801
807
808
+ pub async fn get_spender_leaf < C : Locked + ' static > (
809
+ Extension ( app) : Extension < Arc < Application < C > > > ,
810
+ Extension ( channel_context) : Extension < ChainOf < Channel > > ,
811
+ Path ( params) : Path < ( ChannelId , Address ) > ,
812
+ ) -> Result < Json < GetLeafResponse > , ResponseError > {
813
+ let channel = channel_context. context ;
814
+
815
+ let approve_state = match latest_approve_state ( & app. pool , & channel) . await ? {
816
+ Some ( approve_state) => approve_state,
817
+ None => {
818
+ return Err ( ResponseError :: BadRequest (
819
+ "No ApproveState message for spender" . to_string ( ) ,
820
+ ) )
821
+ }
822
+ } ;
823
+
824
+ let state_root = approve_state. msg . state_root . clone ( ) ;
825
+
826
+ let new_state = latest_new_state ( & app. pool , & channel, & state_root)
827
+ . await ?
828
+ . ok_or ( ResponseError :: BadRequest (
829
+ "No NewState message for spender" . to_string ( ) ,
830
+ ) ) ?;
831
+
832
+ let spender = params. 1 ;
833
+ let amount = new_state
834
+ . msg
835
+ . balances
836
+ . spenders
837
+ . get ( & spender)
838
+ . ok_or ( ResponseError :: BadRequest (
839
+ "No balance entry for spender!" . to_string ( ) ,
840
+ ) ) ?;
841
+ let element = get_balance_leaf (
842
+ true ,
843
+ & spender,
844
+ & amount. to_precision ( channel_context. token . precision . get ( ) ) ,
845
+ )
846
+ . map_err ( |err| ResponseError :: BadRequest ( err. to_string ( ) ) ) ?;
847
+
848
+ let merkle_tree =
849
+ MerkleTree :: new ( & [ element] ) . map_err ( |err| ResponseError :: BadRequest ( err. to_string ( ) ) ) ?;
850
+
851
+ let signable_state_root = get_signable_state_root ( & * channel. id ( ) , & merkle_tree. root ( ) ) ;
852
+
853
+ let res = hex:: encode ( signable_state_root) ;
854
+
855
+ Ok ( Json ( GetLeafResponse { merkle_proof : res } ) )
856
+ }
857
+
858
+ pub async fn get_earner_leaf < C : Locked + ' static > (
859
+ Extension ( app) : Extension < Arc < Application < C > > > ,
860
+ Extension ( channel_context) : Extension < ChainOf < Channel > > ,
861
+ Path ( params) : Path < ( ChannelId , Address ) > ,
862
+ ) -> Result < Json < GetLeafResponse > , ResponseError > {
863
+ let channel = channel_context. context ;
864
+
865
+ let approve_state = match latest_approve_state ( & app. pool , & channel) . await ? {
866
+ Some ( approve_state) => approve_state,
867
+ None => {
868
+ return Err ( ResponseError :: BadRequest (
869
+ "No ApproveState message for earner" . to_string ( ) ,
870
+ ) )
871
+ }
872
+ } ;
873
+
874
+ let state_root = approve_state. msg . state_root . clone ( ) ;
875
+
876
+ let new_state = latest_new_state ( & app. pool , & channel, & state_root)
877
+ . await ?
878
+ . ok_or ( ResponseError :: BadRequest (
879
+ "No NewState message for earner" . to_string ( ) ,
880
+ ) ) ?;
881
+
882
+ let earner = params. 1 ;
883
+ let amount = new_state
884
+ . msg
885
+ . balances
886
+ . earners
887
+ . get ( & earner)
888
+ . ok_or ( ResponseError :: BadRequest (
889
+ "No balance entry for earner!" . to_string ( ) ,
890
+ ) ) ?;
891
+ let element = get_balance_leaf (
892
+ false ,
893
+ & earner,
894
+ & amount. to_precision ( channel_context. token . precision . get ( ) ) ,
895
+ )
896
+ . map_err ( |err| ResponseError :: BadRequest ( err. to_string ( ) ) ) ?;
897
+
898
+ let merkle_tree =
899
+ MerkleTree :: new ( & [ element] ) . map_err ( |err| ResponseError :: BadRequest ( err. to_string ( ) ) ) ?;
900
+
901
+ let signable_state_root = get_signable_state_root ( & * channel. id ( ) , & merkle_tree. root ( ) ) ;
902
+
903
+ let res = hex:: encode ( signable_state_root) ;
904
+
905
+ Ok ( Json ( GetLeafResponse { merkle_proof : res } ) )
906
+ }
907
+
802
908
/// POST `/v5/channel/0xXXX.../pay` request
803
909
///
804
910
/// Body: [`ChannelPayRequest`]
@@ -1163,20 +1269,25 @@ pub mod validator_message {
1163
1269
mod test {
1164
1270
use super :: * ;
1165
1271
use crate :: {
1166
- db:: { insert_campaign, insert_channel, CampaignRemaining } ,
1272
+ db:: {
1273
+ insert_campaign, insert_channel, validator_message:: insert_validator_message,
1274
+ CampaignRemaining ,
1275
+ } ,
1167
1276
test_util:: setup_dummy_app,
1168
1277
} ;
1169
1278
use adapter:: {
1170
1279
ethereum:: test_util:: { GANACHE_INFO_1 , GANACHE_INFO_1337 } ,
1171
1280
primitives:: Deposit as AdapterDeposit ,
1172
1281
} ;
1173
1282
use primitives:: {
1283
+ balances:: UncheckedState ,
1174
1284
channel:: Nonce ,
1175
1285
test_util:: {
1176
1286
ADVERTISER , CREATOR , DUMMY_CAMPAIGN , FOLLOWER , GUARDIAN , IDS , LEADER , LEADER_2 ,
1177
1287
PUBLISHER , PUBLISHER_2 ,
1178
1288
} ,
1179
- BigNum , ChainId , Deposit , UnifiedMap , ValidatorId ,
1289
+ validator:: { ApproveState , MessageTypes , NewState } ,
1290
+ BigNum , ChainId , Deposit , ToETHChecksum , UnifiedMap , ValidatorId ,
1180
1291
} ;
1181
1292
1182
1293
#[ tokio:: test]
@@ -1897,4 +2008,119 @@ mod test {
1897
2008
) ;
1898
2009
}
1899
2010
}
2011
+
2012
+ #[ tokio:: test]
2013
+ async fn get_spender_and_earner_leafs ( ) {
2014
+ let mut balances: Balances < CheckedState > = Balances :: new ( ) ;
2015
+ balances
2016
+ . spend ( * ADVERTISER , * PUBLISHER , UnifiedNum :: from_u64 ( 1000 ) )
2017
+ . expect ( "should spend" ) ;
2018
+ balances
2019
+ . spend ( * ADVERTISER , * PUBLISHER_2 , UnifiedNum :: from_u64 ( 1000 ) )
2020
+ . expect ( "should spend" ) ;
2021
+ balances
2022
+ . spend ( * CREATOR , * PUBLISHER , UnifiedNum :: from_u64 ( 1000 ) )
2023
+ . expect ( "should spend" ) ;
2024
+ balances
2025
+ . spend ( * CREATOR , * PUBLISHER_2 , UnifiedNum :: from_u64 ( 1000 ) )
2026
+ . expect ( "should spend" ) ;
2027
+
2028
+ let app_guard = setup_dummy_app ( ) . await ;
2029
+ let app = Extension ( Arc :: new ( app_guard. app . clone ( ) ) ) ;
2030
+
2031
+ let channel_context = Extension (
2032
+ app. config
2033
+ . find_chain_of ( DUMMY_CAMPAIGN . channel . token )
2034
+ . expect ( "Dummy channel Token should be present in config!" )
2035
+ . with ( DUMMY_CAMPAIGN . channel ) ,
2036
+ ) ;
2037
+ let channel = channel_context. context ;
2038
+
2039
+ insert_channel ( & app. pool , & channel_context)
2040
+ . await
2041
+ . expect ( "should insert channel" ) ;
2042
+
2043
+ // Setting up the validator messages
2044
+ let state_root = balances
2045
+ . encode ( channel. id ( ) , channel_context. token . precision . get ( ) )
2046
+ . expect ( "should encode" ) ;
2047
+ let new_state: NewState < UncheckedState > = NewState {
2048
+ state_root : state_root. clone ( ) ,
2049
+ signature : IDS [ & * LEADER ] . to_checksum ( ) ,
2050
+ balances : balances. into_unchecked ( ) ,
2051
+ } ;
2052
+ let approve_state = ApproveState {
2053
+ state_root,
2054
+ signature : IDS [ & * FOLLOWER ] . to_checksum ( ) ,
2055
+ is_healthy : true ,
2056
+ } ;
2057
+
2058
+ insert_validator_message (
2059
+ & app. pool ,
2060
+ & channel,
2061
+ & channel. leader ,
2062
+ & MessageTypes :: NewState ( new_state) ,
2063
+ )
2064
+ . await
2065
+ . expect ( "Should insert NewState msg" ) ;
2066
+ insert_validator_message (
2067
+ & app. pool ,
2068
+ & channel,
2069
+ & channel. follower ,
2070
+ & MessageTypes :: ApproveState ( approve_state) ,
2071
+ )
2072
+ . await
2073
+ . expect ( "Should insert NewState msg" ) ;
2074
+
2075
+ // generate proofs
2076
+ let spender_proof = {
2077
+ let element = get_balance_leaf (
2078
+ true ,
2079
+ & * ADVERTISER ,
2080
+ & UnifiedNum :: from_u64 ( 2_000 ) . to_precision ( channel_context. token . precision . get ( ) ) ,
2081
+ )
2082
+ . expect ( "should get" ) ;
2083
+
2084
+ let merkle_tree = MerkleTree :: new ( & [ element] ) . expect ( "Should build MerkleTree" ) ;
2085
+
2086
+ let signable_state_root = get_signable_state_root ( & * channel. id ( ) , & merkle_tree. root ( ) ) ;
2087
+
2088
+ hex:: encode ( signable_state_root)
2089
+ } ;
2090
+
2091
+ let earner_proof = {
2092
+ let element = get_balance_leaf (
2093
+ false ,
2094
+ & * PUBLISHER ,
2095
+ & UnifiedNum :: from_u64 ( 2_000 ) . to_precision ( channel_context. token . precision . get ( ) ) ,
2096
+ )
2097
+ . expect ( "should get balance leaf" ) ;
2098
+
2099
+ let merkle_tree = MerkleTree :: new ( & [ element] ) . expect ( "Should build MerkleTree" ) ;
2100
+
2101
+ let signable_state_root = get_signable_state_root ( & * channel. id ( ) , & merkle_tree. root ( ) ) ;
2102
+
2103
+ hex:: encode ( signable_state_root)
2104
+ } ;
2105
+
2106
+ // call functions
2107
+ let spender_leaf = get_spender_leaf (
2108
+ app. clone ( ) ,
2109
+ channel_context. clone ( ) ,
2110
+ Path ( ( channel. id ( ) , * ADVERTISER ) ) ,
2111
+ )
2112
+ . await
2113
+ . expect ( "should get spender leaf" ) ;
2114
+ let earner_leaf = get_earner_leaf (
2115
+ app. clone ( ) ,
2116
+ channel_context. clone ( ) ,
2117
+ Path ( ( channel. id ( ) , * PUBLISHER ) ) ,
2118
+ )
2119
+ . await
2120
+ . expect ( "should get earner leaf" ) ;
2121
+
2122
+ // compare results
2123
+ assert_eq ! ( spender_proof, spender_leaf. merkle_proof) ;
2124
+ assert_eq ! ( earner_proof, earner_leaf. merkle_proof) ;
2125
+ }
1900
2126
}
0 commit comments