From 9cd2b69f4aaeae4e3f7683a03ca3d76d9735e4bf Mon Sep 17 00:00:00 2001 From: Lukasz Klimek <842586+lklimek@users.noreply.github.com> Date: Mon, 17 Jun 2024 12:31:59 +0200 Subject: [PATCH 01/55] test(sdk): update test contested_resource_vote_states_not_found --- .../fetch/contested_resource_vote_state.rs | 35 +++--------------- ...5789c2cb3ec52359f6119ce08b53acca4ee93.json | Bin 34594 -> 0 bytes ...307684913cd9df63fe77d5bfbec1351fc28d.json} | Bin 15949 -> 16127 bytes ...71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json | Bin 81215 -> 80081 bytes ...7d5e2c4adee52c750b8024bb58964b3a48a76.json | 1 + ...119aacf74ce5a6e2b6587fd5a1b4dd74623ae.json | 1 - 6 files changed, 6 insertions(+), 31 deletions(-) delete mode 100644 packages/rs-sdk/tests/vectors/contested_resource_vote_states_not_found/msg_DocumentQuery_22942c9d389d6b8518bda36199d5789c2cb3ec52359f6119ce08b53acca4ee93.json rename packages/rs-sdk/tests/vectors/contested_resource_vote_states_not_found/{msg_GetContestedResourceVoteStateRequest_a7fa439911e16ae02a457f40a4a3968800dd88d3cd55c96ddc7005206ae8a91f.json => msg_GetContestedResourceVoteStateRequest_d45be23de4d7a849521ffc62a060307684913cd9df63fe77d5bfbec1351fc28d.json} (81%) create mode 100644 packages/rs-sdk/tests/vectors/contested_resource_vote_states_not_found/quorum_pubkey-106-01f298bc2eaa95b3d60a818e7e07d5e2c4adee52c750b8024bb58964b3a48a76.json delete mode 100644 packages/rs-sdk/tests/vectors/contested_resource_vote_states_not_found/quorum_pubkey-106-492dae0f1dd6ead4f24c870bd0c119aacf74ce5a6e2b6587fd5a1b4dd74623ae.json diff --git a/packages/rs-sdk/tests/fetch/contested_resource_vote_state.rs b/packages/rs-sdk/tests/fetch/contested_resource_vote_state.rs index 18c8c1056f2..cd7f4432b79 100644 --- a/packages/rs-sdk/tests/fetch/contested_resource_vote_state.rs +++ b/packages/rs-sdk/tests/fetch/contested_resource_vote_state.rs @@ -1,18 +1,13 @@ //! Tests for SDK requests that return one or more [Contender] objects. use crate::fetch::{common::setup_logs, config::Config}; -use dash_sdk::platform::{DocumentQuery, Fetch, FetchMany}; -use dpp::{ - data_contract::DataContract, - document::Document, - voting::{ - contender_structs::ContenderWithSerializedDocument, - vote_polls::contested_document_resource_vote_poll::ContestedDocumentResourceVotePoll, - }, +use dash_sdk::platform::FetchMany; +use dpp::voting::{ + contender_structs::ContenderWithSerializedDocument, + vote_polls::contested_document_resource_vote_poll::ContestedDocumentResourceVotePoll, }; use drive::query::vote_poll_vote_state_query::{ ContestedDocumentVotePollDriveQuery, ContestedDocumentVotePollDriveQueryResultType, }; -use std::sync::Arc; /// Given some data contract ID, document type and document ID, when I fetch it, then I get it. #[tokio::test(flavor = "multi_thread", worker_threads = 1)] @@ -26,26 +21,6 @@ async fn contested_resource_vote_states_not_found() { let data_contract_id = cfg.existing_data_contract_id; - let contract = Arc::new( - DataContract::fetch(&sdk, data_contract_id) - .await - .expect("fetch data contract") - .expect("data contract not found"), - ); - - // Fetch multiple documents so that we get document ID - let all_docs_query = - DocumentQuery::new(Arc::clone(&contract), &cfg.existing_document_type_name) - .expect("create SdkDocumentQuery"); - let first_doc = Document::fetch_many(&sdk, all_docs_query) - .await - .expect("fetch many documents") - .pop_first() - .expect("first item must exist") - .1 - .expect("document must exist"); - - tracing::info!("first_doc: {}", first_doc.to_string()); // Now query for individual document let query = ContestedDocumentVotePollDriveQuery { limit: None, @@ -53,7 +28,7 @@ async fn contested_resource_vote_states_not_found() { start_at: None, vote_poll: ContestedDocumentResourceVotePoll { index_name: "parentNameAndLabel".to_string(), - index_values: vec!["dash".into()], + index_values: vec!["non existing name".into()], document_type_name: cfg.existing_document_type_name, contract_id: data_contract_id, }, diff --git a/packages/rs-sdk/tests/vectors/contested_resource_vote_states_not_found/msg_DocumentQuery_22942c9d389d6b8518bda36199d5789c2cb3ec52359f6119ce08b53acca4ee93.json b/packages/rs-sdk/tests/vectors/contested_resource_vote_states_not_found/msg_DocumentQuery_22942c9d389d6b8518bda36199d5789c2cb3ec52359f6119ce08b53acca4ee93.json deleted file mode 100644 index affacd4a01fad533da312c6f8e52ddbe4df283eb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 34594 zcmeI5Yj@nnk%seGzXAtG=O}yDaMu_mU(X=S_Yxs>-I$M@{;h-|l= z*i3AF`{T~^Z+WKnKP-yc&!3HLZbftTX*sH|W{rvdQMD+?e*A?GYbh6#Nk;(vXP)?L zpNSjyZn=M(J$1`ZsyC&tpT%w6|McwP@#ppB@+Sd8#!cTLP-n=)(bR~!vu{|`l+GU$JuBLer)N1vKeb!vfynT{Z zr{8!y$%L+fTq;VS%>mcg1P#gBgcW$gP&Tz(iKEI6N!($1{H z6U)5{f42YK*l9b*YkKPS{AwfB&~LgZiyszY5?u{$M@-FH8$WMNkHe>Dg`bR{=Z$SG zrFz|jZMgVUSn@_7+vK~PK<&@{+b{E`@pVL?|NS=K`SIb-UkC2hPkW!Z<9GKdHWOTL zxk-Wr+Z@cws>vdlmQ7^Pmxncv{d`mx(e%PZpPePmg-D$=Qhy)U8b8kG7c1y79Ow%r{khs+`%zVo z=ewcTKSl-X^!>qF+S%auUE0G*k~|U#d3CzU#*O2=XmGUPlHbm+`G*uukN#xX;J>pm*>rejlKuHnC5TSZ3k?e zRr6xIk*-E8+xcz6Z>EBGL4AyGM(68wU5X#PTmyFg|!aWt(wTm4o)9XU+#~pY2a4@JD)G+O>*iJ<2Lyu^caw|h0mhgEauu7PM6Q$ zIMW-nr1j%HU;B3((EY!yz0U{P5FAeWzBZJ>_TZ)-CTB(sgI6-yC*w#jlE7zHdlj(w z{VZw=L-|0d_07i6ruV_l%a^+wAnG-3F|iID{k@_jQi&*4iss=r`ufW-zPO>cTAw%D z_I1w)jhy(m79E+#SSgBuiJ#7zt6-xei>u7$bNhQ{eCE=)PODBIXr{>@ELMvM5JJvK zX97D)V(ej9R<1_oxbvGVy!OU4eElMiVcRu&n%8xHMNyqzHU432*h+rQ?>%e$G;rHJ z+Me0$wQU`@w|}$AhB+sTxgonLS3t(uaxo_FHr(lQy1xHgGOX(vfy7Y3*<4RBV(T?@ ztuNGg=Zbf16KuTUX5q$LZV+(We!Y-mdq>a!g4i7Ca@joh<0Aih8Cd4C*`ydnulQeY zBRkz4&t|(tjJYi|si7mWBcQ{I^d--p1Zy$x7PoL?IPFdr)4aZl035e=_0+ZjZuOWe zb!bhcs}x~^J;i8eY*4QR^_Rbmpha;l|FCT|{*=$-2F@eihi(1;+{JZ3uw_qEvz0Hq z83#xzkcb=GJGL?eDCOgEr0Myj*8|ckaWA@x`nW1B=&%${)6z$qL8O*8Q^T=UawIWo zx~RRGKyE-E@V_d3(%PGOn-;}F+#GFaCs}%{Jo#=L7JZkPpIWv-zrX8RMb9GA`Qo(o zUtcXOI{&zcX;FRk=EZ6N?L3NY1(v5(HSu}54FZ5MUx%DR6;lw&*q;@~=q(9gu6g4m z*Q=Vh-YeNL@n4yA|GUkM*>#k6P}?ONjE;8O=-qwYIO&!`w%*yM6PMaXAxnm^nL;#> zkgzb(w|`_%T#X2rhbd{rBs++`>W2?CV|tDf~Brv#+O|$(*s?ZNQ8V%qmcdHeJe&1 z=~b^~ML>EVuEp1y+Il&!Hg~)sT*Q%bi? zrrX}h;%#Ho>CH?!FoSDDk@pN!z@9Zbx3H2|GQY@ovf)9S@{ZYPBhtQ%WIBA9TbN{e zY>{JasqJc-gmp*t%sZB{GTK;aSqriY{A+DB!CVJ-BGPqFABZ$xG6MT>snLTvji}Q<^$a6z?)G(m{(qwMg=4UZ0vU3Ubtr=}WJlTHD; zLweJ8?6wdcsG^mseV9rn+%pd|p?VetdeeYW#MsS%JEA zW)Los7RUyjMTT}z?T%PNE3*oRNEc*7beCbgA+EC_dT__=VaOG*k0W+*bhz=|Vb)CZ zXW4Q8hW(@dHCJ(nIdP6|pUdKu_8`au^yowmdswzR1b=h~SY}4SI7&aGEZGAEvj)i3zKES0r!aC7@r(r>ZlRFKIVu=6HS{8d^xZafcWp zbAS}ub2i`{h`jEIeeUxSOwy=#AGaJHAS?}We})c;C^UZBYPOFK97j07j1I6@`w+Bq z_#k7C?hsgu2XIOF;m&iPIGkKVCUg~4HTJ(xJ;7>@(e9`w)c#u^a04JLmvqcM!8P0O zMEcQ1iXDOu?V7_8lYRmk2~+VViy0F-V@q! z^W`428@}sKwU(-MN6dmCfJ3+hHZ!vzD3>`rk?qkT4B!yl5s*@{4MN+6ZZa?s$0dCA3+Nx^IZ4Uul0xod){Ner6rWh>aZ>7Wz=lkG0ns57 z^I`gA4_J?BJBjjzz|kOyFfwa#Y0OlL29PQ{g=N6lF;K#h@j1F1ssz;f&bx0YUvlT& z*TR51ht}NOdP`R1PUY58wmRk=pDMH{&$tZ7Acl_4aSq~zq(;dAPgD|V2C?tTS zAR~F9O3|gWounS^vN^gcvcfwZTUz_Std22G6QU_;399YgVT@KsnAG?eJdDApgjh}Z z_(uelfMH-DE;WbEBQl7~#0xt@q(n`0SK>609CJKr#M(R4mpr4xC|bfarscJY!m3He zIGRB*=OD#>t=%)FCfNWxpxe)xs5+6-@Qi^T%jDY0M;L!XVW3@i=(+Tdnu-PqBO8+4 zhZX!&q9?QimsBOBk#M)366zZRvAExgv2ZEo-G3M}kywS?SJHHMrQH>6B!cn8C+h;N ztw_yX~$|+CWj4Z2O5#namxX138$T8NEk3P zSs``FjBjL+PLL;Ml%~A(A#VmSQP0EzD;5&gJMO61me#xBeU*917Q&@CIt3?3DS3)j zivgGg#w2BM%&`gk6R?DFWVC38`Hn%|7CpqINg%a;&JC3ag4rh?vX?_n?139DRTrkj zh&o!)0+5lOG4d09KL%eBiXf+`sKvLc3up@?InF@NF;G9nunytHSWL{QEt0xqm0Zx_ z5Tr08ygS;iR3Bv)_9A7U-|3+bhMW>IGN#n55cXI6Gno#RT!TBEHk43~Ry%H?#($76 zB;%NZ#j0TIQUiCI&c;C%8j3{wl7t7)GWrKdVnIA(?;KVnuR_Q^$&$1SOi{K{?0~>5 zQX!>~tO_Acxfpf&)-j~K%~^`9WUs^}ZP{Mx5OMC-X+YW;-QX5_g-4|7F0VOAVugAo zvf)cD8zB)#Cd&0I^F>3_Hq22%g{}LwFt^ zkhi%Q+-S9tv{dL9v5bt+$!72a>5?$i7d2n3qIQt&OR!9aDMxDc6fO%(BuBb=65MiB zazIB4CnQkF5?P2~hSu46_)-Rum+rX`hLQAkWS;WMG{50M;!rshO;Zs*uJ%nFBem$O z6jX>V34n!5JPabPdm>1}muQu#=_8z?_JI}i0p=4VqL2Vo&P#Bm0!L~k5S<)%5S9%1 zVeBTMnpDjMElBwEiz`5j^}8=<5)7TBpd=+H`9R-p?`x>Mk0Q>1^&Xy}Vep@cRox7` zx>x-f!VCyBV&#$w66BFYEp)j1#X2FWExGoDWy~fZN}eKQRp^uC(5RqtD46>%-NUVs5EoBIK z=SJV+ltCCMFjx^$$ct34HEx&SESI4vbVj$zG$k$+qy->2z7HlZOb`bp{9sfjyq~2X z*$zkHGVpU`R&o@`3GgxMc7#r;duiH(c*qKplr8z~ACB<`)Bl7O@M4035G_gXInq5= zDAaYbmLus0`En1@0ft@F2~jht2Z}D=Y7Rtb=9e6g05CBICat+W@EQUz%~8G-ikw7V z%U1snk4$^!_t$`PB2@?kqUpnf^)JygU((fl01F%RcS2@`CT{V{n6i9Znb35xNYE(oZ-?fCC{42=-w|_o!QX@J3ESF#u(3rgeZK?i4 z!{i%$x#PmkxZzr7WB4SbMi?feV`0XsRg@l~e~VIqr$`x84h7PENQO|(>p2!er9Old zFVS1LfTA@JMLh->74yAE} zFg4D?EG3mDu8Z7wOZ`?X1j5p9VdG08BnhMyk~O4F5v?UWq#|lPl!YIm%bGZ*6)GD> z4o`w@0eH#Kl7dUzMn_M7O46wQmGKmLtH?xhm=ow&UJLxIq7@V9srYF!RSSOG`zPAJ`+mqj_!E(3sjSj*D zbxcoBQWW9@rKlqGhL8g9JCD#&)F% zty*IwD4L=liJ%x4Zd4jeQZSL1x&@1IMM*R?F(x*VvL?{h@7&qgWOABw|8xHD{~l*) zX7jC!6IO#)?r(t`i6Yi(BNef6)(PTDzz%r%9KZaMhz2~b$p1b`MsX`qtNEu~t26ai z6G42JukDR^G#tT`rDC1=X0U8^qBL7oTkvY$P>aA5?HhY+Ps(v~_7DI|Yw3 zf)!!=(hydX4jN;E^{B>Fm%{0=U@agx->IF)E8jSHB0$T}|k_xX7^lXRt@KU^U zvR`o~Mc9IeWeyayF{cH~A%&CO8ZT)F8-(|2QhYp|AA8xy^l!~7e{Z=@;b20np*)@` zxNz9|L94>qfJUVtewm@rZ6SSO+lT*^=Fy_UBewXkTkx_{xWTJkj<&m^@qSuxj%`nD zt+i+&%yX{gswFxIcF{1ASQ zxM-$6m!A-zk)%?iV@l&!u9bqqFo{?p!b24L8p&GRrm>%04GCv#fg$V>ue`xJdkfL> zj?oc~`DVd8M0T5EyjfC+6FsNb#+~v1{ZZSWT077b6uiLe=Y*uBHD)-toeJU9b{nJA zw8Dvu*D5^iW!92@-nEkEtyqvF~M+1>uT5V9@C5*`+Y$9?)8@?7oIzR?q0jiF5pSL0-d z@@$Yrmx-U|{e*AQ{Cl_^Yuq;Pn3>KQsYzud`j=4dkd^ru6(^Jm;ol=vzB!Dj^53$d O3a2d41aTzx^!x`95!b;0 delta 1736 zcmZXVUuauZ9LMQx+L*M>J?EsZrdfJ#OK1P2$#Ro>^QTR8Fu`H}=!2b(Irbnv=-l?I zxJ=*19@Y-O=or#$LP4F{3Ii40?3184t%G5mmbD@x+hFaB4=Pr_=f(%k3WucU-t#-( z^ZkB)Cx2JJKK8+01J8;MjE|Z4b0~r}kdoCs`RQ?|rqj#HGZzaQd}^=DTfZQyfzRP1mHg@&5BOv41_?+IDB z8jpW+r4 zs7Tk>qpB3Hbuc1YAw~rjf&|kEtFMb!MBDeEiAE@+v=qC0ks?+ z!N_JYYg@XCe|}MrnCO(a*27E)(RS|S4hlTU<>gL+?|AAC4y{v{T409StDC0upVh|d zDi5$muuI^jl)`#Y7)}9~lD$~>1O`dR9L4|QDvZ*|Me;ix5q|l(iphMR(JkR~- zrNr+vj@&nAGbOBsdi-NrBzHP0IvuBh_bkOv1_>Ya=&_ZHU^64JtIZdSFn#%?-9(vv ztg+_-{Bc6qSRPQAp-yeLj>PQMxk{XiiHq~w_9c8&Ub{yiNyEM;PF23V7*u$uTVj#e zwYw5aMDCSNn&@DPZKl1xnW6`LG}R$}>aK^QSmGZ0hNQu};%dg`3Pwq*^zo)pSlY?@?#(rWpLcy9Hjo;a%!V*&}v)VU#&5p!O zoUITPzKbbh8qh5eR@h|w>37%Jjynm<7DK4Fs>1D%X?P{ru7zK>^EH+`$TOsd75?Dy zH@U2vLeCOiJ%5auYF~9(lL3vS6<$`FLB-yftt2S4evO^cH1gW|m@99P$T^D8SS|2# zpaPP&h( z1n!jTmmb42ibcE`v~jvf&qDHE@Bep=SJMCEsu63kZ6{yE_>hG(y{yqoCS>G1JX4;+ zQHFPgyR25EQ7GVW%61zs(!1`pd?UB6hxghO?4Kys^CnjASNN7FO)<`S$=JyC<)npC t#*`lB4*-3&+B5)7qZYnO*4tyxI`|@IW95Ote*jh6_sjqQ diff --git a/packages/rs-sdk/tests/vectors/contested_resource_vote_states_not_found/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json b/packages/rs-sdk/tests/vectors/contested_resource_vote_states_not_found/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json index 35d918b6b3ab399ebe8bbe06d3221cc5b6f6772e..cd23871fb34aed6bad4a9e3ff6b4519b8f9f43ef 100644 GIT binary patch delta 1910 zcmZWqO>9(E6wZB9N>ST)@2i4CZQqps|IN&szc=lGfk1+Zu?1O3TEdhV7b-G!D}mN% zf`&w^C*g=-(2YP8A#PY0n3`xz085DrjHDDp0t-V63ynWW{mvaiG0M`|3f{QvoWAU++;ZNTSDGeo zYP$8Q=EZJh_{Rbsk9R5)39@-k_Nb-$g+o9TTh_OHKGCjGw! zUe~33x*9=}eJ;;-ss!!0+(M&MF7IzfIi0A9{1J~oiz}Bdp4Co1$0wVW&pQXOGxm*3 ziyI8@%HY;_mZ0iy(>P_je71m2>e8rhVP4ywd9EA3#%nb1YEhnT>6VX!OXQ|QJ=iOw zlf)LyAH;zW>ZKsk$nh9r_GXkh4FEo>qUxnUFP-PjZ75?Am`MExdhvhnu&&(wIWp4r zxq2!Ox>Q7WC-1s6kKEpteQLf5(LjRLbpn<*9() zyV=a{DrKBZKVNIdoro|_nB~SOuzP^p+DIKgvl{o_zHRvKGQ7Na(B&Z%Pl+nSBgp6k zS$ds(z7Us1^eGi^F~o(VG2mOQ(WHGX9r7OFTY)s%h+Nt0hQ^0o-q?)b!_XD?M6o;% z4LpT1xd(`HLn9cN7a5&v#SNueEfRZ~yIWK}|5U){o+!e~(%k4H2$TECM;*M~H{Z_U@YD`CK+u%Csvkwp#Q?rf0^71^;kRmCv0pJ^ zMEATXTKOJFg?x__ZAiC%rHDI|;t5fy)Hy57|BykzI1u2sdhysT{%e40Eo?y3s66cm zn^eeSEvi|R3PINx2K&ZVSD()RcZvi-o>fXkc}qq$IQa~p6HI5?Jf0Dg9T&5tL;Ct` z6N@eRs_qrqBt9y7&)c^;>^C~{V8f-=$Tw53`5H{cLkUE{ z9GXipoJ_2T6ea#p9-%mHXN1RvZsj^bhJM~1vsR*0`|VVx?I$V&fvz2creqGBZw1lf zT06Kf8Vp~QKIR1C(S3F(@`%`EE`$PWE904V;o~udNjrJdIJtm78Bl}5n|Q&_Vml>& zulB8ft^Hm?i4lC|*sM}9o)kwP5f8{0iM~L(vD!M?bmqQAcgw#z_i)GVB?9X@J*rb?}a5L}TbI(2J zJKy=v?ca*Vo)nGNMT%VC&C%LOZIS0>(zG?wxX24~uAj>`xzr!oq=FCbL@wTmsO)lf zd}Yz&-J080DNVZ$X!Nh0{3Dw?Yn9=vRX7=#)jVFSbR_FgurSUYfzsUN$jN(} zFE+w%LnW3}QrUcWHTGM&4Ij_K>dG4IFLSXpddfsS*W;O(N>ERm=9z>twCSKe{t|9j zC5ES>xUp-6(yEC~wW{Zel0vq@%v@u%vtn()P%1- zj>39mk45c8HXmDykKR_zLsf+c>_S5AOD#^-AlSijJeH=b({bhVyQ>fwuBkNZIDSgn z+v?$AqPR5bd1-#ZRdF6)gP86&D7!3h>lY{f^XEBfx^gehRVk&Tu9u_yo*4D+*3@N; zq-BXCD(%;_<D*PF#?30=hOGqrJ_BI*N>>qPa3a8gsxK zKstOo3gbjI{OX+Mew2$Q1IjElh5$|WH!e8KttXkFurnD)6N4n-$Z&e^|9f%!0Pav`atQSya{<;SOhk1 zU7=F^5P4AR2p+01{8tQD#z6I`n@Mxf0Jd2rnjRlB+%0tv^N25(cx~P;@glUc?DIqb z%P*}&aZc4MTV*I;ho3@rDMiP(dYR|t=2OS@GjygnPJItG9q!VCzTtHsC;jk-p)J=f z;ZLams%iMCMKhhq6?U>q`PVgnBq*P(KuLPRK8}Mz)Y6Z-`5q5eBa}7}xy<#`^WXJ6 zZm$B>8#?jII=fJ;pBv$(234oih_~;dq5FYFB^)y9{n;4Zx~J*GYR%>Fsa!4%RHCfO zpYPdi@_G9j6^}xX*a-mS@Keo;geoolh8l}>p#yeQBh#-%AS{h%Av&7Irwx@>LYCk^ z>ISaRn0H7EzXpb3C(Au4M14AMMLd_!tyD>#f-P^&;r7mMD^wHE=^2Gi)fS2xs#GMG zSZ#VtU-bx;4-xRd>lOA=ko|qWjW!Y4$x7sbJ`{icPM2f?MNR|Z>JWCwE0AX%2KQn z;6t}^!kU{4L#+(YO({e% zVPb8lo&**bZlc?G1Sg?52;KQ7>08k!>1x28;kzl7;f<9r3YD}$bZDz9ecKkcD}N`P z$wPa2qE=ZVWq*_d-a#1>V;c=E1;LK6rm0?$Gc93V1Adq{5?aAoXw4fStvo8VJ1UFT zSezslOb1ISr+Fj|6R3`nj8FiSuBSE5+iJ1h>fuEzXCRzmQMq#!U_$K*?+DXGC8!a2 zL&eLW{_C$-N&M!2`q<&4P-JSkfk_}*_0>vTm$^`x!WVkl7L@_bMADvQaX8)pf_H~W z%5h9ofA2wNAQ6=mYnG|Omth*VCx)ts24AVc?&uN`Of>xG6=-`Ka%%NI7{Pu@ diff --git a/packages/rs-sdk/tests/vectors/contested_resource_vote_states_not_found/quorum_pubkey-106-01f298bc2eaa95b3d60a818e7e07d5e2c4adee52c750b8024bb58964b3a48a76.json b/packages/rs-sdk/tests/vectors/contested_resource_vote_states_not_found/quorum_pubkey-106-01f298bc2eaa95b3d60a818e7e07d5e2c4adee52c750b8024bb58964b3a48a76.json new file mode 100644 index 00000000000..fed490402ef --- /dev/null +++ b/packages/rs-sdk/tests/vectors/contested_resource_vote_states_not_found/quorum_pubkey-106-01f298bc2eaa95b3d60a818e7e07d5e2c4adee52c750b8024bb58964b3a48a76.json @@ -0,0 +1 @@ +9838eb549dc11d015245e1c764a0e69aba65975e8c08faa8f2ff03c48465892794b60301cba3cfdd298cff2c01d12e3c \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/contested_resource_vote_states_not_found/quorum_pubkey-106-492dae0f1dd6ead4f24c870bd0c119aacf74ce5a6e2b6587fd5a1b4dd74623ae.json b/packages/rs-sdk/tests/vectors/contested_resource_vote_states_not_found/quorum_pubkey-106-492dae0f1dd6ead4f24c870bd0c119aacf74ce5a6e2b6587fd5a1b4dd74623ae.json deleted file mode 100644 index ccd69e38275..00000000000 --- a/packages/rs-sdk/tests/vectors/contested_resource_vote_states_not_found/quorum_pubkey-106-492dae0f1dd6ead4f24c870bd0c119aacf74ce5a6e2b6587fd5a1b4dd74623ae.json +++ /dev/null @@ -1 +0,0 @@ -aa51132a4e62cec89b731aa8baf4043fea777c484a4856e3b7c9a13c651ff2a9057d30cd251190bde749ac8f7c0026b6 \ No newline at end of file From 01b87be4b7d4c49b79ed4d9c3d57711a32c01881 Mon Sep 17 00:00:00 2001 From: Lukasz Klimek <842586+lklimek@users.noreply.github.com> Date: Tue, 18 Jun 2024 10:43:34 +0200 Subject: [PATCH 02/55] chore: minor improvements --- packages/rs-drive-proof-verifier/src/types.rs | 4 ++-- packages/rs-sdk/src/platform/query.rs | 17 +++++++++++++++++ 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/packages/rs-drive-proof-verifier/src/types.rs b/packages/rs-drive-proof-verifier/src/types.rs index b1a89489dba..fce062141ee 100644 --- a/packages/rs-drive-proof-verifier/src/types.rs +++ b/packages/rs-drive-proof-verifier/src/types.rs @@ -64,7 +64,7 @@ pub type DataContracts = RetrievedObjects; /// /// Mapping between the contenders identity IDs and their info. /// If a contender is not found, it is represented as `None`. -#[derive(Default)] +#[derive(Default, Debug, Clone)] #[cfg_attr( feature = "mocks", derive(Encode, Decode, PlatformSerialize, PlatformDeserialize,), @@ -248,7 +248,7 @@ pub type ResourceVotesByIdentity = RetrievedObjects; derive(Encode, Decode, PlatformSerialize, PlatformDeserialize), platform_serialize(unversioned) )] -pub struct PrefundedSpecializedBalance(Credits); +pub struct PrefundedSpecializedBalance(pub Credits); impl PrefundedSpecializedBalance { /// Get the balance. pub fn to_credits(&self) -> Credits { diff --git a/packages/rs-sdk/src/platform/query.rs b/packages/rs-sdk/src/platform/query.rs index 21cba50abdc..bddd9639091 100644 --- a/packages/rs-sdk/src/platform/query.rs +++ b/packages/rs-sdk/src/platform/query.rs @@ -360,6 +360,23 @@ impl Query } } +impl Query for ProTxHash { + fn query(self, prove: bool) -> Result { + if !prove { + unimplemented!("queries without proofs are not supported yet"); + } + Ok(GetContestedResourceIdentityVotesRequestV0 { + identity_id: self.to_byte_array().to_vec(), + prove, + limit: None, + offset: None, + order_ascending: true, + start_at_vote_poll_id_info: None, + } + .into()) + } +} + impl Query for VotePollsByEndDateDriveQuery { fn query(self, prove: bool) -> Result { if !prove { From 9af521e5f3c31c5ed800d4586b0a5bc5ccd9ee62 Mon Sep 17 00:00:00 2001 From: Lukasz Klimek <842586+lklimek@users.noreply.github.com> Date: Tue, 18 Jun 2024 16:53:35 +0200 Subject: [PATCH 03/55] test(sdk): mn voting tests WIP --- packages/rs-drive-proof-verifier/src/types.rs | 18 +- .../rs-sdk/tests/fetch/contested_resource.rs | 188 +++++++++++++++++- .../contested_resource_identity_votes.rs | 36 +++- .../fetch/contested_resource_vote_state.rs | 185 ++++++++++++++++- .../tests/fetch/contested_resource_voters.rs | 63 +++++- .../fetch/prefunded_specialized_balance.rs | 54 ++++- 6 files changed, 523 insertions(+), 21 deletions(-) diff --git a/packages/rs-drive-proof-verifier/src/types.rs b/packages/rs-drive-proof-verifier/src/types.rs index fce062141ee..70c5f2b8d9e 100644 --- a/packages/rs-drive-proof-verifier/src/types.rs +++ b/packages/rs-drive-proof-verifier/src/types.rs @@ -159,12 +159,26 @@ pub type IdentityBalance = u64; pub type IdentityBalanceAndRevision = (u64, Revision); /// Contested resource values. -#[derive(Debug, derive_more::From, Clone)] +#[derive(Debug, derive_more::From, Clone, PartialEq)] pub enum ContestedResource { /// Generic [Value] Value(Value), } +impl ContestedResource { + /// Get the value. + pub fn encode_to_vec( + &self, + platform_version: &PlatformVersion, + ) -> Result, bincode::error::EncodeError> { + platform_serialization::platform_encode_to_vec( + self, + bincode::config::standard(), + platform_version, + ) + } +} + #[cfg(feature = "mocks")] impl PlatformVersionEncode for ContestedResource { fn platform_encode( @@ -173,7 +187,7 @@ impl PlatformVersionEncode for ContestedResource { _platform_version: &platform_version::PlatformVersion, ) -> Result<(), bincode::error::EncodeError> { match self { - ContestedResource::Value(document) => document.encode(encoder), + ContestedResource::Value(value) => value.encode(encoder), } } } diff --git a/packages/rs-sdk/tests/fetch/contested_resource.rs b/packages/rs-sdk/tests/fetch/contested_resource.rs index 5ee7257fefa..19690d648c4 100644 --- a/packages/rs-sdk/tests/fetch/contested_resource.rs +++ b/packages/rs-sdk/tests/fetch/contested_resource.rs @@ -1,14 +1,18 @@ //! Tests of ContestedResource object - use crate::fetch::{common::setup_logs, config::Config}; use dash_sdk::platform::FetchMany; use dpp::platform_value::Value; use drive::query::vote_polls_by_document_type_query::VotePollsByDocumentTypeQuery; use drive_proof_verifier::types::ContestedResource; +/// Test that we can fetch contested resources +/// +/// ## Preconditions +/// +/// 1. At least one contested resource exists #[tokio::test(flavor = "multi_thread", worker_threads = 1)] #[cfg_attr( - feature = "network-testing", + feature = "network-testing1", ignore = "requires a DPNS name to be registered" )] async fn test_contested_resources_ok() { @@ -34,6 +38,184 @@ async fn test_contested_resources_ok() { let rss = ContestedResource::fetch_many(&sdk, query) .await .expect("fetch contested resources"); - + tracing::debug!(contested_resources=?rss, "Contested resources"); assert!(!rss.0.is_empty()); } + +#[tokio::test(flavor = "multi_thread", worker_threads = 1)] +#[cfg_attr( + feature = "network-testing1", + ignore = "requires a DPNS name to be registered" +)] +/// Test pagination +/// +/// ## Preconditions +/// +/// 1. Multiple contested resources exists +async fn contested_resources_paginate() { + setup_logs(); + + let cfg = Config::new(); + + let sdk = cfg.setup_api("contested_resources_paginate").await; + // Given all contested resources sorted ascending + let index_name = "parentNameAndLabel"; + + let query_all = VotePollsByDocumentTypeQuery { + contract_id: cfg.existing_data_contract_id, + document_type_name: cfg.existing_document_type_name.clone(), + index_name: index_name.to_string(), + start_at_value: None, + start_index_values: vec![Value::Text("dash".into())], + end_index_values: vec![], + limit: None, + order_ascending: true, + }; + + let all = ContestedResource::fetch_many(&sdk, query_all.clone()) + .await + .expect("fetch contested resources"); + + tracing::debug!(contested_resources=?all, "All contested resources"); + // when I set start_at_value to some value, + + // for key,val in all + for (i, start) in all.0.iter().enumerate() { + if i != 2 { + continue; + } + let start_vec = start + .encode_to_vec(sdk.version()) + .expect("encode current value"); + + let query = VotePollsByDocumentTypeQuery { + start_at_value: Some((start_vec, false)), + ..query_all.clone() + }; + + let rss = ContestedResource::fetch_many(&sdk, query) + .await + .expect("fetch contested resources"); + tracing::debug!(?start, contested_resources=?rss, "Contested resources"); + assert!(!rss.0.is_empty()); + + for (j, fetched) in rss.0.into_iter().enumerate() { + let all_index = i + j; // we fetch exclusive + + assert_eq!( + fetched, + (all.0[all_index]), + "when starting with {:?}, fetched element {} ({:?}) must equal all element {} ({:?})", + start, + j, + fetched, + all_index, + all.0[all_index] + ); + } + } +} + +#[tokio::test(flavor = "multi_thread", worker_threads = 1)] +#[cfg_attr( + feature = "network-testing1", + ignore = "requires at least 3 DPNS name contests" +)] + +async fn contested_resources_limit() { + setup_logs(); + + let cfg = Config::new(); + + let sdk = cfg.setup_api("contested_resources_limit").await; + + // Given index with more than 2 contested resources + const LIMIT: u16 = 2; + const LIMIT_ALL: u16 = 100; + let index_name = "parentNameAndLabel"; + + // ... and number of all contested resources + let query_all = VotePollsByDocumentTypeQuery { + contract_id: cfg.existing_data_contract_id, + document_type_name: cfg.existing_document_type_name.clone(), + index_name: index_name.to_string(), + start_at_value: None, + start_index_values: vec![Value::Text("dash".into())], + end_index_values: vec![], + limit: Some(LIMIT_ALL), + order_ascending: false, + }; + let count_all = ContestedResource::fetch_many(&sdk, query_all.clone()) + .await + .expect("fetch contested resources") + .0 + .len() as u16; + + // When we query for 2 contested values at a time, we get all of them + let mut i = 0; + let mut start_at_value = None; + while i < count_all && i < LIMIT_ALL { + let query = VotePollsByDocumentTypeQuery { + limit: Some(LIMIT), + start_at_value, + ..query_all.clone() + }; + + let rss = ContestedResource::fetch_many(&sdk, query) + .await + .expect("fetch contested resources"); + tracing::debug!(contested_resources=?rss, "Contested resources"); + let length = rss.0.len(); + let expected = if i + LIMIT > count_all { + count_all - i + } else { + LIMIT + }; + assert_eq!(length, expected as usize); + + let ContestedResource::Value(last) = rss.0.last().expect("last contested resource"); + let last_value = dpp::bincode::encode_to_vec(last, dpp::bincode::config::standard()) + .expect("encode last value"); + start_at_value = Some((last_value, false)); + tracing::debug!(contested_resources=?rss, i, "Contested resources"); + + i += length as u16; + } + + assert_eq!(i, count_all, "all contested resources fetched"); +} + +#[tokio::test(flavor = "multi_thread", worker_threads = 1)] + +/// Empty string in start_index_values should not cause an error +async fn test_contested_resources_idx_value_empty_string() { + setup_logs(); + + let cfg = Config::new(); + + let sdk = cfg + .setup_api("test_contested_resources_idx_value_empty_string") + .await; + + // Given an empty string as index value + let index_name = "parentNameAndLabel"; + let index_value = Value::Text("".to_string()); + + // When I send a VotePollsByDocumentTypeQuery with this index value + let query = VotePollsByDocumentTypeQuery { + contract_id: cfg.existing_data_contract_id, + document_type_name: cfg.existing_document_type_name.clone(), + index_name: index_name.to_string(), + start_at_value: None, + // start_index_values: vec![], // Value(Text("dash")), Value(Text(""))]) + start_index_values: vec![index_value], + end_index_values: vec![], + limit: None, + order_ascending: false, + }; + let result = ContestedResource::fetch_many(&sdk, query).await; + tracing::debug!(contested_resources=?result, "Contested resources"); + + // Then I don't get an error + assert!(result.is_ok(), "empty index value shall not cause an error"); +} diff --git a/packages/rs-sdk/tests/fetch/contested_resource_identity_votes.rs b/packages/rs-sdk/tests/fetch/contested_resource_identity_votes.rs index addda645e87..84c754b8340 100644 --- a/packages/rs-sdk/tests/fetch/contested_resource_identity_votes.rs +++ b/packages/rs-sdk/tests/fetch/contested_resource_identity_votes.rs @@ -2,10 +2,12 @@ use crate::fetch::{common::setup_logs, config::Config}; use dash_sdk::platform::FetchMany; -use dpp::voting::votes::resource_vote::ResourceVote; +use dpp::{ + dashcore::ProTxHash, identifier::Identifier, voting::votes::resource_vote::ResourceVote, +}; use drive::query::contested_resource_votes_given_by_identity_query::ContestedResourceVotesGivenByIdentityQuery; -/// Given some data contract ID, document type and document ID, when I fetch it, then I get it. +/// When we request votes for a non-existing identity, we should get no votes. #[tokio::test(flavor = "multi_thread", worker_threads = 1)] async fn contested_resource_identity_votes_not_found() { setup_logs(); @@ -15,17 +17,43 @@ async fn contested_resource_identity_votes_not_found() { .setup_api("contested_resource_identity_votes_not_found") .await; + // Given some non-existing identity ID + let identity_id = Identifier::new([0xff; 32]); + + // When I query for votes given by this identity let query = ContestedResourceVotesGivenByIdentityQuery { - identity_id: cfg.existing_identity_id, + identity_id, limit: None, offset: None, order_ascending: true, start_at: None, }; - let votes = ResourceVote::fetch_many(&sdk, query) .await .expect("fetch votes for identity"); + // Then I get no votes assert!(votes.is_empty(), "no votes expected for this query"); } + +/// When we request votes for an existing identity, we should get some votes. +#[tokio::test(flavor = "multi_thread", worker_threads = 1)] +async fn contested_resource_identity_votes_ok() { + setup_logs(); + + let cfg = Config::new(); + let sdk = cfg.setup_api("contested_resource_identity_votes_ok").await; + + // Given some existing identity ID, that is, proTxHash of some Validator + // TODO: Fetch proTxHash from the network + let protx_hex = "7624E7D0D7C8837D4D02A19700F4116091A8AD145352420193DE8828F6D00BBF"; + let protx = ProTxHash::from_hex(protx_hex).expect("ProTxHash from hex"); + + // When I query for votes given by this identity + let votes = ResourceVote::fetch_many(&sdk, protx) + .await + .expect("fetch votes for identity"); + + // Then I get some votes + assert!(!votes.is_empty(), "votes expected for this query"); +} diff --git a/packages/rs-sdk/tests/fetch/contested_resource_vote_state.rs b/packages/rs-sdk/tests/fetch/contested_resource_vote_state.rs index cd7f4432b79..44b97c40aba 100644 --- a/packages/rs-sdk/tests/fetch/contested_resource_vote_state.rs +++ b/packages/rs-sdk/tests/fetch/contested_resource_vote_state.rs @@ -1,15 +1,20 @@ //! Tests for SDK requests that return one or more [Contender] objects. use crate::fetch::{common::setup_logs, config::Config}; use dash_sdk::platform::FetchMany; -use dpp::voting::{ - contender_structs::ContenderWithSerializedDocument, - vote_polls::contested_document_resource_vote_poll::ContestedDocumentResourceVotePoll, +use dpp::{ + identifier::Identifier, + platform_value::Value, + util::strings::convert_to_homograph_safe_chars, + voting::{ + contender_structs::ContenderWithSerializedDocument, + vote_polls::contested_document_resource_vote_poll::ContestedDocumentResourceVotePoll, + }, }; use drive::query::vote_poll_vote_state_query::{ ContestedDocumentVotePollDriveQuery, ContestedDocumentVotePollDriveQueryResultType, }; -/// Given some data contract ID, document type and document ID, when I fetch it, then I get it. +/// Ensure we get proof of non-existence when querying for a non-existing index value. #[tokio::test(flavor = "multi_thread", worker_threads = 1)] async fn contested_resource_vote_states_not_found() { setup_logs(); @@ -18,17 +23,18 @@ async fn contested_resource_vote_states_not_found() { let sdk = cfg .setup_api("contested_resource_vote_states_not_found") .await; - + // Given some existing data contract ID and non-existing label let data_contract_id = cfg.existing_data_contract_id; + let label = "non existing name"; - // Now query for individual document + // When I query for vote poll states let query = ContestedDocumentVotePollDriveQuery { limit: None, offset: None, start_at: None, vote_poll: ContestedDocumentResourceVotePoll { index_name: "parentNameAndLabel".to_string(), - index_values: vec!["non existing name".into()], + index_values: vec![label.into()], document_type_name: cfg.existing_document_type_name, contract_id: data_contract_id, }, @@ -40,9 +46,172 @@ async fn contested_resource_vote_states_not_found() { let contenders = ContenderWithSerializedDocument::fetch_many(&sdk, query) .await .expect("fetch many contenders"); - + // Then I get no contenders assert!( contenders.contenders.is_empty(), "no contenders expected for this query" ); } + +/// Asking for non-existing contract should return error. +/// +/// Note: due to the way error handling is implemented, this test will not work +/// correctly in offline mode. +#[cfg_attr( + feature = "offline-testing", + ignore = "offline mode does not support this test" +)] +#[tokio::test(flavor = "multi_thread", worker_threads = 1)] +async fn contested_resource_vote_states_nx_contract() { + setup_logs(); + + let cfg = Config::new(); + let sdk = cfg + .setup_api("contested_resource_vote_states_nx_contract") + .await; + + // Given some non-existing contract ID + let data_contract_id = Identifier::new([0xff; 32]); + + // When I query for votes referring this contract ID + let query = ContestedDocumentVotePollDriveQuery { + limit: None, + offset: None, + start_at: None, + vote_poll: ContestedDocumentResourceVotePoll { + index_name: "parentNameAndLabel".to_string(), + index_values: vec!["dash".into()], + document_type_name: cfg.existing_document_type_name, + contract_id: data_contract_id, + }, + allow_include_locked_and_abstaining_vote_tally: true, + // TODO test other result types + result_type: ContestedDocumentVotePollDriveQueryResultType::DocumentsAndVoteTally, + }; + + // Then I get an error + let result = if let Err(e) = ContenderWithSerializedDocument::fetch_many(&sdk, query).await { + e + } else { + panic!("asking for non-existing contract should return error.") + }; + + if let dash_sdk::error::Error::DapiClientError(e) = result { + assert!( + e.contains( + "Transport(Status { code: InvalidArgument, message: \"contract not found error" + ), + "we should get contract not found error" + ); + } else { + panic!("expected 'contract not found' transport error"); + }; +} + +/// Ensure we can successfully query for existing index values. +/// +/// ## Preconditions +/// +/// 1. There must be at least one contender for name "dash" and value "dada". +#[tokio::test(flavor = "multi_thread", worker_threads = 1)] +async fn contested_resource_vote_states_ok() { + setup_logs(); + + let cfg = Config::new(); + let sdk = cfg.setup_api("contested_resource_vote_states_ok").await; + // Given some existing data contract ID and existing label + let data_contract_id = cfg.existing_data_contract_id; + // TODO: Lookup the label instead of hardcoding it + let label = Value::Text(convert_to_homograph_safe_chars("dada")); + let document_type_name = "domain".into(); + + // When I query for vote poll states with existing index values + let query = ContestedDocumentVotePollDriveQuery { + limit: None, + offset: None, + start_at: None, + vote_poll: ContestedDocumentResourceVotePoll { + index_name: "parentNameAndLabel".to_string(), + index_values: vec![Value::Text("dash".into()), label], + document_type_name, + contract_id: data_contract_id, + }, + allow_include_locked_and_abstaining_vote_tally: true, + result_type: ContestedDocumentVotePollDriveQueryResultType::DocumentsAndVoteTally, + }; + + let contenders = ContenderWithSerializedDocument::fetch_many(&sdk, query) + .await + .expect("fetch many contenders"); + tracing::debug!(contenders=?contenders, "Contenders"); + // Then I get contenders + assert!( + !contenders.contenders.is_empty(), + "contenders expected for this query" + ); +} + +/// Ensure we can limit the number of returned contenders. +/// +/// ## Preconditions +/// +/// 1. There must be at least 3 condenders for name "dash" and value "dada". +/// +#[tokio::test(flavor = "multi_thread", worker_threads = 1)] +async fn contested_resource_vote_states_with_limit() { + setup_logs(); + + let cfg = Config::new(); + let sdk = cfg + .setup_api("contested_resource_vote_states_with_limit") + .await; + // Given more contenders for some `label` than the limit + let data_contract_id = cfg.existing_data_contract_id; + let limit: u16 = 2; + let label = Value::Text("dada".into()); + // ensure we have enough contenders + let query_all = ContestedDocumentVotePollDriveQuery { + limit: None, + offset: None, + start_at: None, + vote_poll: ContestedDocumentResourceVotePoll { + index_name: "parentNameAndLabel".to_string(), + index_values: vec![Value::Text("dash".into()), label.clone()], + document_type_name: cfg.existing_document_type_name, + contract_id: data_contract_id, + }, + allow_include_locked_and_abstaining_vote_tally: true, + result_type: ContestedDocumentVotePollDriveQueryResultType::DocumentsAndVoteTally, + }; + + let all_contenders = ContenderWithSerializedDocument::fetch_many(&sdk, query_all.clone()) + .await + .expect("fetch many contenders") + .contenders + .len(); + assert!( + all_contenders > limit as usize, + "we need more than {} contenders for this test", + limit + ); + + // When I query for vote poll states with a limit + let query = ContestedDocumentVotePollDriveQuery { + limit: Some(limit), + ..query_all + }; + + let contenders = ContenderWithSerializedDocument::fetch_many(&sdk, query) + .await + .expect("fetch many contenders"); + // Then I get no more than the limit of contenders + tracing::debug!(contenders=?contenders, "Contenders"); + + assert_eq!( + contenders.contenders.len(), + limit as usize, + "number of contenders for {:?} should must be at least {}", + label, + limit + ); +} diff --git a/packages/rs-sdk/tests/fetch/contested_resource_voters.rs b/packages/rs-sdk/tests/fetch/contested_resource_voters.rs index 9e507fe3a24..20ef80e0aa9 100644 --- a/packages/rs-sdk/tests/fetch/contested_resource_voters.rs +++ b/packages/rs-sdk/tests/fetch/contested_resource_voters.rs @@ -1,11 +1,13 @@ //! Test GetContestedResourceVotersForIdentityRequest -use dash_sdk::platform::FetchMany; +use dash_sdk::platform::{Fetch, FetchMany}; +use dpp::{identifier::Identifier, identity::Identity, platform_value::Value}; use drive::query::vote_poll_contestant_votes_query::ContestedDocumentVotePollVotesDriveQuery; use drive_proof_verifier::types::Voter; use crate::fetch::{common::setup_logs, config::Config}; +/// When we request votes for a non-existing identity, we should get no votes. #[tokio::test(flavor = "multi_thread", worker_threads = 1)] async fn test_contested_resource_voters_for_identity_not_found() { setup_logs(); @@ -16,6 +18,7 @@ async fn test_contested_resource_voters_for_identity_not_found() { .setup_api("test_contested_resource_voters_for_identity_not_found") .await; + let contestant_id = Identifier::new([0xff; 32]); let index_name = "parentNameAndLabel"; let query = ContestedDocumentVotePollVotesDriveQuery { @@ -29,7 +32,7 @@ async fn test_contested_resource_voters_for_identity_not_found() { index_name: index_name.to_string(), index_values: vec!["dash".into()], }, - contestant_id: cfg.existing_identity_id, + contestant_id, }; let rss = Voter::fetch_many(&sdk, query) @@ -38,3 +41,59 @@ async fn test_contested_resource_voters_for_identity_not_found() { assert!(rss.0.is_empty()); } + +/// When we request votes for an existing contestant, we should get some votes. +/// +/// ## Preconditions +/// +/// 1. Votes exist for the given contestant. +#[tokio::test(flavor = "multi_thread", worker_threads = 1)] +async fn contested_resource_voters_for_existing_contestant() { + setup_logs(); + + let cfg = Config::new(); + let sdk = cfg + .setup_api("contested_resource_voters_for_existing_contestant") + .await; + + // Given a known contestant ID that has votes + // TODO: lookup contestant ID + let contestant_id = Identifier::from_string( + "D63rWKSagCgEE53XPkouP3swN9n87jHvjesFEZEh1cLr", + dpp::platform_value::string_encoding::Encoding::Base58, + ) + .expect("valid contestant ID"); + + let index_name = "parentNameAndLabel"; + let index_value = Value::Text("dada".to_string()); + // double-check that the contestant identity exist + let _contestant_identity = Identity::fetch(&sdk, contestant_id) + .await + .expect("fetch identity") + .expect("contestant identity must exist"); + + // When I query for votes given to this contestant + let query = ContestedDocumentVotePollVotesDriveQuery { + limit: None, + offset: None, + order_ascending: true, + start_at: None, + vote_poll: dpp::voting::vote_polls::contested_document_resource_vote_poll::ContestedDocumentResourceVotePoll { + contract_id: cfg.existing_data_contract_id, + document_type_name: cfg.existing_document_type_name, + index_name: index_name.to_string(), + index_values: vec!["dash".into(), index_value], + }, + contestant_id, + }; + + let rss = Voter::fetch_many(&sdk, query) + .await + .expect("fetch contested resources"); + + // We expect to find votes for the known contestant + assert!( + !rss.0.is_empty(), + "Expected to find votes for the existing contestant" + ); +} diff --git a/packages/rs-sdk/tests/fetch/prefunded_specialized_balance.rs b/packages/rs-sdk/tests/fetch/prefunded_specialized_balance.rs index 8ab44ccd40e..88d016783db 100644 --- a/packages/rs-sdk/tests/fetch/prefunded_specialized_balance.rs +++ b/packages/rs-sdk/tests/fetch/prefunded_specialized_balance.rs @@ -1,8 +1,9 @@ //! Test GetPrefundedSpecializedBalanceRequest use crate::fetch::{common::setup_logs, config::Config}; -use dash_sdk::platform::Fetch; -use dpp::identifier::Identifier; +use dash_sdk::platform::{Fetch, FetchMany}; +use dpp::{identifier::Identifier, voting::vote_polls::VotePoll}; +use drive::query::VotePollsByEndDateDriveQuery; use drive_proof_verifier::types::PrefundedSpecializedBalance; #[tokio::test(flavor = "multi_thread", worker_threads = 1)] @@ -23,3 +24,52 @@ async fn test_prefunded_specialized_balance_not_found() { assert!(rss.is_none()); } + +#[tokio::test(flavor = "multi_thread", worker_threads = 1)] +async fn test_prefunded_specialized_balance_ok() { + setup_logs(); + + let cfg = Config::new(); + + let sdk = cfg.setup_api("test_prefunded_specialized_balance_ok").await; + + // Given some vote poll + let query = VotePollsByEndDateDriveQuery { + limit: None, + offset: None, + order_ascending: true, + start_time: None, + end_time: None, + }; + + let polls = VotePoll::fetch_many(&sdk, query) + .await + .expect("fetch vote polls"); + tracing::debug!("vote polls retrieved: {:?}", polls); + + let poll = polls + .0 + .first_key_value() + .expect("need at least one vote poll timestamp") + .1 + .first() + .expect("need at least one vote poll"); + + // Vote poll specialized balance ID + let balance_id = poll + .specialized_balance_id() + .expect("vote poll specialized balance ID") + .expect("must have specialized balance ID"); + + let balance = PrefundedSpecializedBalance::fetch(&sdk, balance_id) + .await + .expect("fetch prefunded specialized balance") + .expect("prefunded specialized balance expected for this query"); + + tracing::debug!(balance=?balance, "Prefunded specialized balance"); + + assert!( + balance.to_credits() > 0, + "prefunded specialized balance expected for this query" + ); +} From 8e5665969911412a4ea362becf7cacb9e4a42fb5 Mon Sep 17 00:00:00 2001 From: Lukasz Klimek <842586+lklimek@users.noreply.github.com> Date: Tue, 18 Jun 2024 17:30:05 +0200 Subject: [PATCH 04/55] chore: build fixes after merge --- .../src/from_request.rs | 31 ++++++++++++++----- .../rs-sdk/tests/fetch/contested_resource.rs | 16 +++++----- 2 files changed, 30 insertions(+), 17 deletions(-) diff --git a/packages/rs-drive-proof-verifier/src/from_request.rs b/packages/rs-drive-proof-verifier/src/from_request.rs index 0eee6607bb7..ff2a74de36c 100644 --- a/packages/rs-drive-proof-verifier/src/from_request.rs +++ b/packages/rs-drive-proof-verifier/src/from_request.rs @@ -300,7 +300,16 @@ impl TryFromRequest for VotePollsByDocumentTypeQue index_name: req.index_name.clone(), start_at_value: req .start_at_value_info - .map(|i| (i.start_value, i.start_value_included)), + .map(|i| { + let (value, _): (Value, _) = + bincode::decode_from_slice(&i.start_value, BINCODE_CONFIG).map_err( + |e| Error::RequestError { + error: format!("cannot decode start value: {}", e), + }, + )?; + Ok::<_, Error>((value, i.start_value_included)) + }) + .transpose()?, start_index_values: bincode_decode_values(req.start_index_values.iter())?, end_index_values: bincode_decode_values(req.end_index_values.iter())?, limit: req.count.map(|v| v as u16), @@ -320,14 +329,20 @@ impl TryFromRequest for VotePollsByDocumentTypeQue start_index_values: bincode_encode_values(&self.start_index_values)?, index_name: self.index_name.clone(), order_ascending: self.order_ascending, - start_at_value_info: self.start_at_value.as_ref().map( - |(start_value, start_value_included)| { - get_contested_resources_request_v0::StartAtValueInfo { - start_value: start_value.clone(), + start_at_value_info: self + .start_at_value + .as_ref() + .map(|(start_value, start_value_included)| { + Ok::<_, Error>(get_contested_resources_request_v0::StartAtValueInfo { + start_value: bincode::encode_to_vec(start_value, BINCODE_CONFIG).map_err( + |e| Error::RequestError { + error: format!("cannot encode start value: {}", e), + }, + )?, start_value_included: *start_value_included, - } - }, - ), + }) + }) + .transpose()?, } .into()) } diff --git a/packages/rs-sdk/tests/fetch/contested_resource.rs b/packages/rs-sdk/tests/fetch/contested_resource.rs index 19690d648c4..a55fdc93551 100644 --- a/packages/rs-sdk/tests/fetch/contested_resource.rs +++ b/packages/rs-sdk/tests/fetch/contested_resource.rs @@ -84,12 +84,11 @@ async fn contested_resources_paginate() { if i != 2 { continue; } - let start_vec = start - .encode_to_vec(sdk.version()) - .expect("encode current value"); + + let ContestedResource::Value(start_value) = start.clone(); let query = VotePollsByDocumentTypeQuery { - start_at_value: Some((start_vec, false)), + start_at_value: Some((start_value, false)), ..query_all.clone() }; @@ -172,13 +171,12 @@ async fn contested_resources_limit() { LIMIT }; assert_eq!(length, expected as usize); - - let ContestedResource::Value(last) = rss.0.last().expect("last contested resource"); - let last_value = dpp::bincode::encode_to_vec(last, dpp::bincode::config::standard()) - .expect("encode last value"); - start_at_value = Some((last_value, false)); tracing::debug!(contested_resources=?rss, i, "Contested resources"); + let ContestedResource::Value(last) = + rss.0.into_iter().last().expect("last contested resource"); + start_at_value = Some((last, false)); + i += length as u16; } From 4a7e2dd88e07c393d2bb69ac61aa6c6d0dd4dcc7 Mon Sep 17 00:00:00 2001 From: Lukasz Klimek <842586+lklimek@users.noreply.github.com> Date: Wed, 19 Jun 2024 10:15:41 +0200 Subject: [PATCH 05/55] test(sdk): contested_resources_paginate green --- packages/rs-sdk/tests/fetch/contested_resource.rs | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/packages/rs-sdk/tests/fetch/contested_resource.rs b/packages/rs-sdk/tests/fetch/contested_resource.rs index a55fdc93551..6f1a7f738e7 100644 --- a/packages/rs-sdk/tests/fetch/contested_resource.rs +++ b/packages/rs-sdk/tests/fetch/contested_resource.rs @@ -78,13 +78,7 @@ async fn contested_resources_paginate() { tracing::debug!(contested_resources=?all, "All contested resources"); // when I set start_at_value to some value, - - // for key,val in all for (i, start) in all.0.iter().enumerate() { - if i != 2 { - continue; - } - let ContestedResource::Value(start_value) = start.clone(); let query = VotePollsByDocumentTypeQuery { @@ -96,10 +90,9 @@ async fn contested_resources_paginate() { .await .expect("fetch contested resources"); tracing::debug!(?start, contested_resources=?rss, "Contested resources"); - assert!(!rss.0.is_empty()); for (j, fetched) in rss.0.into_iter().enumerate() { - let all_index = i + j; // we fetch exclusive + let all_index = i + j + 1; // we fetch exclusive assert_eq!( fetched, From 17a41f7099092fca509d54ba58dde76adca9973b Mon Sep 17 00:00:00 2001 From: Lukasz Klimek <842586+lklimek@users.noreply.github.com> Date: Wed, 19 Jun 2024 13:25:00 +0200 Subject: [PATCH 06/55] refactor(sdk): refactor contested_resource tests --- .../rs-sdk/tests/fetch/contested_resource.rs | 165 ++++++++++++++---- 1 file changed, 133 insertions(+), 32 deletions(-) diff --git a/packages/rs-sdk/tests/fetch/contested_resource.rs b/packages/rs-sdk/tests/fetch/contested_resource.rs index 6f1a7f738e7..be1919190d8 100644 --- a/packages/rs-sdk/tests/fetch/contested_resource.rs +++ b/packages/rs-sdk/tests/fetch/contested_resource.rs @@ -1,19 +1,32 @@ //! Tests of ContestedResource object use crate::fetch::{common::setup_logs, config::Config}; use dash_sdk::platform::FetchMany; -use dpp::platform_value::Value; -use drive::query::vote_polls_by_document_type_query::VotePollsByDocumentTypeQuery; +use dpp::{ + platform_value::Value, + voting::{ + contender_structs::ContenderWithSerializedDocument, + vote_polls::contested_document_resource_vote_poll::ContestedDocumentResourceVotePoll, + }, +}; +use drive::query::{ + vote_poll_vote_state_query::{ + ContestedDocumentVotePollDriveQuery, ContestedDocumentVotePollDriveQueryResultType, + }, + vote_polls_by_document_type_query::VotePollsByDocumentTypeQuery, +}; use drive_proof_verifier::types::ContestedResource; +pub(crate) const INDEX_VALUE: &str = "dada"; + /// Test that we can fetch contested resources /// /// ## Preconditions /// -/// 1. At least one contested resource exists +/// 1. At least one contested resource (DPNS name) exists #[tokio::test(flavor = "multi_thread", worker_threads = 1)] #[cfg_attr( - feature = "network-testing1", - ignore = "requires a DPNS name to be registered" + feature = "network-testing", + ignore = "requires manual DPNS names setup for masternode voting tests; see fn check_mn_voting_prerequisities()" )] async fn test_contested_resources_ok() { setup_logs(); @@ -21,6 +34,9 @@ async fn test_contested_resources_ok() { let cfg = Config::new(); let sdk = cfg.setup_api("test_contested_resources_ok").await; + check_mn_voting_prerequisities(&sdk, &cfg) + .await + .expect("prerequisities"); let index_name = "parentNameAndLabel"; @@ -44,20 +60,25 @@ async fn test_contested_resources_ok() { #[tokio::test(flavor = "multi_thread", worker_threads = 1)] #[cfg_attr( - feature = "network-testing1", - ignore = "requires a DPNS name to be registered" + feature = "network-testing", + ignore = "requires manual DPNS names setup for masternode voting tests; see fn check_mn_voting_prerequisities()" )] -/// Test pagination + +/// Test [ContestedResource] start index (`start_at_value`) /// /// ## Preconditions /// -/// 1. Multiple contested resources exists -async fn contested_resources_paginate() { +/// 1. At least 2 contested resources (eg. different DPNS names) exist +async fn contested_resources_start_at_value() { setup_logs(); let cfg = Config::new(); - let sdk = cfg.setup_api("contested_resources_paginate").await; + let sdk = cfg.setup_api("contested_resources_start_at_value").await; + check_mn_voting_prerequisities(&sdk, &cfg) + .await + .expect("prerequisities"); + // Given all contested resources sorted ascending let index_name = "parentNameAndLabel"; @@ -68,7 +89,7 @@ async fn contested_resources_paginate() { start_at_value: None, start_index_values: vec![Value::Text("dash".into())], end_index_values: vec![], - limit: None, + limit: Some(50), order_ascending: true, }; @@ -77,49 +98,58 @@ async fn contested_resources_paginate() { .expect("fetch contested resources"); tracing::debug!(contested_resources=?all, "All contested resources"); - // when I set start_at_value to some value, - for (i, start) in all.0.iter().enumerate() { - let ContestedResource::Value(start_value) = start.clone(); + for inclusive in [true, false] { + // when I set start_at_value to some value, + for (i, start) in all.0.iter().enumerate() { + let ContestedResource::Value(start_value) = start.clone(); - let query = VotePollsByDocumentTypeQuery { - start_at_value: Some((start_value, false)), - ..query_all.clone() - }; + let query = VotePollsByDocumentTypeQuery { + start_at_value: Some((start_value, inclusive)), + ..query_all.clone() + }; - let rss = ContestedResource::fetch_many(&sdk, query) - .await - .expect("fetch contested resources"); - tracing::debug!(?start, contested_resources=?rss, "Contested resources"); + let rss = ContestedResource::fetch_many(&sdk, query) + .await + .expect("fetch contested resources"); + tracing::debug!(?start, contested_resources=?rss, "Contested resources"); - for (j, fetched) in rss.0.into_iter().enumerate() { - let all_index = i + j + 1; // we fetch exclusive + for (j, fetched) in rss.0.into_iter().enumerate() { + let all_index = if inclusive { i + j } else { i + j + 1 }; - assert_eq!( + assert_eq!( fetched, (all.0[all_index]), - "when starting with {:?}, fetched element {} ({:?}) must equal all element {} ({:?})", + "when starting with {:?} with inclusive {}, fetched element {} ({:?}) must equal all element {} ({:?})", start, + inclusive, j, fetched, all_index, all.0[all_index] ); + } } } } +/// Test that we can fetch contested resources with a limit +/// +/// ## Preconditions +/// +/// 1. At least 3 contested resources (eg. different DPNS names) exist #[tokio::test(flavor = "multi_thread", worker_threads = 1)] #[cfg_attr( - feature = "network-testing1", - ignore = "requires at least 3 DPNS name contests" + feature = "network-testing", + ignore = "requires manual DPNS names setup for masternode voting tests; see fn check_mn_voting_prerequisities()" )] - async fn contested_resources_limit() { setup_logs(); let cfg = Config::new(); - let sdk = cfg.setup_api("contested_resources_limit").await; + check_mn_voting_prerequisities(&sdk, &cfg) + .await + .expect("prerequisities"); // Given index with more than 2 contested resources const LIMIT: u16 = 2; @@ -179,11 +209,14 @@ async fn contested_resources_limit() { #[tokio::test(flavor = "multi_thread", worker_threads = 1)] /// Empty string in start_index_values should not cause an error +/// +/// ## Preconditions +/// +/// None async fn test_contested_resources_idx_value_empty_string() { setup_logs(); let cfg = Config::new(); - let sdk = cfg .setup_api("test_contested_resources_idx_value_empty_string") .await; @@ -210,3 +243,71 @@ async fn test_contested_resources_idx_value_empty_string() { // Then I don't get an error assert!(result.is_ok(), "empty index value shall not cause an error"); } + +/// Ensure prerequsities for masternode voting tests are met +pub async fn check_mn_voting_prerequisities( + sdk: &dash_sdk::Sdk, + cfg: &Config, +) -> Result<(), Vec> { + let mut errors = Vec::new(); + + let index_name = "parentNameAndLabel".to_string(); + + let query_contested_resources = VotePollsByDocumentTypeQuery { + contract_id: cfg.existing_data_contract_id, + document_type_name: cfg.existing_document_type_name.clone(), + index_name: index_name.to_string(), + start_at_value: None, + start_index_values: vec![Value::Text("dash".into())], + end_index_values: vec![], + limit: None, + order_ascending: true, + }; + + // Check if we have enough contested resources; this implies that we have at least 1 vote poll + let contested_resources = ContestedResource::fetch_many(sdk, query_contested_resources) + .await + .expect("fetch contested resources"); + if contested_resources.0.len() < 3 { + errors.push(format!( + "Please create at least 3 different DPNS names for masternode voting tests, found {}", + contested_resources.0.len() + )); + } + + // ensure we have enough contenders + let query_all = ContestedDocumentVotePollDriveQuery { + limit: None, + offset: None, + start_at: None, + vote_poll: ContestedDocumentResourceVotePoll { + index_name: "parentNameAndLabel".to_string(), + index_values: vec![ + Value::Text("dash".into()), + Value::Text(INDEX_VALUE.to_string()), + ], + document_type_name: cfg.existing_document_type_name.clone(), + contract_id: cfg.existing_data_contract_id, + }, + allow_include_locked_and_abstaining_vote_tally: true, + result_type: ContestedDocumentVotePollDriveQueryResultType::DocumentsAndVoteTally, + }; + + let all_contenders = ContenderWithSerializedDocument::fetch_many(sdk, query_all.clone()) + .await + .expect("fetch many contenders"); + if all_contenders.contenders.len() < 3 { + errors.push(format!( + "Please create 3 identities and create DPNS name `{}` for each of them, found {}", + INDEX_VALUE, + all_contenders.contenders.len() + )); + } + + if errors.is_empty() { + Ok(()) + } else { + tracing::error!(?errors, "Prerequisities for masternode voting tests not met, please configure the network accordingly"); + Err(errors) + } +} From 3c159d9090870470f60918d42591d597d485e9b8 Mon Sep 17 00:00:00 2001 From: Lukasz Klimek <842586+lklimek@users.noreply.github.com> Date: Thu, 20 Jun 2024 10:44:18 +0200 Subject: [PATCH 07/55] test(sdk): vote polls by ts id --- Cargo.lock | 1 + packages/rs-drive-proof-verifier/src/lib.rs | 2 +- packages/rs-sdk/Cargo.toml | 1 + packages/rs-sdk/src/platform.rs | 2 +- packages/rs-sdk/tests/fetch/common.rs | 2 +- .../rs-sdk/tests/fetch/contested_resource.rs | 6 +- .../contested_resource_identity_votes.rs | 12 +- .../fetch/contested_resource_pools_by_ts.rs | 185 +++++++++++++++++- .../fetch/contested_resource_vote_state.rs | 9 +- 9 files changed, 205 insertions(+), 15 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3daafcea7db..9f6c164398b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1312,6 +1312,7 @@ dependencies = [ "async-trait", "base64 0.22.1", "bip37-bloom-filter", + "chrono", "ciborium", "clap 4.5.7", "dapi-grpc", diff --git a/packages/rs-drive-proof-verifier/src/lib.rs b/packages/rs-drive-proof-verifier/src/lib.rs index bee807bda66..bf38d555ef7 100644 --- a/packages/rs-drive-proof-verifier/src/lib.rs +++ b/packages/rs-drive-proof-verifier/src/lib.rs @@ -9,7 +9,7 @@ mod provider; pub mod types; mod verify; pub use error::Error; -pub use proof::FromProof; +pub use proof::{FromProof, Length}; pub use provider::ContextProvider; #[cfg(feature = "mocks")] pub use provider::MockContextProvider; diff --git a/packages/rs-sdk/Cargo.toml b/packages/rs-sdk/Cargo.toml index afd978dc435..fd1a5498a6e 100644 --- a/packages/rs-sdk/Cargo.toml +++ b/packages/rs-sdk/Cargo.toml @@ -51,6 +51,7 @@ data-contracts = { path = "../data-contracts" } tokio-test = { version = "0.4.4" } clap = { version = "4.5.4", features = ["derive"] } sanitize-filename = { version = "0.5.0" } +chrono = { version = "0.4.38" } [features] default = ["mocks", "offline-testing"] diff --git a/packages/rs-sdk/src/platform.rs b/packages/rs-sdk/src/platform.rs index 0718da718d3..54667e92c2c 100644 --- a/packages/rs-sdk/src/platform.rs +++ b/packages/rs-sdk/src/platform.rs @@ -30,5 +30,5 @@ pub use { document_query::DocumentQuery, fetch::Fetch, fetch_many::FetchMany, - query::{LimitQuery, Query, DEFAULT_EPOCH_QUERY_LIMIT}, + query::{LimitQuery, Query, QueryStartInfo, DEFAULT_EPOCH_QUERY_LIMIT}, }; diff --git a/packages/rs-sdk/tests/fetch/common.rs b/packages/rs-sdk/tests/fetch/common.rs index e7847db9f22..12bfeb77617 100644 --- a/packages/rs-sdk/tests/fetch/common.rs +++ b/packages/rs-sdk/tests/fetch/common.rs @@ -72,7 +72,7 @@ pub fn mock_data_contract( pub fn setup_logs() { tracing_subscriber::fmt::fmt() .with_env_filter(tracing_subscriber::EnvFilter::new( - "info,dash_sdk=trace,drive_proof_verifier=trace,main=debug,h2=info", + "info,dash_sdk=trace,dash_sdk::platform::fetch=debug,drive_proof_verifier=debug,main=debug,h2=info", )) .pretty() .with_ansi(true) diff --git a/packages/rs-sdk/tests/fetch/contested_resource.rs b/packages/rs-sdk/tests/fetch/contested_resource.rs index be1919190d8..8d4d275546a 100644 --- a/packages/rs-sdk/tests/fetch/contested_resource.rs +++ b/packages/rs-sdk/tests/fetch/contested_resource.rs @@ -1,4 +1,5 @@ //! Tests of ContestedResource object + use crate::fetch::{common::setup_logs, config::Config}; use dash_sdk::platform::FetchMany; use dpp::{ @@ -63,7 +64,6 @@ async fn test_contested_resources_ok() { feature = "network-testing", ignore = "requires manual DPNS names setup for masternode voting tests; see fn check_mn_voting_prerequisities()" )] - /// Test [ContestedResource] start index (`start_at_value`) /// /// ## Preconditions @@ -207,7 +207,6 @@ async fn contested_resources_limit() { } #[tokio::test(flavor = "multi_thread", worker_threads = 1)] - /// Empty string in start_index_values should not cause an error /// /// ## Preconditions @@ -264,7 +263,8 @@ pub async fn check_mn_voting_prerequisities( order_ascending: true, }; - // Check if we have enough contested resources; this implies that we have at least 1 vote poll + // Check if we have enough contested resources; this implies that we have + // at least 1 vote poll for each of them let contested_resources = ContestedResource::fetch_many(sdk, query_contested_resources) .await .expect("fetch contested resources"); diff --git a/packages/rs-sdk/tests/fetch/contested_resource_identity_votes.rs b/packages/rs-sdk/tests/fetch/contested_resource_identity_votes.rs index 84c754b8340..0902e88d774 100644 --- a/packages/rs-sdk/tests/fetch/contested_resource_identity_votes.rs +++ b/packages/rs-sdk/tests/fetch/contested_resource_identity_votes.rs @@ -37,6 +37,14 @@ async fn contested_resource_identity_votes_not_found() { } /// When we request votes for an existing identity, we should get some votes. +/// +/// ## Preconditions +/// +/// 1. At least one vote exists for the given masternode identity (protx hash). +#[cfg_attr( + feature = "network-testing", + ignore = "requires manual DPNS names setup for masternode voting tests; see fn check_mn_voting_prerequisities()" +)] #[tokio::test(flavor = "multi_thread", worker_threads = 1)] async fn contested_resource_identity_votes_ok() { setup_logs(); @@ -45,7 +53,9 @@ async fn contested_resource_identity_votes_ok() { let sdk = cfg.setup_api("contested_resource_identity_votes_ok").await; // Given some existing identity ID, that is, proTxHash of some Validator - // TODO: Fetch proTxHash from the network + + // TODO: Fetch proTxHash from the network instead of hardcoding; it's not so trivial as it must support our mocking + // mechanisms let protx_hex = "7624E7D0D7C8837D4D02A19700F4116091A8AD145352420193DE8828F6D00BBF"; let protx = ProTxHash::from_hex(protx_hex).expect("ProTxHash from hex"); diff --git a/packages/rs-sdk/tests/fetch/contested_resource_pools_by_ts.rs b/packages/rs-sdk/tests/fetch/contested_resource_pools_by_ts.rs index 805763d9117..8a8c234580c 100644 --- a/packages/rs-sdk/tests/fetch/contested_resource_pools_by_ts.rs +++ b/packages/rs-sdk/tests/fetch/contested_resource_pools_by_ts.rs @@ -1,22 +1,30 @@ //! Test VotePollsByEndDateDriveQuery +use crate::fetch::{common::setup_logs, config::Config}; use dash_sdk::platform::FetchMany; -use dpp::voting::vote_polls::VotePoll; +use dpp::{identity::TimestampMillis, voting::vote_polls::VotePoll}; use drive::query::VotePollsByEndDateDriveQuery; +use std::collections::BTreeMap; -use crate::fetch::{common::setup_logs, config::Config}; - -#[tokio::test(flavor = "multi_thread", worker_threads = 1)] +/// Test that we can fetch vote polls +/// +/// ## Preconditions +/// +/// 1. At least one vote poll exists #[cfg_attr( feature = "network-testing", - ignore = "requires a DPNS name to be registered" + ignore = "requires manual DPNS names setup for masternode voting tests; see fn check_mn_voting_prerequisities()" )] -async fn test_vote_polls_by_ts_ok() { +#[tokio::test(flavor = "multi_thread", worker_threads = 1)] +async fn vote_polls_by_ts_ok() { setup_logs(); let cfg = Config::new(); - let sdk = cfg.setup_api("test_vote_polls_by_ts_ok").await; + let sdk = cfg.setup_api("vote_polls_by_ts_ok").await; + super::contested_resource::check_mn_voting_prerequisities(&sdk, &cfg) + .await + .expect("prerequisities"); let query = VotePollsByEndDateDriveQuery { limit: None, @@ -32,3 +40,166 @@ async fn test_vote_polls_by_ts_ok() { tracing::info!("vote polls retrieved: {:?}", rss); assert!(!rss.0.is_empty()); } + +/// Test that we can fetch vote polls ordered by timestamp, ascending and descending +/// +/// ## Preconditions +/// +/// 1. At least 2 vote polls exist +#[tokio::test(flavor = "multi_thread", worker_threads = 1)] +#[cfg_attr( + feature = "network-testing", + ignore = "requires manual DPNS names setup for masternode voting tests; see fn check_mn_voting_prerequisities()" +)] +async fn vote_polls_by_ts_order() { + setup_logs(); + + let cfg = Config::new(); + let sdk = cfg.setup_api("vote_polls_by_ts_order").await; + super::contested_resource::check_mn_voting_prerequisities(&sdk, &cfg) + .await + .expect("prerequisities"); + + let base_query = VotePollsByEndDateDriveQuery { + limit: None, + offset: None, + order_ascending: true, + start_time: None, + end_time: None, + }; + + for order_ascending in [true, false] { + let query = VotePollsByEndDateDriveQuery { + order_ascending, + ..base_query.clone() + }; + + let rss = VotePoll::fetch_many(&sdk, query) + .await + .expect("fetch contested resources"); + tracing::debug!(order_ascending, ?rss, "vote polls retrieved"); + assert!(!rss.0.is_empty()); + let enumerated = rss.0.iter().enumerate().collect::>(); + for (i, (ts, _)) in &enumerated { + if *i > 0 { + let (prev_ts, _) = &enumerated[&(i - 1)]; + if order_ascending { + assert!( + ts >= prev_ts, + "ascending order: item {} ({}) must be >= than item {} ({})", + ts, + i, + prev_ts, + i - 1 + ); + } else { + assert!( + ts <= prev_ts, + "descending order: item {} ({}) must be >= than item {} ({})", + ts, + i, + prev_ts, + i - 1 + ); + } + } + } + } +} + +/// Test that we can fetch vote polls with a limit +/// +/// ## Preconditions +/// +/// 1. At least 3 vote poll exists +#[tokio::test(flavor = "multi_thread", worker_threads = 1)] +#[cfg_attr( + feature = "network-testing", + ignore = "requires manual DPNS names setup for masternode voting tests; see fn check_mn_voting_prerequisities()" +)] +async fn vote_polls_by_ts_limit() { + setup_logs(); + + let cfg = Config::new(); + let sdk = cfg.setup_api("vote_polls_by_ts_limit").await; + super::contested_resource::check_mn_voting_prerequisities(&sdk, &cfg) + .await + .expect("prerequisities"); + + // Given index with more than 2 contested resources + const LIMIT: usize = 2; + const LIMIT_ALL: usize = 100; + + let test_start_time: TimestampMillis = chrono::Utc::now().timestamp_millis() as u64; + + let query_all = VotePollsByEndDateDriveQuery { + limit: Some(LIMIT_ALL as u16), + offset: None, + order_ascending: true, + start_time: None, + end_time: Some((test_start_time, true)), + }; + + let all = VotePoll::fetch_many(&sdk, query_all.clone()) + .await + .expect("fetch vote polls"); + // this counts timestamps, not vote polls themselves + let count_all_timestamps = all.0.len(); + assert_ne!(count_all_timestamps, 0, "at least one vote poll expected"); + + let all_values = all.0.into_iter().collect::>(); + + tracing::debug!(count_all_timestamps, "Count all"); + // When we query for 2 contested values at a time, we get all of them + let mut checked_count: usize = 0; + let mut start_time = None; + + for inclusive in [true, false] { + while checked_count < LIMIT_ALL { + let query = VotePollsByEndDateDriveQuery { + limit: Some(LIMIT as u16), + start_time, + ..query_all.clone() + }; + + let rss = VotePoll::fetch_many(&sdk, query) + .await + .expect("fetch vote polls"); + + let Some(last) = rss.0.keys().last().copied() else { + // no more vote polls + break; + }; + + tracing::debug!(polls=?rss, inclusive, ?start_time, checked_count, "Vote pools"); + let length = rss.0.len(); + + for (j, current) in rss.0.iter().enumerate() { + let all_idx = if inclusive && (j + checked_count > 0) { + j + checked_count - 1 + } else { + j + checked_count + }; + let expected = &all_values[all_idx]; + assert_eq!(*current.0, expected.0, "timestamp should match"); + assert_eq!(current.1, &expected.1, "vote polls should match"); + } + + let expected = if checked_count + LIMIT > count_all_timestamps { + count_all_timestamps - checked_count + } else { + LIMIT + }; + assert_eq!(length, expected as usize); + tracing::debug!(polls=?rss, checked_count, "Vote polls"); + + start_time = Some((last, inclusive)); + checked_count += if inclusive { length - 1 } else { length }; + } + } + assert_eq!( + checked_count, + count_all_timestamps * 2, + "all vote polls should be checked twice (inclusive and exclusive)" + ); +} diff --git a/packages/rs-sdk/tests/fetch/contested_resource_vote_state.rs b/packages/rs-sdk/tests/fetch/contested_resource_vote_state.rs index 44b97c40aba..00d4e9921fd 100644 --- a/packages/rs-sdk/tests/fetch/contested_resource_vote_state.rs +++ b/packages/rs-sdk/tests/fetch/contested_resource_vote_state.rs @@ -1,5 +1,7 @@ //! Tests for SDK requests that return one or more [Contender] objects. -use crate::fetch::{common::setup_logs, config::Config}; +use crate::fetch::{ + common::setup_logs, config::Config, contested_resource::check_mn_voting_prerequisities, +}; use dash_sdk::platform::FetchMany; use dpp::{ identifier::Identifier, @@ -165,11 +167,16 @@ async fn contested_resource_vote_states_with_limit() { let sdk = cfg .setup_api("contested_resource_vote_states_with_limit") .await; + check_mn_voting_prerequisities(&sdk, &cfg) + .await + .expect("prerequisites not met"); + // Given more contenders for some `label` than the limit let data_contract_id = cfg.existing_data_contract_id; let limit: u16 = 2; let label = Value::Text("dada".into()); // ensure we have enough contenders + let query_all = ContestedDocumentVotePollDriveQuery { limit: None, offset: None, From 6bd15b4e04ed162aa28df880f733b56166bf6f98 Mon Sep 17 00:00:00 2001 From: Lukasz Klimek <842586+lklimek@users.noreply.github.com> Date: Thu, 20 Jun 2024 10:44:58 +0200 Subject: [PATCH 08/55] refactor(sdk): fix typo in test file name --- ...esource_pools_by_ts.rs => contested_resource_polls_by_ts.rs} | 0 packages/rs-sdk/tests/fetch/mod.rs | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename packages/rs-sdk/tests/fetch/{contested_resource_pools_by_ts.rs => contested_resource_polls_by_ts.rs} (100%) diff --git a/packages/rs-sdk/tests/fetch/contested_resource_pools_by_ts.rs b/packages/rs-sdk/tests/fetch/contested_resource_polls_by_ts.rs similarity index 100% rename from packages/rs-sdk/tests/fetch/contested_resource_pools_by_ts.rs rename to packages/rs-sdk/tests/fetch/contested_resource_polls_by_ts.rs diff --git a/packages/rs-sdk/tests/fetch/mod.rs b/packages/rs-sdk/tests/fetch/mod.rs index bdcb4073d6c..76e6c84c69c 100644 --- a/packages/rs-sdk/tests/fetch/mod.rs +++ b/packages/rs-sdk/tests/fetch/mod.rs @@ -11,7 +11,7 @@ mod common; mod config; mod contested_resource; mod contested_resource_identity_votes; -mod contested_resource_pools_by_ts; +mod contested_resource_polls_by_ts; mod contested_resource_vote_state; mod contested_resource_voters; mod data_contract; From 89a907541fd2839402816763cc1753d92a784414 Mon Sep 17 00:00:00 2001 From: Lukasz Klimek <842586+lklimek@users.noreply.github.com> Date: Thu, 20 Jun 2024 11:21:39 +0200 Subject: [PATCH 09/55] feat(sdk): impl LimitQuery for some mn voting queries --- packages/rs-drive-proof-verifier/src/types.rs | 10 +++ packages/rs-sdk/src/core_client.rs | 26 +++++- packages/rs-sdk/src/platform/query.rs | 88 +++++++++++++++++++ 3 files changed, 123 insertions(+), 1 deletion(-) diff --git a/packages/rs-drive-proof-verifier/src/types.rs b/packages/rs-drive-proof-verifier/src/types.rs index 70c5f2b8d9e..5955c040de9 100644 --- a/packages/rs-drive-proof-verifier/src/types.rs +++ b/packages/rs-drive-proof-verifier/src/types.rs @@ -179,6 +179,16 @@ impl ContestedResource { } } +impl TryInto for ContestedResource { + type Error = crate::Error; + + fn try_into(self) -> Result { + match self { + ContestedResource::Value(value) => Ok(value), + } + } +} + #[cfg(feature = "mocks")] impl PlatformVersionEncode for ContestedResource { fn platform_encode( diff --git a/packages/rs-sdk/src/core_client.rs b/packages/rs-sdk/src/core_client.rs index acb2372077d..656fff61b1c 100644 --- a/packages/rs-sdk/src/core_client.rs +++ b/packages/rs-sdk/src/core_client.rs @@ -5,8 +5,11 @@ use dashcore_rpc::{ dashcore::{hashes::Hash, Amount, QuorumHash}, - dashcore_rpc_json as json, Auth, Client, RpcApi, + dashcore_rpc_json as json, + json::{ProTxList, ProTxListType}, + Auth, Client, RpcApi, }; +use dpp::dashcore::ProTxHash; use drive_proof_verifier::error::ContextProviderError; use std::{fmt::Debug, sync::Mutex}; @@ -126,4 +129,25 @@ impl CoreClient { })?; Ok(pubkey) } + + /// Require list of validators from Core. + /// + /// See also [Dash Core documentation](https://docs.dash.org/projects/core/en/stable/docs/api/remote-procedure-calls-evo.html#protx-list) + #[allow(unused)] + pub fn protx_list( + &self, + height: Option, + protx_type: Option, + ) -> Result, Error> { + let core = self.core.lock().expect("Core lock poisoned"); + + let pro_tx_hashes = + core.get_protx_list(protx_type, Some(false), height) + .map(|x| match x { + ProTxList::Hex(hex) => hex, + ProTxList::Info(info) => info.into_iter().map(|v| v.pro_tx_hash).collect(), + })?; + + Ok(pro_tx_hashes) + } } diff --git a/packages/rs-sdk/src/platform/query.rs b/packages/rs-sdk/src/platform/query.rs index bddd9639091..87500822006 100644 --- a/packages/rs-sdk/src/platform/query.rs +++ b/packages/rs-sdk/src/platform/query.rs @@ -3,6 +3,8 @@ //! [Query] trait is used to specify individual objects as well as search criteria for fetching multiple objects from the platform. use dapi_grpc::mock::Mockable; use dapi_grpc::platform::v0::get_contested_resource_identity_votes_request::GetContestedResourceIdentityVotesRequestV0; +use dapi_grpc::platform::v0::get_contested_resource_voters_for_identity_request::GetContestedResourceVotersForIdentityRequestV0; +use dapi_grpc::platform::v0::get_contested_resources_request::GetContestedResourcesRequestV0; use dapi_grpc::platform::v0::{ self as proto, get_identity_keys_request, get_identity_keys_request::GetIdentityKeysRequestV0, AllKeys, GetContestedResourceVoteStateRequest, GetContestedResourceVotersForIdentityRequest, @@ -15,6 +17,7 @@ use dapi_grpc::platform::v0::{ GetVotePollsByEndDateRequest, }; use dashcore_rpc::dashcore::{hashes::Hash, ProTxHash}; +use dpp::version::PlatformVersionError; use dpp::{block::epoch::EpochIndex, prelude::Identifier}; use drive::query::contested_resource_votes_given_by_identity_query::ContestedResourceVotesGivenByIdentityQuery; use drive::query::vote_poll_contestant_votes_query::ContestedDocumentVotePollVotesDriveQuery; @@ -317,6 +320,34 @@ impl Query for VotePollsByDocumentTypeQuery { } } +impl Query for LimitQuery { + fn query(self, prove: bool) -> Result { + use proto::get_contested_resources_request::{ + get_contested_resources_request_v0::StartAtValueInfo, Version, + }; + let query = match self.query.query(prove)?.version { + Some(Version::V0(v0)) => GetContestedResourcesRequestV0 { + start_at_value_info: self.start_info.map(|v| StartAtValueInfo { + start_value: v.start_key, + start_value_included: v.start_included, + }), + ..v0 + } + .into(), + None => { + return Err(Error::Protocol( + PlatformVersionError::UnknownVersionError( + "version not present in request".into(), + ) + .into(), + )) + } + }; + + Ok(query) + } +} + impl Query for ContestedDocumentVotePollDriveQuery { fn query(self, prove: bool) -> Result { if !prove { @@ -330,6 +361,33 @@ impl Query for ContestedDocumentVotePollDr } } +impl Query + for LimitQuery +{ + fn query(self, prove: bool) -> Result { + use proto::get_contested_resource_vote_state_request::get_contested_resource_vote_state_request_v0::StartAtIdentifierInfo; + if !prove { + unimplemented!("queries without proofs are not supported yet"); + } + let result = match self.query.query(prove)?.version { + Some(proto::get_contested_resource_vote_state_request::Version::V0(v0)) => + proto::get_contested_resource_vote_state_request::GetContestedResourceVoteStateRequestV0 { + start_at_identifier_info: self.start_info.map(|v| StartAtIdentifierInfo { + start_identifier: v.start_key, + start_identifier_included: v.start_included, + }), + ..v0 + }.into(), + + None =>return Err(Error::Protocol( + PlatformVersionError::UnknownVersionError("version not present in request".into()).into(), + )), + }; + + Ok(result) + } +} + impl Query for ContestedDocumentVotePollVotesDriveQuery { @@ -345,6 +403,36 @@ impl Query } } +impl Query + for LimitQuery +{ + fn query(self, prove: bool) -> Result { + use proto::get_contested_resource_voters_for_identity_request::{ + get_contested_resource_voters_for_identity_request_v0::StartAtIdentifierInfo, Version, + }; + let query = match self.query.query(prove)?.version { + Some(Version::V0(v0)) => GetContestedResourceVotersForIdentityRequestV0 { + start_at_identifier_info: self.start_info.map(|v| StartAtIdentifierInfo { + start_identifier: v.start_key, + start_identifier_included: v.start_included, + }), + ..v0 + } + .into(), + None => { + return Err(Error::Protocol( + PlatformVersionError::UnknownVersionError( + "version not present in request".into(), + ) + .into(), + )) + } + }; + + Ok(query) + } +} + impl Query for ContestedResourceVotesGivenByIdentityQuery { From 0e8070e8f98273e71a06e2f08dd9445953e91564 Mon Sep 17 00:00:00 2001 From: Lukasz Klimek <842586+lklimek@users.noreply.github.com> Date: Thu, 20 Jun 2024 14:30:29 +0200 Subject: [PATCH 10/55] test(sdk): contested_resource additional tests --- .../rs-sdk/tests/fetch/contested_resource.rs | 359 +++++++++++++----- 1 file changed, 270 insertions(+), 89 deletions(-) diff --git a/packages/rs-sdk/tests/fetch/contested_resource.rs b/packages/rs-sdk/tests/fetch/contested_resource.rs index 8d4d275546a..93a6879e290 100644 --- a/packages/rs-sdk/tests/fetch/contested_resource.rs +++ b/packages/rs-sdk/tests/fetch/contested_resource.rs @@ -1,5 +1,8 @@ //! Tests of ContestedResource object +use core::panic; +use std::{collections::BTreeMap, fmt::Debug}; + use crate::fetch::{common::setup_logs, config::Config}; use dash_sdk::platform::FetchMany; use dpp::{ @@ -81,52 +84,54 @@ async fn contested_resources_start_at_value() { // Given all contested resources sorted ascending let index_name = "parentNameAndLabel"; + for order_ascending in [true, false] { + let query_all = VotePollsByDocumentTypeQuery { + contract_id: cfg.existing_data_contract_id, + document_type_name: cfg.existing_document_type_name.clone(), + index_name: index_name.to_string(), + start_at_value: None, + start_index_values: vec![Value::Text("dash".into())], + end_index_values: vec![], + limit: Some(50), + order_ascending, + }; - let query_all = VotePollsByDocumentTypeQuery { - contract_id: cfg.existing_data_contract_id, - document_type_name: cfg.existing_document_type_name.clone(), - index_name: index_name.to_string(), - start_at_value: None, - start_index_values: vec![Value::Text("dash".into())], - end_index_values: vec![], - limit: Some(50), - order_ascending: true, - }; - - let all = ContestedResource::fetch_many(&sdk, query_all.clone()) - .await - .expect("fetch contested resources"); + let all = ContestedResource::fetch_many(&sdk, query_all.clone()) + .await + .expect("fetch contested resources"); - tracing::debug!(contested_resources=?all, "All contested resources"); - for inclusive in [true, false] { - // when I set start_at_value to some value, - for (i, start) in all.0.iter().enumerate() { - let ContestedResource::Value(start_value) = start.clone(); + tracing::debug!(contested_resources=?all, order_ascending, "All contested resources"); + for inclusive in [true, false] { + // when I set start_at_value to some value, + for (i, start) in all.0.iter().enumerate() { + let ContestedResource::Value(start_value) = start.clone(); - let query = VotePollsByDocumentTypeQuery { - start_at_value: Some((start_value, inclusive)), - ..query_all.clone() - }; + let query = VotePollsByDocumentTypeQuery { + start_at_value: Some((start_value, inclusive)), + ..query_all.clone() + }; - let rss = ContestedResource::fetch_many(&sdk, query) - .await - .expect("fetch contested resources"); - tracing::debug!(?start, contested_resources=?rss, "Contested resources"); + let rss = ContestedResource::fetch_many(&sdk, query) + .await + .expect("fetch contested resources"); + tracing::debug!(?start, contested_resources=?rss, "Contested resources"); - for (j, fetched) in rss.0.into_iter().enumerate() { - let all_index = if inclusive { i + j } else { i + j + 1 }; + for (j, fetched) in rss.0.into_iter().enumerate() { + let all_index = if inclusive { i + j } else { i + j + 1 }; - assert_eq!( + assert_eq!( fetched, (all.0[all_index]), - "when starting with {:?} with inclusive {}, fetched element {} ({:?}) must equal all element {} ({:?})", + "when starting with {:?} order ascending {} with inclusive {}, fetched element {} ({:?}) must equal all element {} ({:?})", start, + order_ascending, inclusive, j, fetched, all_index, all.0[all_index] ); + } } } } @@ -137,6 +142,7 @@ async fn contested_resources_start_at_value() { /// ## Preconditions /// /// 1. At least 3 contested resources (eg. different DPNS names) exist +// TODO: fails due to PLAN-656, not tested enough so it can be faulty #[tokio::test(flavor = "multi_thread", worker_threads = 1)] #[cfg_attr( feature = "network-testing", @@ -151,96 +157,271 @@ async fn contested_resources_limit() { .await .expect("prerequisities"); - // Given index with more than 2 contested resources const LIMIT: u16 = 2; const LIMIT_ALL: u16 = 100; let index_name = "parentNameAndLabel"; - // ... and number of all contested resources - let query_all = VotePollsByDocumentTypeQuery { - contract_id: cfg.existing_data_contract_id, - document_type_name: cfg.existing_document_type_name.clone(), - index_name: index_name.to_string(), - start_at_value: None, - start_index_values: vec![Value::Text("dash".into())], - end_index_values: vec![], - limit: Some(LIMIT_ALL), - order_ascending: false, - }; - let count_all = ContestedResource::fetch_many(&sdk, query_all.clone()) - .await - .expect("fetch contested resources") - .0 - .len() as u16; - - // When we query for 2 contested values at a time, we get all of them - let mut i = 0; - let mut start_at_value = None; - while i < count_all && i < LIMIT_ALL { - let query = VotePollsByDocumentTypeQuery { - limit: Some(LIMIT), - start_at_value, - ..query_all.clone() + for order_ascending in [true, false] { + let query_all = VotePollsByDocumentTypeQuery { + contract_id: cfg.existing_data_contract_id, + document_type_name: cfg.existing_document_type_name.clone(), + index_name: index_name.to_string(), + start_at_value: None, + start_index_values: vec![Value::Text("dash".into())], + end_index_values: vec![], + limit: Some(LIMIT_ALL), + order_ascending, }; - - let rss = ContestedResource::fetch_many(&sdk, query) + let all = ContestedResource::fetch_many(&sdk, query_all.clone()) .await .expect("fetch contested resources"); - tracing::debug!(contested_resources=?rss, "Contested resources"); - let length = rss.0.len(); - let expected = if i + LIMIT > count_all { - count_all - i - } else { - LIMIT - }; - assert_eq!(length, expected as usize); - tracing::debug!(contested_resources=?rss, i, "Contested resources"); + let count_all = all.0.len() as u16; - let ContestedResource::Value(last) = - rss.0.into_iter().last().expect("last contested resource"); - start_at_value = Some((last, false)); + // When we query for 2 contested values at a time, we get all of them + let mut i = 0; + let mut start_at_value = None; + while i < count_all && i < LIMIT_ALL { + let query = VotePollsByDocumentTypeQuery { + limit: Some(LIMIT), + start_at_value, + order_ascending, + ..query_all.clone() + }; - i += length as u16; - } + let rss = ContestedResource::fetch_many(&sdk, query) + .await + .expect("fetch contested resources"); + tracing::debug!(contested_resources=?rss, "Contested resources"); + let length = rss.0.len(); + let expected = if i + LIMIT > count_all { + count_all - i + } else { + LIMIT + }; + assert_eq!(length, expected as usize); + tracing::debug!(contested_resources=?rss, i, "Contested resources"); + + for (j, fetched) in rss.0.iter().enumerate() { + let all_index = i + j as u16; + assert_eq!( + fetched, + &(all.0[all_index as usize]), + "fetched element {} ({:?}) must equal all element {} ({:?}) when ascending {}", + j, + fetched, + all_index, + all.0[all_index as usize], + order_ascending, + ); + } - assert_eq!(i, count_all, "all contested resources fetched"); + let ContestedResource::Value(last) = + rss.0.into_iter().last().expect("last contested resource"); + start_at_value = Some((last, false)); + + i += length as u16; + } + assert_eq!(i, count_all, "all contested resources fetched"); + } } -#[tokio::test(flavor = "multi_thread", worker_threads = 1)] -/// Empty string in start_index_values should not cause an error +/// Check various queries for [ContestedResource] that contain invalid field values /// /// ## Preconditions /// /// None -async fn test_contested_resources_idx_value_empty_string() { +#[tokio::test(flavor = "multi_thread", worker_threads = 1)] +async fn contested_resources_invalid_field_values() { setup_logs(); + type MutFn = fn(&mut VotePollsByDocumentTypeQuery); + struct TestCase { + name: &'static str, + query_mut_fn: MutFn, + expect: Result<&'static str, &'static str>, + } + + let test_cases: Vec = vec![ + TestCase { + name: "index value empty string is Ok", + query_mut_fn: |q| q.start_index_values = vec![Value::Text("".to_string())], + expect: Ok(""), + }, + TestCase { + name: "non existing document type returns InvalidArgument", + query_mut_fn: |q| q.document_type_name = "some random non-existing name".to_string(), + expect: Err( + r#"code: InvalidArgument, message: "document type some random non-existing name not found"#, + ), + }, + TestCase { + name: "non existing index returns InvalidArgument", + query_mut_fn: |q| q.index_name = "nx index".to_string(), + expect: Err( + r#"code: InvalidArgument, message: "index with name nx index is not the contested index"#, + ), + }, + TestCase { + name: "existing non-contested index returns InvalidArgument", + query_mut_fn: |q| q.index_name = "dashIdentityId".to_string(), + expect: Err( + r#"code: InvalidArgument, message: "index with name dashIdentityId is not the contested index"#, + ), + }, + TestCase { + // this fails with code: Internal, see PLAN-563 + name: "start_at_value wrong index type returns InvalidArgument PLAN-563", + query_mut_fn: |q| q.start_at_value = Some((Value::Array(vec![]), true)), + expect: Err(r#"code: InvalidArgument"#), + }, + TestCase { + name: "start_index_values empty vec returns top-level keys", + query_mut_fn: |q| q.start_index_values = vec![], + expect: Ok(r#"ContestedResources([Value(Text("dash"))])"#), + }, + TestCase { + name: "start_index_values empty string returns zero results", + query_mut_fn: |q| q.start_index_values = vec![Value::Text("".to_string())], + expect: Ok(r#"ContestedResources([])"#), + }, + TestCase { + // fails due to PLAN-662 + name: "start_index_values with two values PLAN-662", + query_mut_fn: |q| { + q.start_index_values = vec![ + Value::Text("dash".to_string()), + Value::Text("dada".to_string()), + ] + }, + expect: Ok(r#"ContestedResources([Value(Text("dash"))])"#), + }, + TestCase { + // fails due to PLAN-662 + name: "too many items in start_index_values PLAN-662", + query_mut_fn: |q| { + q.start_index_values = vec![ + Value::Text("dash".to_string()), + Value::Text("dada".to_string()), + Value::Text("eee".to_string()), + ] + }, + expect: Ok( + r#"code: InvalidArgument, message: "missing index values error: the start index values and the end index"#, + ), + }, + TestCase { + // fails due to PLAN-663 + name: "Non existing end_index_values PLAN-663", + query_mut_fn: |q| q.end_index_values = vec![Value::Text("non existing".to_string())], + expect: Ok(r#"ContestedResources([Value(Text("dash"))])"#), + }, + TestCase { + // fails due to PLAN-663 + name: "wrong type of end_index_values should return InvalidArgument PLAN-663", + query_mut_fn: |q| q.end_index_values = vec![Value::Array(vec![0.into(), 1.into()])], + expect: Ok(r#"code: InvalidArgument"#), + }, + TestCase { + // fails due to PLAN-664 + name: "limit 0 returns InvalidArgument PLAN-664", + query_mut_fn: |q| q.limit = Some(0), + expect: Ok(r#"code: InvalidArgument"#), + }, + TestCase { + name: "limit std::u16::MAX returns InvalidArgument PLAN-664", + query_mut_fn: |q| q.limit = Some(std::u16::MAX), + expect: Ok(r#"code: InvalidArgument"#), + }, + ]; + let cfg = Config::new(); let sdk = cfg .setup_api("test_contested_resources_idx_value_empty_string") .await; + check_mn_voting_prerequisities(&sdk, &cfg) + .await + .expect("prerequisities"); - // Given an empty string as index value - let index_name = "parentNameAndLabel"; - let index_value = Value::Text("".to_string()); - - // When I send a VotePollsByDocumentTypeQuery with this index value - let query = VotePollsByDocumentTypeQuery { + let base_query = VotePollsByDocumentTypeQuery { contract_id: cfg.existing_data_contract_id, document_type_name: cfg.existing_document_type_name.clone(), - index_name: index_name.to_string(), + index_name: "parentNameAndLabel".to_string(), start_at_value: None, // start_index_values: vec![], // Value(Text("dash")), Value(Text(""))]) - start_index_values: vec![index_value], + start_index_values: vec![Value::Text("dash".to_string())], end_index_values: vec![], limit: None, order_ascending: false, }; - let result = ContestedResource::fetch_many(&sdk, query).await; - tracing::debug!(contested_resources=?result, "Contested resources"); - // Then I don't get an error - assert!(result.is_ok(), "empty index value shall not cause an error"); + // check if the base query works + let result = ContestedResource::fetch_many(&sdk, base_query.clone()).await; + assert!( + result.is_ok_and(|v| !v.0.is_empty()), + "base query should return some results" + ); + + let mut failures: Vec<(&'static str, String)> = Default::default(); + + for test_case in test_cases { + tracing::debug!("Running test case: {}", test_case.name); + // create new sdk to ensure that test cases don't interfere with each other + let sdk = cfg + .setup_api("test_contested_resources_idx_value_empty_string") + .await; + + let mut query = base_query.clone(); + (test_case.query_mut_fn)(&mut query); + + let result = ContestedResource::fetch_many(&sdk, query).await; + match test_case.expect { + Ok(expected) if result.is_ok() => { + let result_string = format!("{:?}", result.as_ref().expect("result")); + if !result_string.contains(expected) { + failures.push(( + test_case.name, + format!("expected: {:#?}\ngot: {:?}\n", expected, result), + )); + } + } + Err(expected) if result.is_err() => { + let result = result.expect_err("error"); + if !result.to_string().contains(expected) { + failures.push(( + test_case.name, + format!("expected: {:#?}\ngot {:?}\n", expected, result), + )); + } + } + expected => { + failures.push(( + test_case.name, + format!("expected: {:#?}\ngot: {:?}\n", expected, result), + )); + } + } + } + if !failures.is_empty() { + for failure in &failures { + tracing::error!(?failure, "Failed: {}", failure.0); + } + let failed_cases = failures + .iter() + .map(|(name, _)| name.to_string()) + .collect::>() + .join("\n* "); + + panic!( + "{} test cases failed:\n{}\n\n{}\n", + failures.len(), + failed_cases, + failures + .iter() + .map(|(name, msg)| format!("===========================\n{}:\n\n{:?}", name, msg)) + .collect::>() + .join("\n") + ); + } } /// Ensure prerequsities for masternode voting tests are met From 05dea66efa05285fb43cbfaef6614dd524f8a1a5 Mon Sep 17 00:00:00 2001 From: Lukasz Klimek <842586+lklimek@users.noreply.github.com> Date: Thu, 20 Jun 2024 16:09:46 +0200 Subject: [PATCH 11/55] test(sdk): contested_resource_vote_state --- .../rs-sdk/tests/fetch/contested_resource.rs | 4 +- .../fetch/contested_resource_polls_by_ts.rs | 3 + .../fetch/contested_resource_vote_state.rs | 266 +++++++++++++++++- 3 files changed, 265 insertions(+), 8 deletions(-) diff --git a/packages/rs-sdk/tests/fetch/contested_resource.rs b/packages/rs-sdk/tests/fetch/contested_resource.rs index 93a6879e290..c4909d7b35e 100644 --- a/packages/rs-sdk/tests/fetch/contested_resource.rs +++ b/packages/rs-sdk/tests/fetch/contested_resource.rs @@ -1,9 +1,7 @@ //! Tests of ContestedResource object -use core::panic; -use std::{collections::BTreeMap, fmt::Debug}; - use crate::fetch::{common::setup_logs, config::Config}; +use core::panic; use dash_sdk::platform::FetchMany; use dpp::{ platform_value::Value, diff --git a/packages/rs-sdk/tests/fetch/contested_resource_polls_by_ts.rs b/packages/rs-sdk/tests/fetch/contested_resource_polls_by_ts.rs index 8a8c234580c..ce23a7b400b 100644 --- a/packages/rs-sdk/tests/fetch/contested_resource_polls_by_ts.rs +++ b/packages/rs-sdk/tests/fetch/contested_resource_polls_by_ts.rs @@ -51,6 +51,7 @@ async fn vote_polls_by_ts_ok() { feature = "network-testing", ignore = "requires manual DPNS names setup for masternode voting tests; see fn check_mn_voting_prerequisities()" )] +// fails due to PLAN-661 async fn vote_polls_by_ts_order() { setup_logs(); @@ -117,6 +118,8 @@ async fn vote_polls_by_ts_order() { feature = "network-testing", ignore = "requires manual DPNS names setup for masternode voting tests; see fn check_mn_voting_prerequisities()" )] + +// fails due to PLAN-659 async fn vote_polls_by_ts_limit() { setup_logs(); diff --git a/packages/rs-sdk/tests/fetch/contested_resource_vote_state.rs b/packages/rs-sdk/tests/fetch/contested_resource_vote_state.rs index 00d4e9921fd..d10efdc2550 100644 --- a/packages/rs-sdk/tests/fetch/contested_resource_vote_state.rs +++ b/packages/rs-sdk/tests/fetch/contested_resource_vote_state.rs @@ -2,8 +2,12 @@ use crate::fetch::{ common::setup_logs, config::Config, contested_resource::check_mn_voting_prerequisities, }; -use dash_sdk::platform::FetchMany; +use dash_sdk::platform::{Fetch, FetchMany}; use dpp::{ + data_contract::{accessors::v0::DataContractV0Getters, DataContract}, + document::{ + serialization_traits::DocumentPlatformConversionMethodsV0, Document, DocumentV0Getters, + }, identifier::Identifier, platform_value::Value, util::strings::convert_to_homograph_safe_chars, @@ -121,11 +125,18 @@ async fn contested_resource_vote_states_ok() { let cfg = Config::new(); let sdk = cfg.setup_api("contested_resource_vote_states_ok").await; - // Given some existing data contract ID and existing label + // Given some existing data contract and existing label let data_contract_id = cfg.existing_data_contract_id; - // TODO: Lookup the label instead of hardcoding it let label = Value::Text(convert_to_homograph_safe_chars("dada")); - let document_type_name = "domain".into(); + let document_type_name = "domain".to_string(); + + let data_contract = DataContract::fetch_by_identifier(&sdk, data_contract_id) + .await + .expect("fetch data contract") + .expect("found data contract"); + let document_type = data_contract + .document_type_for_name(&document_type_name) + .expect("found document type"); // When I query for vote poll states with existing index values let query = ContestedDocumentVotePollDriveQuery { @@ -151,6 +162,24 @@ async fn contested_resource_vote_states_ok() { !contenders.contenders.is_empty(), "contenders expected for this query" ); + + // verify that the contenders have the expected properties and we don't have duplicates + let mut seen = std::collections::BTreeSet::new(); + for contender in contenders.contenders { + let serialized_document = contender + .1 + .serialized_document() + .as_ref() + .expect("serialized doc"); + + let doc = Document::from_bytes(serialized_document, document_type, sdk.version()) + .expect("doc from bytes"); + assert!(seen.insert(doc.id()), "duplicate contender"); + let properties = doc.properties(); + assert_eq!(properties["parentDomainName"], Value::Text("dash".into())); + assert_eq!(properties["label"], Value::Text("dada".into())); + tracing::debug!(?properties, "document properties"); + } } /// Ensure we can limit the number of returned contenders. @@ -175,8 +204,8 @@ async fn contested_resource_vote_states_with_limit() { let data_contract_id = cfg.existing_data_contract_id; let limit: u16 = 2; let label = Value::Text("dada".into()); - // ensure we have enough contenders + // ensure we have enough contenders let query_all = ContestedDocumentVotePollDriveQuery { limit: None, offset: None, @@ -222,3 +251,230 @@ async fn contested_resource_vote_states_with_limit() { limit ); } + +/// Check various queries for [ContenderWithSerializedDocument] that contain invalid field values +/// +/// ## Preconditions +/// +/// None +#[tokio::test(flavor = "multi_thread", worker_threads = 1)] +async fn contested_resource_vote_states_fields() { + setup_logs(); + + type MutFn = fn(&mut ContestedDocumentVotePollDriveQuery); + struct TestCase { + name: &'static str, + query_mut_fn: MutFn, + expect: Result<&'static str, &'static str>, + } + + let test_cases: Vec = vec![ + TestCase { + name: "limit 0 PLAN-664", + query_mut_fn: |q| q.limit = Some(0), + expect: Ok("..."), + }, + TestCase { + name: "limit std::u16::MAX PLAN-664", + query_mut_fn: |q| q.limit = Some(std::u16::MAX), + expect: Ok("..."), + }, + TestCase { + name: "offset not None", + query_mut_fn: |q| q.offset = Some(1), + expect: Err( + r#"Generic("ContestedDocumentVotePollDriveQuery.offset field is internal and must be set to None")"#, + ), + }, + TestCase { + // TODO: pagination test + name: "start_at does not exist", + query_mut_fn: |q| q.start_at = Some(([0x11; 32], true)), + expect: Ok("Contenders { contenders: {Identifier("), + }, + TestCase { + name: "start_at 0xff;32", + query_mut_fn: |q| q.start_at = Some(([0xff; 32], true)), + expect: Ok("Contenders { contenders: {Identifier("), + }, + TestCase { + name: "non existing document type returns InvalidArgument", + query_mut_fn: |q| q.vote_poll.document_type_name = "nx doctype".to_string(), + expect: Err(r#"code: InvalidArgument, message: "document type nx doctype not found"#), + }, + TestCase { + name: "non existing index returns InvalidArgument", + query_mut_fn: |q| q.vote_poll.index_name = "nx index".to_string(), + expect: Err( + r#"code: InvalidArgument, message: "index with name nx index is not the contested index"#, + ), + }, + TestCase { + name: "existing non-contested index returns InvalidArgument", + query_mut_fn: |q| q.vote_poll.index_name = "dashIdentityId".to_string(), + expect: Err( + r#"code: InvalidArgument, message: "index with name dashIdentityId is not the contested index"#, + ), + }, + TestCase { + // todo maybe this should fail? or return everything? + name: "index_values empty vec returns zero results PLAN-665", + query_mut_fn: |q| q.vote_poll.index_values = vec![], + expect: Ok(r#"Contenders { contenders: {},"#), + }, + TestCase { + name: "index_values empty string returns zero results", + query_mut_fn: |q| q.vote_poll.index_values = vec![Value::Text("".to_string())], + expect: Ok("contenders: {}"), + }, + TestCase { + name: "index_values with one value returns results PLAN-665", + query_mut_fn: |q| q.vote_poll.index_values = vec![Value::Text("dash".to_string())], + expect: Ok("contenders: {...}"), + }, + TestCase { + name: "index_values with two values returns contenders ", + query_mut_fn: |q| { + q.vote_poll.index_values = vec![ + Value::Text("dash".to_string()), + Value::Text("dada".to_string()), + ] + }, + expect: Ok("contenders: {Identifier("), + }, + TestCase { + name: "index_values too many items should return error PLAN-665", + query_mut_fn: |q| { + q.vote_poll.index_values = vec![ + Value::Text("dash".to_string()), + Value::Text("dada".to_string()), + Value::Text("eee".to_string()), + ] + }, + expect: Ok( + r#"code: InvalidArgument, message: "missing index values error: the start index values and the end index"#, + ), + }, + TestCase { + name: "invalid contract id should cause InvalidArgument error", + query_mut_fn: |q| q.vote_poll.contract_id = Identifier::from([0xff; 32]), + expect: Err(r#"InvalidArgument, message: "contract not found error"#), + }, + TestCase { + name: + "allow_include_locked_and_abstaining_vote_tally false should return some contenders", + query_mut_fn: |q| q.allow_include_locked_and_abstaining_vote_tally = false, + expect: Ok(r#"contenders: {Identifier(IdentifierBytes32"#), + }, + TestCase { + name: "result_type Documents", + query_mut_fn: |q| { + q.result_type = ContestedDocumentVotePollDriveQueryResultType::Documents + }, + expect: Ok(r#"]), vote_tally: None })"#), + }, + TestCase { + name: "result_type DocumentsAndVoteTally", + query_mut_fn: |q| { + q.result_type = ContestedDocumentVotePollDriveQueryResultType::DocumentsAndVoteTally + }, + expect: Ok(r#"]), vote_tally: Some("#), + }, + TestCase { + name: "result_type VoteTally", + query_mut_fn: |q| { + q.result_type = ContestedDocumentVotePollDriveQueryResultType::VoteTally + }, + expect: Ok(r#"serialized_document: None, vote_tally: Some"#), + }, + ]; + + let cfg = Config::new(); + let sdk = cfg + .setup_api("test_contested_resources_idx_value_empty_string") + .await; + check_mn_voting_prerequisities(&sdk, &cfg) + .await + .expect("prerequisities"); + + let base_query = ContestedDocumentVotePollDriveQuery { + limit: None, + offset: None, + start_at: None, + vote_poll: ContestedDocumentResourceVotePoll { + index_name: "parentNameAndLabel".to_string(), + index_values: vec![Value::Text("dash".into()), Value::Text("dada".into())], + document_type_name: cfg.existing_document_type_name.clone(), + contract_id: cfg.existing_data_contract_id, + }, + allow_include_locked_and_abstaining_vote_tally: true, + result_type: ContestedDocumentVotePollDriveQueryResultType::DocumentsAndVoteTally, + }; + + // check if the base query works + let result = ContenderWithSerializedDocument::fetch_many(&sdk, base_query.clone()).await; + assert!( + result.is_ok_and(|v| !v.contenders.is_empty()), + "base query should return some results" + ); + + let mut failures: Vec<(&'static str, String)> = Default::default(); + + for test_case in test_cases { + tracing::debug!("Running test case: {}", test_case.name); + // create new sdk to ensure that test cases don't interfere with each other + let sdk = cfg.setup_api("contested_resource_vote_states_fields").await; + + let mut query = base_query.clone(); + (test_case.query_mut_fn)(&mut query); + + let result = ContenderWithSerializedDocument::fetch_many(&sdk, query).await; + match test_case.expect { + Ok(expected) if result.is_ok() => { + let result_string = format!("{:?}", result.as_ref().expect("result")); + if !result_string.contains(expected) { + failures.push(( + test_case.name, + format!("expected: {:#?}\ngot: {:?}\n", expected, result), + )); + } + } + Err(expected) if result.is_err() => { + let result = result.expect_err("error"); + if !result.to_string().contains(expected) { + failures.push(( + test_case.name, + format!("expected: {:#?}\ngot {:?}\n", expected, result), + )); + } + } + expected => { + failures.push(( + test_case.name, + format!("expected: {:#?}\ngot: {:?}\n", expected, result), + )); + } + } + } + if !failures.is_empty() { + for failure in &failures { + tracing::error!(?failure, "Failed: {}", failure.0); + } + let failed_cases = failures + .iter() + .map(|(name, _)| name.to_string()) + .collect::>() + .join("\n* "); + + panic!( + "{} test cases failed:\n* {}\n\n{}\n", + failures.len(), + failed_cases, + failures + .iter() + .map(|(name, msg)| format!("===========================\n{}:\n\n{:?}", name, msg)) + .collect::>() + .join("\n") + ); + } +} From 79bf4a860acf383e7c14b24ba7e384fdd51c6668 Mon Sep 17 00:00:00 2001 From: Lukasz Klimek <842586+lklimek@users.noreply.github.com> Date: Thu, 20 Jun 2024 16:24:18 +0200 Subject: [PATCH 12/55] test(sdk): separate sub-scenarios folders --- .../rs-sdk/tests/fetch/contested_resource.rs | 29 +++++++++---------- .../fetch/contested_resource_polls_by_ts.rs | 6 ++-- .../fetch/contested_resource_vote_state.rs | 20 ++++++++----- 3 files changed, 29 insertions(+), 26 deletions(-) diff --git a/packages/rs-sdk/tests/fetch/contested_resource.rs b/packages/rs-sdk/tests/fetch/contested_resource.rs index c4909d7b35e..3d8aeda42b6 100644 --- a/packages/rs-sdk/tests/fetch/contested_resource.rs +++ b/packages/rs-sdk/tests/fetch/contested_resource.rs @@ -36,7 +36,7 @@ async fn test_contested_resources_ok() { let cfg = Config::new(); let sdk = cfg.setup_api("test_contested_resources_ok").await; - check_mn_voting_prerequisities(&sdk, &cfg) + check_mn_voting_prerequisities(&cfg) .await .expect("prerequisities"); @@ -76,7 +76,7 @@ async fn contested_resources_start_at_value() { let cfg = Config::new(); let sdk = cfg.setup_api("contested_resources_start_at_value").await; - check_mn_voting_prerequisities(&sdk, &cfg) + check_mn_voting_prerequisities(&cfg) .await .expect("prerequisities"); @@ -151,7 +151,7 @@ async fn contested_resources_limit() { let cfg = Config::new(); let sdk = cfg.setup_api("contested_resources_limit").await; - check_mn_voting_prerequisities(&sdk, &cfg) + check_mn_voting_prerequisities(&cfg) .await .expect("prerequisities"); @@ -229,7 +229,7 @@ async fn contested_resources_limit() { /// /// None #[tokio::test(flavor = "multi_thread", worker_threads = 1)] -async fn contested_resources_invalid_field_values() { +async fn contested_resources_fields() { setup_logs(); type MutFn = fn(&mut VotePollsByDocumentTypeQuery); @@ -333,10 +333,8 @@ async fn contested_resources_invalid_field_values() { ]; let cfg = Config::new(); - let sdk = cfg - .setup_api("test_contested_resources_idx_value_empty_string") - .await; - check_mn_voting_prerequisities(&sdk, &cfg) + + check_mn_voting_prerequisities(&cfg) .await .expect("prerequisities"); @@ -353,7 +351,8 @@ async fn contested_resources_invalid_field_values() { }; // check if the base query works - let result = ContestedResource::fetch_many(&sdk, base_query.clone()).await; + let base_query_sdk = cfg.setup_api("contested_resources_fields_base_query").await; + let result = ContestedResource::fetch_many(&base_query_sdk, base_query.clone()).await; assert!( result.is_ok_and(|v| !v.0.is_empty()), "base query should return some results" @@ -365,7 +364,7 @@ async fn contested_resources_invalid_field_values() { tracing::debug!("Running test case: {}", test_case.name); // create new sdk to ensure that test cases don't interfere with each other let sdk = cfg - .setup_api("test_contested_resources_idx_value_empty_string") + .setup_api(&format!("contested_resources_fields_{}", test_case.name)) .await; let mut query = base_query.clone(); @@ -423,10 +422,8 @@ async fn contested_resources_invalid_field_values() { } /// Ensure prerequsities for masternode voting tests are met -pub async fn check_mn_voting_prerequisities( - sdk: &dash_sdk::Sdk, - cfg: &Config, -) -> Result<(), Vec> { +pub async fn check_mn_voting_prerequisities(cfg: &Config) -> Result<(), Vec> { + let sdk = cfg.setup_api("check_mn_voting_prerequisities").await; let mut errors = Vec::new(); let index_name = "parentNameAndLabel".to_string(); @@ -444,7 +441,7 @@ pub async fn check_mn_voting_prerequisities( // Check if we have enough contested resources; this implies that we have // at least 1 vote poll for each of them - let contested_resources = ContestedResource::fetch_many(sdk, query_contested_resources) + let contested_resources = ContestedResource::fetch_many(&sdk, query_contested_resources) .await .expect("fetch contested resources"); if contested_resources.0.len() < 3 { @@ -472,7 +469,7 @@ pub async fn check_mn_voting_prerequisities( result_type: ContestedDocumentVotePollDriveQueryResultType::DocumentsAndVoteTally, }; - let all_contenders = ContenderWithSerializedDocument::fetch_many(sdk, query_all.clone()) + let all_contenders = ContenderWithSerializedDocument::fetch_many(&sdk, query_all.clone()) .await .expect("fetch many contenders"); if all_contenders.contenders.len() < 3 { diff --git a/packages/rs-sdk/tests/fetch/contested_resource_polls_by_ts.rs b/packages/rs-sdk/tests/fetch/contested_resource_polls_by_ts.rs index ce23a7b400b..3f970fa6ef6 100644 --- a/packages/rs-sdk/tests/fetch/contested_resource_polls_by_ts.rs +++ b/packages/rs-sdk/tests/fetch/contested_resource_polls_by_ts.rs @@ -22,7 +22,7 @@ async fn vote_polls_by_ts_ok() { let cfg = Config::new(); let sdk = cfg.setup_api("vote_polls_by_ts_ok").await; - super::contested_resource::check_mn_voting_prerequisities(&sdk, &cfg) + super::contested_resource::check_mn_voting_prerequisities(&cfg) .await .expect("prerequisities"); @@ -57,7 +57,7 @@ async fn vote_polls_by_ts_order() { let cfg = Config::new(); let sdk = cfg.setup_api("vote_polls_by_ts_order").await; - super::contested_resource::check_mn_voting_prerequisities(&sdk, &cfg) + super::contested_resource::check_mn_voting_prerequisities(&cfg) .await .expect("prerequisities"); @@ -125,7 +125,7 @@ async fn vote_polls_by_ts_limit() { let cfg = Config::new(); let sdk = cfg.setup_api("vote_polls_by_ts_limit").await; - super::contested_resource::check_mn_voting_prerequisities(&sdk, &cfg) + super::contested_resource::check_mn_voting_prerequisities(&cfg) .await .expect("prerequisities"); diff --git a/packages/rs-sdk/tests/fetch/contested_resource_vote_state.rs b/packages/rs-sdk/tests/fetch/contested_resource_vote_state.rs index d10efdc2550..e1d4e2e8185 100644 --- a/packages/rs-sdk/tests/fetch/contested_resource_vote_state.rs +++ b/packages/rs-sdk/tests/fetch/contested_resource_vote_state.rs @@ -196,7 +196,7 @@ async fn contested_resource_vote_states_with_limit() { let sdk = cfg .setup_api("contested_resource_vote_states_with_limit") .await; - check_mn_voting_prerequisities(&sdk, &cfg) + check_mn_voting_prerequisities(&cfg) .await .expect("prerequisites not met"); @@ -390,10 +390,7 @@ async fn contested_resource_vote_states_fields() { ]; let cfg = Config::new(); - let sdk = cfg - .setup_api("test_contested_resources_idx_value_empty_string") - .await; - check_mn_voting_prerequisities(&sdk, &cfg) + check_mn_voting_prerequisities(&cfg) .await .expect("prerequisities"); @@ -412,7 +409,11 @@ async fn contested_resource_vote_states_fields() { }; // check if the base query works - let result = ContenderWithSerializedDocument::fetch_many(&sdk, base_query.clone()).await; + let base_query_sdk = cfg + .setup_api("contested_resource_vote_states_fields_base_query") + .await; + let result = + ContenderWithSerializedDocument::fetch_many(&base_query_sdk, base_query.clone()).await; assert!( result.is_ok_and(|v| !v.contenders.is_empty()), "base query should return some results" @@ -423,7 +424,12 @@ async fn contested_resource_vote_states_fields() { for test_case in test_cases { tracing::debug!("Running test case: {}", test_case.name); // create new sdk to ensure that test cases don't interfere with each other - let sdk = cfg.setup_api("contested_resource_vote_states_fields").await; + let sdk = cfg + .setup_api(&format!( + "contested_resources_vote_states_fields_{}", + test_case.name + )) + .await; let mut query = base_query.clone(); (test_case.query_mut_fn)(&mut query); From 6ac5e082d6891ff44f1d6db08f75cc5daa59617e Mon Sep 17 00:00:00 2001 From: Quantum Explorer Date: Mon, 24 Jun 2024 18:35:51 +0300 Subject: [PATCH 13/55] fix: fixes for contested document queries 2 --- .../state_transitions/masternode_vote/mod.rs | 1584 +++++++++++++---- .../contested_resource_vote_state/v0/mod.rs | 32 +- .../v0/mod.rs | 25 +- .../voting/contested_resources/v0/mod.rs | 25 +- packages/rs-drive/src/error/query.rs | 2 +- .../vote_polls_by_document_type_query.rs | 17 +- .../rs-sdk/tests/fetch/contested_resource.rs | 2 +- .../fetch/contested_resource_vote_state.rs | 2 +- 8 files changed, 1256 insertions(+), 433 deletions(-) diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/masternode_vote/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/masternode_vote/mod.rs index 30e0b9d7ffc..278bbdc735a 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/masternode_vote/mod.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/masternode_vote/mod.rs @@ -642,6 +642,292 @@ mod tests { } } + #[test] + fn test_existing_end_index_value() { + let platform_version = PlatformVersion::latest(); + let mut platform = TestPlatformBuilder::new() + .build_with_mock_rpc() + .set_genesis_state(); + + let platform_state = platform.state.load(); + + let (_contender_1, _contender_2, dpns_contract) = create_dpns_name_contest( + &mut platform, + &platform_state, + 7, + "quantum", + platform_version, + ); + + let domain = dpns_contract + .document_type_for_name("domain") + .expect("expected a profile document type"); + + let config = bincode::config::standard() + .with_big_endian() + .with_no_limit(); + + let encoded_existing_value = + bincode::encode_to_vec(Value::Text("quantum".to_string()), config) + .expect("expected to encode value"); + + let index_name = "parentNameAndLabel".to_string(); + + { + let query_validation_result = platform + .query_contested_resources( + GetContestedResourcesRequest { + version: Some(get_contested_resources_request::Version::V0( + GetContestedResourcesRequestV0 { + contract_id: dpns_contract.id().to_vec(), + document_type_name: domain.name().clone(), + index_name: index_name.clone(), + start_index_values: vec![], + end_index_values: vec![encoded_existing_value.clone()], + start_at_value_info: None, + count: None, + order_ascending: true, + prove: false, + }, + )), + }, + &platform_state, + platform_version, + ) + .expect("expected to execute query") + .into_data() + .expect("expected query to be valid"); + + let get_contested_resources_response::Version::V0( + GetContestedResourcesResponseV0 { + metadata: _, + result, + }, + ) = query_validation_result.version.expect("expected a version"); + + let Some(get_contested_resources_response_v0::Result::ContestedResourceValues( + get_contested_resources_response_v0::ContestedResourceValues { + contested_resource_values, + }, + )) = result + else { + panic!("expected contested resources") + }; + + let dash_encoded = + bincode::encode_to_vec(Value::Text("dash".to_string()), config) + .expect("expected to encode the word dash"); + + assert_eq!( + contested_resource_values.first(), + Some(dash_encoded).as_ref() + ); + } + + { + let query_validation_result = platform + .query_contested_resources( + GetContestedResourcesRequest { + version: Some(get_contested_resources_request::Version::V0( + GetContestedResourcesRequestV0 { + contract_id: dpns_contract.id().to_vec(), + document_type_name: domain.name().clone(), + index_name: index_name.clone(), + start_index_values: vec![], + end_index_values: vec![encoded_existing_value], + start_at_value_info: None, + count: None, + order_ascending: true, + prove: true, + }, + )), + }, + &platform_state, + platform_version, + ) + .expect("expected to execute query") + .into_data() + .expect("expected query to be valid"); + + let get_contested_resources_response::Version::V0( + GetContestedResourcesResponseV0 { + metadata: _, + result, + }, + ) = query_validation_result.version.expect("expected a version"); + + let Some(get_contested_resources_response_v0::Result::Proof(proof)) = result + else { + panic!("expected proof") + }; + + let resolved_contested_document_vote_poll_drive_query = + ResolvedVotePollsByDocumentTypeQuery { + contract: DataContractResolvedInfo::BorrowedDataContract( + dpns_contract.as_ref(), + ), + document_type_name: domain.name(), + index_name: &index_name, + start_index_values: &vec![], + end_index_values: &vec!["quantum".into()], + limit: None, + order_ascending: true, + start_at_value: &None, + }; + + let (_, contests) = resolved_contested_document_vote_poll_drive_query + .verify_contests_proof(proof.grovedb_proof.as_ref(), platform_version) + .expect("expected to verify proof"); + + let dash_encoded = + bincode::encode_to_vec(Value::Text("dash".to_string()), config) + .expect("expected to encode the word dash"); + + assert_eq!( + contests.first(), + Some(Value::Text("dash".to_string())).as_ref() + ); + } + } + + #[test] + fn test_non_existing_end_index_value() { + let platform_version = PlatformVersion::latest(); + let mut platform = TestPlatformBuilder::new() + .build_with_mock_rpc() + .set_genesis_state(); + + let platform_state = platform.state.load(); + + let (_contender_1, _contender_2, dpns_contract) = create_dpns_name_contest( + &mut platform, + &platform_state, + 7, + "quantum", + platform_version, + ); + + let domain = dpns_contract + .document_type_for_name("domain") + .expect("expected a profile document type"); + + let config = bincode::config::standard() + .with_big_endian() + .with_no_limit(); + + let encoded_non_existing_value = + bincode::encode_to_vec(Value::Text("cashcash".to_string()), config) + .expect("expected to encode value"); + + let index_name = "parentNameAndLabel".to_string(); + + let config = bincode::config::standard() + .with_big_endian() + .with_no_limit(); + + { + let query_validation_result = platform + .query_contested_resources( + GetContestedResourcesRequest { + version: Some(get_contested_resources_request::Version::V0( + GetContestedResourcesRequestV0 { + contract_id: dpns_contract.id().to_vec(), + document_type_name: domain.name().clone(), + index_name: index_name.clone(), + start_index_values: vec![], + end_index_values: vec![encoded_non_existing_value.clone()], + start_at_value_info: None, + count: None, + order_ascending: true, + prove: false, + }, + )), + }, + &platform_state, + platform_version, + ) + .expect("expected to execute query") + .into_data() + .expect("expected query to be valid"); + + let get_contested_resources_response::Version::V0( + GetContestedResourcesResponseV0 { + metadata: _, + result, + }, + ) = query_validation_result.version.expect("expected a version"); + + let Some(get_contested_resources_response_v0::Result::ContestedResourceValues( + get_contested_resources_response_v0::ContestedResourceValues { + contested_resource_values, + }, + )) = result + else { + panic!("expected contested resources") + }; + + assert_eq!(contested_resource_values.first(), None); + } + + { + let query_validation_result = platform + .query_contested_resources( + GetContestedResourcesRequest { + version: Some(get_contested_resources_request::Version::V0( + GetContestedResourcesRequestV0 { + contract_id: dpns_contract.id().to_vec(), + document_type_name: domain.name().clone(), + index_name: index_name.clone(), + start_index_values: vec![], + end_index_values: vec![encoded_non_existing_value], + start_at_value_info: None, + count: None, + order_ascending: true, + prove: true, + }, + )), + }, + &platform_state, + platform_version, + ) + .expect("expected to execute query") + .into_data() + .expect("expected query to be valid"); + + let get_contested_resources_response::Version::V0( + GetContestedResourcesResponseV0 { + metadata: _, + result, + }, + ) = query_validation_result.version.expect("expected a version"); + + let Some(get_contested_resources_response_v0::Result::Proof(proof)) = result + else { + panic!("expected proof") + }; + + let resolved_contested_document_vote_poll_drive_query = + ResolvedVotePollsByDocumentTypeQuery { + contract: DataContractResolvedInfo::BorrowedDataContract( + dpns_contract.as_ref(), + ), + document_type_name: domain.name(), + index_name: &index_name, + start_index_values: &vec![], + end_index_values: &vec!["cashcash".into()], + limit: None, + order_ascending: true, + start_at_value: &None, + }; + + let (_, contests) = resolved_contested_document_vote_poll_drive_query + .verify_contests_proof(proof.grovedb_proof.as_ref(), platform_version) + .expect("expected to verify proof"); + + assert_eq!(contests.first(), None); + } + } + #[test] #[ignore] // Currently will have an issue due to a grovedb bug fn test_limit() { @@ -652,7 +938,7 @@ mod tests { let platform_state = platform.state.load(); - let (_contender_1, _contender_2, dpns_contract) = create_dpns_name_contest( + let (_contender_1, _contender_2, _dpns_contract) = create_dpns_name_contest( &mut platform, &platform_state, 7, @@ -660,7 +946,7 @@ mod tests { platform_version, ); - let (_contender_3, _contender_4, dpns_contract) = create_dpns_name_contest( + let (_contender_3, _contender_4, _dpns_contract) = create_dpns_name_contest( &mut platform, &platform_state, 8, @@ -962,8 +1248,25 @@ mod tests { } mod vote_state_query { - use super::*; + use dapi_grpc::platform::v0::get_contested_resource_vote_state_request::{ + get_contested_resource_vote_state_request_v0, + GetContestedResourceVoteStateRequestV0, + }; + use dapi_grpc::platform::v0::get_contested_resource_vote_state_response::{ + get_contested_resource_vote_state_response_v0, + GetContestedResourceVoteStateResponseV0, + }; + use dapi_grpc::platform::v0::{ + get_contested_resource_vote_state_request, + get_contested_resource_vote_state_response, GetContestedResourceVoteStateRequest, + }; + use dpp::document::Document; + use dpp::voting::contender_structs::{Contender, ContenderV0}; + use drive::query::vote_poll_vote_state_query::{ + ContestedDocumentVotePollDriveQueryResultType, + ResolvedContestedDocumentVotePollDriveQuery, + }; #[test] fn test_not_proved_vote_state_query_request_after_vote() { @@ -1132,27 +1435,243 @@ mod tests { platform_version, ); - let (masternode_1, signer_1, voting_key_1) = - setup_masternode_identity(&mut platform, 29, platform_version); + let (masternode_1, signer_1, voting_key_1) = + setup_masternode_identity(&mut platform, 29, platform_version); + + let platform_state = platform.state.load(); + + perform_vote( + &mut platform, + &platform_state, + dpns_contract.as_ref(), + TowardsIdentity(contender_1.id()), + "quantum", + &signer_1, + masternode_1.id(), + &voting_key_1, + 1, + None, + platform_version, + ); + + { + let (contenders, abstaining, locking, finished_info) = get_proved_vote_states( + &platform, + &platform_state, + &dpns_contract, + "quantum", + None, + true, + None, + ResultType::DocumentsAndVoteTally, + platform_version, + ); + + assert_eq!(finished_info, None); + + assert_eq!(contenders.len(), 2); + + let first_contender = contenders.first().unwrap(); + + let second_contender = contenders.last().unwrap(); + + assert_ne!(first_contender.document(), second_contender.document()); + + assert_eq!(first_contender.identity_id(), contender_1.id()); + + assert_eq!(second_contender.identity_id(), contender_2.id()); + + assert_eq!(first_contender.vote_tally(), Some(1)); + + assert_eq!(second_contender.vote_tally(), Some(0)); + + assert_eq!(abstaining, Some(0)); + + assert_eq!(locking, Some(0)); + } + + { + let (contenders, abstaining, locking, finished_info) = get_proved_vote_states( + &platform, + &platform_state, + &dpns_contract, + "quantum", + None, + true, + None, + ResultType::Documents, + platform_version, + ); + + assert_eq!(finished_info, None); + + assert_eq!(contenders.len(), 2); + + let first_contender = contenders.first().unwrap(); + + let second_contender = contenders.last().unwrap(); + + assert_ne!(first_contender.document(), second_contender.document()); + + assert_eq!(first_contender.identity_id(), contender_1.id()); + + assert_eq!(second_contender.identity_id(), contender_2.id()); + + assert_eq!(first_contender.vote_tally(), None); + + assert_eq!(second_contender.vote_tally(), None); + + assert_eq!(abstaining, None); + + assert_eq!(locking, None); + } + + { + let (contenders, abstaining, locking, finished_info) = get_proved_vote_states( + &platform, + &platform_state, + &dpns_contract, + "quantum", + None, + true, + None, + ResultType::VoteTally, + platform_version, + ); + + assert_eq!(finished_info, None); + + assert_eq!(contenders.len(), 2); + + let first_contender = contenders.first().unwrap(); + + let second_contender = contenders.last().unwrap(); + + assert_eq!(first_contender.document(), &None); + + assert_eq!(second_contender.document(), &None); + + assert_eq!(first_contender.identity_id(), contender_1.id()); + + assert_eq!(second_contender.identity_id(), contender_2.id()); + + assert_eq!(first_contender.vote_tally(), Some(1)); + + assert_eq!(second_contender.vote_tally(), Some(0)); + + assert_eq!(abstaining, Some(0)); + + assert_eq!(locking, Some(0)); + } + } + + #[test] + fn test_not_proved_vote_state_query_request_after_many_votes() { + let platform_version = PlatformVersion::latest(); + let mut platform = TestPlatformBuilder::new() + .build_with_mock_rpc() + .set_genesis_state(); + + let platform_state = platform.state.load(); + + let (contender_1, contender_2, dpns_contract) = create_dpns_name_contest( + &mut platform, + &platform_state, + 7, + "quantum", + platform_version, + ); + + perform_votes_multi( + &mut platform, + dpns_contract.as_ref(), + vec![ + (TowardsIdentity(contender_1.id()), 50), + (TowardsIdentity(contender_2.id()), 5), + (ResourceVoteChoice::Abstain, 10), + (ResourceVoteChoice::Lock, 3), + ], + "quantum", + 10, + platform_version, + ); + + // DocumentsAndVoteTally + { + let (contenders, abstaining, locking, finished_vote_info) = get_vote_states( + &platform, + &platform_state, + &dpns_contract, + "quantum", + None, + true, + None, + ResultType::DocumentsAndVoteTally, + platform_version, + ); + + assert_eq!(finished_vote_info, None); + + assert_eq!(contenders.len(), 2); + + let first_contender = contenders.first().unwrap(); + + let second_contender = contenders.last().unwrap(); + + assert_ne!(first_contender.document(), second_contender.document()); + + assert_eq!(first_contender.identity_id(), contender_1.id()); + + assert_eq!(second_contender.identity_id(), contender_2.id()); + + assert_eq!(first_contender.vote_tally(), Some(50)); + + assert_eq!(second_contender.vote_tally(), Some(5)); + + assert_eq!(abstaining, Some(10)); + + assert_eq!(locking, Some(3)); + + // Now let's not include locked and abstaining + + let (contenders, abstaining, locking, finished_vote_info) = get_vote_states( + &platform, + &platform_state, + &dpns_contract, + "quantum", + None, + false, + None, + ResultType::DocumentsAndVoteTally, + platform_version, + ); + + assert_eq!(finished_vote_info, None); + + assert_eq!(contenders.len(), 2); + + let first_contender = contenders.first().unwrap(); + + let second_contender = contenders.last().unwrap(); + + assert_ne!(first_contender.document(), second_contender.document()); + + assert_eq!(first_contender.identity_id(), contender_1.id()); + + assert_eq!(second_contender.identity_id(), contender_2.id()); + + assert_eq!(first_contender.vote_tally(), Some(50)); - let platform_state = platform.state.load(); + assert_eq!(second_contender.vote_tally(), Some(5)); - perform_vote( - &mut platform, - &platform_state, - dpns_contract.as_ref(), - TowardsIdentity(contender_1.id()), - "quantum", - &signer_1, - masternode_1.id(), - &voting_key_1, - 1, - None, - platform_version, - ); + assert_eq!(abstaining, None); + + assert_eq!(locking, None); + } + // Documents { - let (contenders, abstaining, locking, finished_info) = get_proved_vote_states( + let (contenders, abstaining, locking, finished_vote_info) = get_vote_states( &platform, &platform_state, &dpns_contract, @@ -1160,11 +1679,11 @@ mod tests { None, true, None, - ResultType::DocumentsAndVoteTally, + ResultType::Documents, platform_version, ); - assert_eq!(finished_info, None); + assert_eq!(finished_vote_info, None); assert_eq!(contenders.len(), 2); @@ -1178,29 +1697,29 @@ mod tests { assert_eq!(second_contender.identity_id(), contender_2.id()); - assert_eq!(first_contender.vote_tally(), Some(1)); + assert_eq!(first_contender.vote_tally(), None); - assert_eq!(second_contender.vote_tally(), Some(0)); + assert_eq!(second_contender.vote_tally(), None); - assert_eq!(abstaining, Some(0)); + assert_eq!(abstaining, None); - assert_eq!(locking, Some(0)); - } + assert_eq!(locking, None); - { - let (contenders, abstaining, locking, finished_info) = get_proved_vote_states( + // Now let's not include locked and abstaining + + let (contenders, abstaining, locking, finished_vote_info) = get_vote_states( &platform, &platform_state, &dpns_contract, "quantum", None, - true, + false, None, ResultType::Documents, platform_version, ); - assert_eq!(finished_info, None); + assert_eq!(finished_vote_info, None); assert_eq!(contenders.len(), 2); @@ -1223,8 +1742,9 @@ mod tests { assert_eq!(locking, None); } + // VoteTally { - let (contenders, abstaining, locking, finished_info) = get_proved_vote_states( + let (contenders, abstaining, locking, finished_vote_info) = get_vote_states( &platform, &platform_state, &dpns_contract, @@ -1236,7 +1756,7 @@ mod tests { platform_version, ); - assert_eq!(finished_info, None); + assert_eq!(finished_vote_info, None); assert_eq!(contenders.len(), 2); @@ -1252,18 +1772,56 @@ mod tests { assert_eq!(second_contender.identity_id(), contender_2.id()); - assert_eq!(first_contender.vote_tally(), Some(1)); + assert_eq!(first_contender.vote_tally(), Some(50)); - assert_eq!(second_contender.vote_tally(), Some(0)); + assert_eq!(second_contender.vote_tally(), Some(5)); - assert_eq!(abstaining, Some(0)); + assert_eq!(abstaining, Some(10)); - assert_eq!(locking, Some(0)); + assert_eq!(locking, Some(3)); + + // Now let's not include locked and abstaining + + let (contenders, abstaining, locking, finished_vote_info) = get_vote_states( + &platform, + &platform_state, + &dpns_contract, + "quantum", + None, + false, + None, + ResultType::VoteTally, + platform_version, + ); + + assert_eq!(finished_vote_info, None); + + assert_eq!(contenders.len(), 2); + + let first_contender = contenders.first().unwrap(); + + let second_contender = contenders.last().unwrap(); + + assert_eq!(first_contender.document(), &None); + + assert_eq!(second_contender.document(), &None); + + assert_eq!(first_contender.identity_id(), contender_1.id()); + + assert_eq!(second_contender.identity_id(), contender_2.id()); + + assert_eq!(first_contender.vote_tally(), Some(50)); + + assert_eq!(second_contender.vote_tally(), Some(5)); + + assert_eq!(abstaining, None); + + assert_eq!(locking, None); } } #[test] - fn test_not_proved_vote_state_query_request_after_many_votes() { + fn test_proved_vote_state_query_request_after_many_votes() { let platform_version = PlatformVersion::latest(); let mut platform = TestPlatformBuilder::new() .build_with_mock_rpc() @@ -1295,7 +1853,7 @@ mod tests { // DocumentsAndVoteTally { - let (contenders, abstaining, locking, finished_vote_info) = get_vote_states( + let (contenders, abstaining, locking, finished_info) = get_proved_vote_states( &platform, &platform_state, &dpns_contract, @@ -1307,7 +1865,7 @@ mod tests { platform_version, ); - assert_eq!(finished_vote_info, None); + assert_eq!(finished_info, None); assert_eq!(contenders.len(), 2); @@ -1331,7 +1889,7 @@ mod tests { // Now let's not include locked and abstaining - let (contenders, abstaining, locking, finished_vote_info) = get_vote_states( + let (contenders, abstaining, locking, finished_info) = get_proved_vote_states( &platform, &platform_state, &dpns_contract, @@ -1343,7 +1901,7 @@ mod tests { platform_version, ); - assert_eq!(finished_vote_info, None); + assert_eq!(finished_info, None); assert_eq!(contenders.len(), 2); @@ -1368,7 +1926,7 @@ mod tests { // Documents { - let (contenders, abstaining, locking, finished_vote_info) = get_vote_states( + let (contenders, abstaining, locking, finished_info) = get_proved_vote_states( &platform, &platform_state, &dpns_contract, @@ -1380,7 +1938,7 @@ mod tests { platform_version, ); - assert_eq!(finished_vote_info, None); + assert_eq!(finished_info, None); assert_eq!(contenders.len(), 2); @@ -1404,7 +1962,7 @@ mod tests { // Now let's not include locked and abstaining - let (contenders, abstaining, locking, finished_vote_info) = get_vote_states( + let (contenders, abstaining, locking, finished_info) = get_proved_vote_states( &platform, &platform_state, &dpns_contract, @@ -1416,7 +1974,7 @@ mod tests { platform_version, ); - assert_eq!(finished_vote_info, None); + assert_eq!(finished_info, None); assert_eq!(contenders.len(), 2); @@ -1441,7 +1999,7 @@ mod tests { // VoteTally { - let (contenders, abstaining, locking, finished_vote_info) = get_vote_states( + let (contenders, abstaining, locking, finished_info) = get_proved_vote_states( &platform, &platform_state, &dpns_contract, @@ -1453,7 +2011,7 @@ mod tests { platform_version, ); - assert_eq!(finished_vote_info, None); + assert_eq!(finished_info, None); assert_eq!(contenders.len(), 2); @@ -1479,46 +2037,226 @@ mod tests { // Now let's not include locked and abstaining - let (contenders, abstaining, locking, finished_vote_info) = get_vote_states( + let (contenders, abstaining, locking, finished_info) = get_proved_vote_states( + &platform, + &platform_state, + &dpns_contract, + "quantum", + None, + false, + None, + ResultType::VoteTally, + platform_version, + ); + + assert_eq!(finished_info, None); + + assert_eq!(contenders.len(), 2); + + let first_contender = contenders.first().unwrap(); + + let second_contender = contenders.last().unwrap(); + + assert_eq!(first_contender.document(), &None); + + assert_eq!(second_contender.document(), &None); + + assert_eq!(first_contender.identity_id(), contender_1.id()); + + assert_eq!(second_contender.identity_id(), contender_2.id()); + + assert_eq!(first_contender.vote_tally(), Some(50)); + + assert_eq!(second_contender.vote_tally(), Some(5)); + + assert_eq!(abstaining, None); + + assert_eq!(locking, None); + } + } + + fn get_vote_states_expect_error( + platform: &TempPlatform, + platform_state: &PlatformState, + dpns_contract: &DataContract, + index_values: Vec>, + count: Option, + allow_include_locked_and_abstaining_vote_tally: bool, + start_at_identifier_info: Option< + get_contested_resource_vote_state_request_v0::StartAtIdentifierInfo, + >, + result_type: ResultType, + prove: bool, + expected_error: &str, + platform_version: &PlatformVersion, + ) { + // Now let's run a query for the vote totals + + let domain = dpns_contract + .document_type_for_name("domain") + .expect("expected a profile document type"); + + let index_name = "parentNameAndLabel".to_string(); + + let query_validation_result = platform + .query_contested_resource_vote_state( + GetContestedResourceVoteStateRequest { + version: Some(get_contested_resource_vote_state_request::Version::V0( + GetContestedResourceVoteStateRequestV0 { + contract_id: dpns_contract.id().to_vec(), + document_type_name: domain.name().clone(), + index_name: index_name.clone(), + index_values, + result_type: result_type as i32, + allow_include_locked_and_abstaining_vote_tally, + start_at_identifier_info, + count, + prove, + }, + )), + }, + platform_state, + platform_version, + ) + .expect("expected to execute query"); + + assert_eq!( + query_validation_result + .first_error() + .expect("expected query to return error") + .to_string() + .as_str(), + expected_error + ); + } + + #[test] + fn test_vote_state_query_request_with_no_index_values_should_return_error() { + let platform_version = PlatformVersion::latest(); + let mut platform = TestPlatformBuilder::new() + .build_with_mock_rpc() + .set_genesis_state(); + + let platform_state = platform.state.load(); + + let (contender_1, contender_2, dpns_contract) = create_dpns_name_contest( + &mut platform, + &platform_state, + 7, + "quantum", + platform_version, + ); + + perform_votes_multi( + &mut platform, + dpns_contract.as_ref(), + vec![ + (TowardsIdentity(contender_1.id()), 50), + (TowardsIdentity(contender_2.id()), 5), + (ResourceVoteChoice::Abstain, 10), + (ResourceVoteChoice::Lock, 3), + ], + "quantum", + 10, + platform_version, + ); + + // DocumentsAndVoteTally + { + get_vote_states_expect_error( + &platform, + &platform_state, + &dpns_contract, + vec![], + None, + true, + None, + ResultType::DocumentsAndVoteTally, + false, + "invalid argument error: query uses index parentNameAndLabel, this index has 2 properties, but the query provided 0 index values instead", + platform_version, + ); + + get_vote_states_expect_error( + &platform, + &platform_state, + &dpns_contract, + vec![], + None, + true, + None, + ResultType::DocumentsAndVoteTally, + true, + "invalid argument error: query uses index parentNameAndLabel, this index has 2 properties, but the query provided 0 index values instead", + platform_version, + ); + } + + // Documents + { + get_vote_states_expect_error( + &platform, + &platform_state, + &dpns_contract, + vec![], + None, + true, + None, + ResultType::Documents, + false, + "invalid argument error: query uses index parentNameAndLabel, this index has 2 properties, but the query provided 0 index values instead", + platform_version, + ); + + get_vote_states_expect_error( + &platform, + &platform_state, + &dpns_contract, + vec![], + None, + true, + None, + ResultType::Documents, + true, + "invalid argument error: query uses index parentNameAndLabel, this index has 2 properties, but the query provided 0 index values instead", + platform_version, + ); + } + + // VoteTally + { + get_vote_states_expect_error( &platform, &platform_state, &dpns_contract, - "quantum", + vec![], None, - false, + true, None, ResultType::VoteTally, + false, + "invalid argument error: query uses index parentNameAndLabel, this index has 2 properties, but the query provided 0 index values instead", platform_version, ); - assert_eq!(finished_vote_info, None); - - assert_eq!(contenders.len(), 2); - - let first_contender = contenders.first().unwrap(); - - let second_contender = contenders.last().unwrap(); - - assert_eq!(first_contender.document(), &None); - - assert_eq!(second_contender.document(), &None); - - assert_eq!(first_contender.identity_id(), contender_1.id()); - - assert_eq!(second_contender.identity_id(), contender_2.id()); - - assert_eq!(first_contender.vote_tally(), Some(50)); - - assert_eq!(second_contender.vote_tally(), Some(5)); - - assert_eq!(abstaining, None); - - assert_eq!(locking, None); + get_vote_states_expect_error( + &platform, + &platform_state, + &dpns_contract, + vec![], + None, + true, + None, + ResultType::VoteTally, + true, + "invalid argument error: query uses index parentNameAndLabel, this index has 2 properties, but the query provided 0 index values instead", + platform_version, + ); } } #[test] - fn test_proved_vote_state_query_request_after_many_votes() { + fn test_vote_state_query_request_with_limit_too_high_should_return_error() { let platform_version = PlatformVersion::latest(); let mut platform = TestPlatformBuilder::new() .build_with_mock_rpc() @@ -1548,227 +2286,112 @@ mod tests { platform_version, ); + let config = bincode::config::standard() + .with_big_endian() + .with_no_limit(); + + let dash_encoded = bincode::encode_to_vec(Value::Text("dash".to_string()), config) + .expect("expected to encode the word dash"); + + let quantum_encoded = bincode::encode_to_vec( + Value::Text(convert_to_homograph_safe_chars("quantum")), + config, + ) + .expect("expected to encode the word quantum"); + + let index_values = vec![dash_encoded, quantum_encoded]; + // DocumentsAndVoteTally { - let (contenders, abstaining, locking, finished_info) = get_proved_vote_states( + get_vote_states_expect_error( &platform, &platform_state, &dpns_contract, - "quantum", - None, + index_values.clone(), + Some(3000), true, None, ResultType::DocumentsAndVoteTally, + false, + "invalid argument error: limit 3000 out of bounds of [1, 100]", platform_version, ); - assert_eq!(finished_info, None); - - assert_eq!(contenders.len(), 2); - - let first_contender = contenders.first().unwrap(); - - let second_contender = contenders.last().unwrap(); - - assert_ne!(first_contender.document(), second_contender.document()); - - assert_eq!(first_contender.identity_id(), contender_1.id()); - - assert_eq!(second_contender.identity_id(), contender_2.id()); - - assert_eq!(first_contender.vote_tally(), Some(50)); - - assert_eq!(second_contender.vote_tally(), Some(5)); - - assert_eq!(abstaining, Some(10)); - - assert_eq!(locking, Some(3)); - - // Now let's not include locked and abstaining - - let (contenders, abstaining, locking, finished_info) = get_proved_vote_states( + get_vote_states_expect_error( &platform, &platform_state, &dpns_contract, - "quantum", - None, - false, + index_values.clone(), + Some(3000), + true, None, ResultType::DocumentsAndVoteTally, + true, + "invalid argument error: limit 3000 out of bounds of [1, 100]", platform_version, ); - - assert_eq!(finished_info, None); - - assert_eq!(contenders.len(), 2); - - let first_contender = contenders.first().unwrap(); - - let second_contender = contenders.last().unwrap(); - - assert_ne!(first_contender.document(), second_contender.document()); - - assert_eq!(first_contender.identity_id(), contender_1.id()); - - assert_eq!(second_contender.identity_id(), contender_2.id()); - - assert_eq!(first_contender.vote_tally(), Some(50)); - - assert_eq!(second_contender.vote_tally(), Some(5)); - - assert_eq!(abstaining, None); - - assert_eq!(locking, None); } // Documents { - let (contenders, abstaining, locking, finished_info) = get_proved_vote_states( + get_vote_states_expect_error( &platform, &platform_state, &dpns_contract, - "quantum", - None, + index_values.clone(), + Some(3000), true, None, ResultType::Documents, + false, + "invalid argument error: limit 3000 out of bounds of [1, 100]", platform_version, ); - assert_eq!(finished_info, None); - - assert_eq!(contenders.len(), 2); - - let first_contender = contenders.first().unwrap(); - - let second_contender = contenders.last().unwrap(); - - assert_ne!(first_contender.document(), second_contender.document()); - - assert_eq!(first_contender.identity_id(), contender_1.id()); - - assert_eq!(second_contender.identity_id(), contender_2.id()); - - assert_eq!(first_contender.vote_tally(), None); - - assert_eq!(second_contender.vote_tally(), None); - - assert_eq!(abstaining, None); - - assert_eq!(locking, None); - - // Now let's not include locked and abstaining - - let (contenders, abstaining, locking, finished_info) = get_proved_vote_states( + get_vote_states_expect_error( &platform, &platform_state, &dpns_contract, - "quantum", - None, - false, + index_values.clone(), + Some(3000), + true, None, ResultType::Documents, + true, + "invalid argument error: limit 3000 out of bounds of [1, 100]", platform_version, ); - - assert_eq!(finished_info, None); - - assert_eq!(contenders.len(), 2); - - let first_contender = contenders.first().unwrap(); - - let second_contender = contenders.last().unwrap(); - - assert_ne!(first_contender.document(), second_contender.document()); - - assert_eq!(first_contender.identity_id(), contender_1.id()); - - assert_eq!(second_contender.identity_id(), contender_2.id()); - - assert_eq!(first_contender.vote_tally(), None); - - assert_eq!(second_contender.vote_tally(), None); - - assert_eq!(abstaining, None); - - assert_eq!(locking, None); } // VoteTally { - let (contenders, abstaining, locking, finished_info) = get_proved_vote_states( + get_vote_states_expect_error( &platform, &platform_state, &dpns_contract, - "quantum", - None, + index_values.clone(), + Some(3000), true, None, ResultType::VoteTally, + false, + "invalid argument error: limit 3000 out of bounds of [1, 100]", platform_version, ); - assert_eq!(finished_info, None); - - assert_eq!(contenders.len(), 2); - - let first_contender = contenders.first().unwrap(); - - let second_contender = contenders.last().unwrap(); - - assert_eq!(first_contender.document(), &None); - - assert_eq!(second_contender.document(), &None); - - assert_eq!(first_contender.identity_id(), contender_1.id()); - - assert_eq!(second_contender.identity_id(), contender_2.id()); - - assert_eq!(first_contender.vote_tally(), Some(50)); - - assert_eq!(second_contender.vote_tally(), Some(5)); - - assert_eq!(abstaining, Some(10)); - - assert_eq!(locking, Some(3)); - - // Now let's not include locked and abstaining - - let (contenders, abstaining, locking, finished_info) = get_proved_vote_states( + get_vote_states_expect_error( &platform, &platform_state, &dpns_contract, - "quantum", - None, - false, + index_values.clone(), + Some(3000), + true, None, ResultType::VoteTally, + true, + "invalid argument error: limit 3000 out of bounds of [1, 100]", platform_version, ); - - assert_eq!(finished_info, None); - - assert_eq!(contenders.len(), 2); - - let first_contender = contenders.first().unwrap(); - - let second_contender = contenders.last().unwrap(); - - assert_eq!(first_contender.document(), &None); - - assert_eq!(second_contender.document(), &None); - - assert_eq!(first_contender.identity_id(), contender_1.id()); - - assert_eq!(second_contender.identity_id(), contender_2.id()); - - assert_eq!(first_contender.vote_tally(), Some(50)); - - assert_eq!(second_contender.vote_tally(), Some(5)); - - assert_eq!(abstaining, None); - - assert_eq!(locking, None); } } } @@ -3439,84 +4062,169 @@ mod tests { platform_version, ); - let GetVotePollsByEndDateResponse { version } = platform - .query_vote_polls_by_end_date_query( - GetVotePollsByEndDateRequest { - version: Some(get_vote_polls_by_end_date_request::Version::V0( - GetVotePollsByEndDateRequestV0 { - start_time_info: Some( - get_vote_polls_by_end_date_request_v0::StartAtTimeInfo { - start_time_ms: 1_209_603_000, - start_time_included: false, - }, - ), - end_time_info: None, - limit: None, - offset: None, - ascending: true, - prove: false, - }, - )), + // ascending order + { + let GetVotePollsByEndDateResponse { version } = platform + .query_vote_polls_by_end_date_query( + GetVotePollsByEndDateRequest { + version: Some(get_vote_polls_by_end_date_request::Version::V0( + GetVotePollsByEndDateRequestV0 { + start_time_info: Some( + get_vote_polls_by_end_date_request_v0::StartAtTimeInfo { + start_time_ms: 1_209_603_000, + start_time_included: false, + }, + ), + end_time_info: None, + limit: None, + offset: None, + ascending: true, + prove: false, + }, + )), + }, + &platform_state, + platform_version, + ) + .expect("expected to execute query") + .into_data() + .expect("expected query to be valid"); + + let get_vote_polls_by_end_date_response::Version::V0( + GetVotePollsByEndDateResponseV0 { + metadata: _, + result, }, - &platform_state, - platform_version, - ) - .expect("expected to execute query") - .into_data() - .expect("expected query to be valid"); + ) = version.expect("expected a version"); + + let Some(get_vote_polls_by_end_date_response_v0::Result::VotePollsByTimestamps( + get_vote_polls_by_end_date_response_v0::SerializedVotePollsByTimestamps { + vote_polls_by_timestamps, + finished_results, + }, + )) = result + else { + panic!("expected contenders") + }; - let get_vote_polls_by_end_date_response::Version::V0( - GetVotePollsByEndDateResponseV0 { - metadata: _, - result, - }, - ) = version.expect("expected a version"); + assert!(finished_results); - let Some(get_vote_polls_by_end_date_response_v0::Result::VotePollsByTimestamps( - get_vote_polls_by_end_date_response_v0::SerializedVotePollsByTimestamps { + let serialized_contested_vote_poll_bytes_2 = vec![ + 0, 230, 104, 198, 89, 175, 102, 174, 225, 231, 44, 24, 109, 222, 123, 91, + 126, 10, 29, 113, 42, 9, 196, 13, 87, 33, 246, 34, 191, 83, 197, 49, 85, 6, + 100, 111, 109, 97, 105, 110, 18, 112, 97, 114, 101, 110, 116, 78, 97, 109, + 101, 65, 110, 100, 76, 97, 98, 101, 108, 2, 18, 4, 100, 97, 115, 104, 18, + 6, 99, 48, 48, 49, 49, 48, + ]; + + let serialized_contested_vote_poll_bytes_3 = vec![ + 0, 230, 104, 198, 89, 175, 102, 174, 225, 231, 44, 24, 109, 222, 123, 91, + 126, 10, 29, 113, 42, 9, 196, 13, 87, 33, 246, 34, 191, 83, 197, 49, 85, 6, + 100, 111, 109, 97, 105, 110, 18, 112, 97, 114, 101, 110, 116, 78, 97, 109, + 101, 65, 110, 100, 76, 97, 98, 101, 108, 2, 18, 4, 100, 97, 115, 104, 18, + 8, 99, 114, 97, 122, 121, 109, 97, 110, + ]; + + assert_eq!( vote_polls_by_timestamps, - finished_results, - }, - )) = result - else { - panic!("expected contenders") - }; + vec![ + SerializedVotePollsByTimestamp { + timestamp: 1_210_103_000, // in ms, 500 s after Jan 1 1970 + 3 seconds (chosen block time in test) + serialized_vote_polls: vec![ + serialized_contested_vote_poll_bytes_2.clone() + ] + }, + SerializedVotePollsByTimestamp { + timestamp: 1_210_503_000, // in ms, 900 s after Jan 1 1970 + 3 seconds (chosen block time in test) + serialized_vote_polls: vec![ + serialized_contested_vote_poll_bytes_3.clone() + ] + }, + ] + ); + } - assert!(finished_results); + // descending order + { + let GetVotePollsByEndDateResponse { version } = platform + .query_vote_polls_by_end_date_query( + GetVotePollsByEndDateRequest { + version: Some(get_vote_polls_by_end_date_request::Version::V0( + GetVotePollsByEndDateRequestV0 { + start_time_info: Some( + get_vote_polls_by_end_date_request_v0::StartAtTimeInfo { + start_time_ms: 1_209_603_000, + start_time_included: false, + }, + ), + end_time_info: None, + limit: None, + offset: None, + ascending: false, + prove: false, + }, + )), + }, + &platform_state, + platform_version, + ) + .expect("expected to execute query") + .into_data() + .expect("expected query to be valid"); - let serialized_contested_vote_poll_bytes_2 = vec![ - 0, 230, 104, 198, 89, 175, 102, 174, 225, 231, 44, 24, 109, 222, 123, 91, 126, - 10, 29, 113, 42, 9, 196, 13, 87, 33, 246, 34, 191, 83, 197, 49, 85, 6, 100, - 111, 109, 97, 105, 110, 18, 112, 97, 114, 101, 110, 116, 78, 97, 109, 101, 65, - 110, 100, 76, 97, 98, 101, 108, 2, 18, 4, 100, 97, 115, 104, 18, 6, 99, 48, 48, - 49, 49, 48, - ]; + let get_vote_polls_by_end_date_response::Version::V0( + GetVotePollsByEndDateResponseV0 { + metadata: _, + result, + }, + ) = version.expect("expected a version"); + + let Some(get_vote_polls_by_end_date_response_v0::Result::VotePollsByTimestamps( + get_vote_polls_by_end_date_response_v0::SerializedVotePollsByTimestamps { + vote_polls_by_timestamps, + finished_results, + }, + )) = result + else { + panic!("expected contenders") + }; - let serialized_contested_vote_poll_bytes_3 = vec![ - 0, 230, 104, 198, 89, 175, 102, 174, 225, 231, 44, 24, 109, 222, 123, 91, 126, - 10, 29, 113, 42, 9, 196, 13, 87, 33, 246, 34, 191, 83, 197, 49, 85, 6, 100, - 111, 109, 97, 105, 110, 18, 112, 97, 114, 101, 110, 116, 78, 97, 109, 101, 65, - 110, 100, 76, 97, 98, 101, 108, 2, 18, 4, 100, 97, 115, 104, 18, 8, 99, 114, - 97, 122, 121, 109, 97, 110, - ]; + assert!(finished_results); - assert_eq!( - vote_polls_by_timestamps, - vec![ - SerializedVotePollsByTimestamp { - timestamp: 1_210_103_000, // in ms, 500 s after Jan 1 1970 + 3 seconds (chosen block time in test) - serialized_vote_polls: vec![ - serialized_contested_vote_poll_bytes_2.clone() - ] - }, - SerializedVotePollsByTimestamp { - timestamp: 1_210_503_000, // in ms, 900 s after Jan 1 1970 + 3 seconds (chosen block time in test) - serialized_vote_polls: vec![ - serialized_contested_vote_poll_bytes_3.clone() - ] - }, - ] - ); + let serialized_contested_vote_poll_bytes_2 = vec![ + 0, 230, 104, 198, 89, 175, 102, 174, 225, 231, 44, 24, 109, 222, 123, 91, + 126, 10, 29, 113, 42, 9, 196, 13, 87, 33, 246, 34, 191, 83, 197, 49, 85, 6, + 100, 111, 109, 97, 105, 110, 18, 112, 97, 114, 101, 110, 116, 78, 97, 109, + 101, 65, 110, 100, 76, 97, 98, 101, 108, 2, 18, 4, 100, 97, 115, 104, 18, + 6, 99, 48, 48, 49, 49, 48, + ]; + + let serialized_contested_vote_poll_bytes_3 = vec![ + 0, 230, 104, 198, 89, 175, 102, 174, 225, 231, 44, 24, 109, 222, 123, 91, + 126, 10, 29, 113, 42, 9, 196, 13, 87, 33, 246, 34, 191, 83, 197, 49, 85, 6, + 100, 111, 109, 97, 105, 110, 18, 112, 97, 114, 101, 110, 116, 78, 97, 109, + 101, 65, 110, 100, 76, 97, 98, 101, 108, 2, 18, 4, 100, 97, 115, 104, 18, + 8, 99, 114, 97, 122, 121, 109, 97, 110, + ]; + + assert_eq!( + vote_polls_by_timestamps, + vec![ + SerializedVotePollsByTimestamp { + timestamp: 1_210_503_000, // in ms, 900 s after Jan 1 1970 + 3 seconds (chosen block time in test) + serialized_vote_polls: vec![ + serialized_contested_vote_poll_bytes_3.clone() + ] + }, + SerializedVotePollsByTimestamp { + timestamp: 1_210_103_000, // in ms, 500 s after Jan 1 1970 + 3 seconds (chosen block time in test) + serialized_vote_polls: vec![ + serialized_contested_vote_poll_bytes_2.clone() + ] + }, + ] + ); + } } #[test] @@ -4019,95 +4727,191 @@ mod tests { platform_version, ); - let GetVotePollsByEndDateResponse { version } = platform - .query_vote_polls_by_end_date_query( - GetVotePollsByEndDateRequest { - version: Some(get_vote_polls_by_end_date_request::Version::V0( - GetVotePollsByEndDateRequestV0 { - start_time_info: None, - end_time_info: None, - limit: None, - offset: None, - ascending: true, - prove: true, - }, - )), + // ascending order + { + let GetVotePollsByEndDateResponse { version } = platform + .query_vote_polls_by_end_date_query( + GetVotePollsByEndDateRequest { + version: Some(get_vote_polls_by_end_date_request::Version::V0( + GetVotePollsByEndDateRequestV0 { + start_time_info: None, + end_time_info: None, + limit: None, + offset: None, + ascending: true, + prove: true, + }, + )), + }, + &platform_state, + platform_version, + ) + .expect("expected to execute query") + .into_data() + .expect("expected query to be valid"); + + let get_vote_polls_by_end_date_response::Version::V0( + GetVotePollsByEndDateResponseV0 { + metadata: _, + result, }, - &platform_state, - platform_version, - ) - .expect("expected to execute query") - .into_data() - .expect("expected query to be valid"); + ) = version.expect("expected a version"); - let get_vote_polls_by_end_date_response::Version::V0( - GetVotePollsByEndDateResponseV0 { - metadata: _, - result, - }, - ) = version.expect("expected a version"); + let Some(get_vote_polls_by_end_date_response_v0::Result::Proof(proof)) = result + else { + panic!("expected contenders") + }; - let Some(get_vote_polls_by_end_date_response_v0::Result::Proof(proof)) = result - else { - panic!("expected contenders") - }; + let vote_poll_by_end_date_query = VotePollsByEndDateDriveQuery { + start_time: None, + end_time: None, + offset: None, + limit: None, + order_ascending: true, + }; - let vote_poll_by_end_date_query = VotePollsByEndDateDriveQuery { - start_time: None, - end_time: None, - offset: None, - limit: None, - order_ascending: true, - }; + let (_, vote_polls_by_timestamps) = vote_poll_by_end_date_query + .verify_vote_polls_by_end_date_proof( + proof.grovedb_proof.as_ref(), + platform_version, + ) + .expect("expected to verify proof"); - let (_, vote_polls_by_timestamps) = vote_poll_by_end_date_query - .verify_vote_polls_by_end_date_proof( - proof.grovedb_proof.as_ref(), - platform_version, - ) - .expect("expected to verify proof"); + assert_eq!( + vote_polls_by_timestamps, + BTreeMap::from([ + ( + 1_209_603_000, + vec![VotePoll::ContestedDocumentResourceVotePoll( + ContestedDocumentResourceVotePoll { + contract_id: Identifier(IdentifierBytes32([ + 230, 104, 198, 89, 175, 102, 174, 225, 231, 44, 24, + 109, 222, 123, 91, 126, 10, 29, 113, 42, 9, 196, 13, + 87, 33, 246, 34, 191, 83, 197, 49, 85 + ])), + document_type_name: "domain".to_string(), + index_name: "parentNameAndLabel".to_string(), + index_values: vec![ + Text("dash".to_string()), + Text("quantum".to_string()) + ] + } + )] + ), + ( + 1_210_103_000, + vec![VotePoll::ContestedDocumentResourceVotePoll( + ContestedDocumentResourceVotePoll { + contract_id: Identifier(IdentifierBytes32([ + 230, 104, 198, 89, 175, 102, 174, 225, 231, 44, 24, + 109, 222, 123, 91, 126, 10, 29, 113, 42, 9, 196, 13, + 87, 33, 246, 34, 191, 83, 197, 49, 85 + ])), + document_type_name: "domain".to_string(), + index_name: "parentNameAndLabel".to_string(), + index_values: vec![ + Text("dash".to_string()), + Text("c00110".to_string()) + ] + } + )] + ) + ]) + ); + } - assert_eq!( - vote_polls_by_timestamps, - BTreeMap::from([ - ( - 1_209_603_000, - vec![VotePoll::ContestedDocumentResourceVotePoll( - ContestedDocumentResourceVotePoll { - contract_id: Identifier(IdentifierBytes32([ - 230, 104, 198, 89, 175, 102, 174, 225, 231, 44, 24, 109, - 222, 123, 91, 126, 10, 29, 113, 42, 9, 196, 13, 87, 33, - 246, 34, 191, 83, 197, 49, 85 - ])), - document_type_name: "domain".to_string(), - index_name: "parentNameAndLabel".to_string(), - index_values: vec![ - Text("dash".to_string()), - Text("quantum".to_string()) - ] - } - )] - ), - ( - 1_210_103_000, - vec![VotePoll::ContestedDocumentResourceVotePoll( - ContestedDocumentResourceVotePoll { - contract_id: Identifier(IdentifierBytes32([ - 230, 104, 198, 89, 175, 102, 174, 225, 231, 44, 24, 109, - 222, 123, 91, 126, 10, 29, 113, 42, 9, 196, 13, 87, 33, - 246, 34, 191, 83, 197, 49, 85 - ])), - document_type_name: "domain".to_string(), - index_name: "parentNameAndLabel".to_string(), - index_values: vec![ - Text("dash".to_string()), - Text("c00110".to_string()) - ] - } - )] + // descending order + { + let GetVotePollsByEndDateResponse { version } = platform + .query_vote_polls_by_end_date_query( + GetVotePollsByEndDateRequest { + version: Some(get_vote_polls_by_end_date_request::Version::V0( + GetVotePollsByEndDateRequestV0 { + start_time_info: None, + end_time_info: None, + limit: None, + offset: None, + ascending: false, + prove: true, + }, + )), + }, + &platform_state, + platform_version, ) - ]) - ); + .expect("expected to execute query") + .into_data() + .expect("expected query to be valid"); + + let get_vote_polls_by_end_date_response::Version::V0( + GetVotePollsByEndDateResponseV0 { + metadata: _, + result, + }, + ) = version.expect("expected a version"); + + let Some(get_vote_polls_by_end_date_response_v0::Result::Proof(proof)) = result + else { + panic!("expected contenders") + }; + + let vote_poll_by_end_date_query = VotePollsByEndDateDriveQuery { + start_time: None, + end_time: None, + offset: None, + limit: None, + order_ascending: false, + }; + + let (_, vote_polls_by_timestamps) = vote_poll_by_end_date_query + .verify_vote_polls_by_end_date_proof( + proof.grovedb_proof.as_ref(), + platform_version, + ) + .expect("expected to verify proof"); + + assert_eq!( + vote_polls_by_timestamps, + BTreeMap::from([ + ( + 1_209_603_000, + vec![VotePoll::ContestedDocumentResourceVotePoll( + ContestedDocumentResourceVotePoll { + contract_id: Identifier(IdentifierBytes32([ + 230, 104, 198, 89, 175, 102, 174, 225, 231, 44, 24, + 109, 222, 123, 91, 126, 10, 29, 113, 42, 9, 196, 13, + 87, 33, 246, 34, 191, 83, 197, 49, 85 + ])), + document_type_name: "domain".to_string(), + index_name: "parentNameAndLabel".to_string(), + index_values: vec![ + Text("dash".to_string()), + Text("quantum".to_string()) + ] + } + )] + ), + ( + 1_210_103_000, + vec![VotePoll::ContestedDocumentResourceVotePoll( + ContestedDocumentResourceVotePoll { + contract_id: Identifier(IdentifierBytes32([ + 230, 104, 198, 89, 175, 102, 174, 225, 231, 44, 24, + 109, 222, 123, 91, 126, 10, 29, 113, 42, 9, 196, 13, + 87, 33, 246, 34, 191, 83, 197, 49, 85 + ])), + document_type_name: "domain".to_string(), + index_name: "parentNameAndLabel".to_string(), + index_values: vec![ + Text("dash".to_string()), + Text("c00110".to_string()) + ] + } + )] + ) + ]) + ); + } } } diff --git a/packages/rs-drive-abci/src/query/voting/contested_resource_vote_state/v0/mod.rs b/packages/rs-drive-abci/src/query/voting/contested_resource_vote_state/v0/mod.rs index 4091e56e006..c61800dd49a 100644 --- a/packages/rs-drive-abci/src/query/voting/contested_resource_vote_state/v0/mod.rs +++ b/packages/rs-drive-abci/src/query/voting/contested_resource_vote_state/v0/mod.rs @@ -85,6 +85,13 @@ impl Platform { )))); } + if index.properties.len() != index_values.len() { + return Ok(QueryValidationResult::new_with_error(QueryError::InvalidArgument(format!( + "query uses index {}, this index has {} properties, but the query provided {} index values instead", + index_name, index.properties.len(), index_values.len() + )))); + } + let bincode_config = bincode::config::standard() .with_big_endian() .with_no_limit(); @@ -117,20 +124,21 @@ impl Platform { index_values, }; - let limit = count - .map_or(Some(config.default_query_limit), |limit_value| { - if limit_value == 0 - || limit_value > u16::MAX as u32 - || limit_value as u16 > config.default_query_limit - { - None + let limit = check_validation_result_with_data!(count.map_or( + Ok(config.default_query_limit), + |limit| { + let limit = u16::try_from(limit) + .map_err(|_| QueryError::InvalidArgument("limit out of bounds".to_string()))?; + if limit == 0 || limit > config.default_query_limit { + Err(QueryError::InvalidArgument(format!( + "limit {} out of bounds of [1, {}]", + limit, config.default_query_limit + ))) } else { - Some(limit_value as u16) + Ok(limit) } - }) - .ok_or(drive::error::Error::Query(QuerySyntaxError::InvalidLimit( - format!("limit greater than max limit {}", config.max_query_limit), - )))?; + } + )); let query = ContestedDocumentVotePollDriveQuery { vote_poll, diff --git a/packages/rs-drive-abci/src/query/voting/contested_resource_voters_for_identity/v0/mod.rs b/packages/rs-drive-abci/src/query/voting/contested_resource_voters_for_identity/v0/mod.rs index 2df1abc67c5..b1f36702659 100644 --- a/packages/rs-drive-abci/src/query/voting/contested_resource_voters_for_identity/v0/mod.rs +++ b/packages/rs-drive-abci/src/query/voting/contested_resource_voters_for_identity/v0/mod.rs @@ -118,20 +118,21 @@ impl Platform { index_values, }; - let limit = count - .map_or(Some(config.default_query_limit), |limit_value| { - if limit_value == 0 - || limit_value > u16::MAX as u32 - || limit_value as u16 > config.default_query_limit - { - None + let limit = check_validation_result_with_data!(count.map_or( + Ok(config.default_query_limit), + |limit| { + let limit = u16::try_from(limit) + .map_err(|_| QueryError::InvalidArgument("limit out of bounds".to_string()))?; + if limit == 0 || limit > config.default_query_limit { + Err(QueryError::InvalidArgument(format!( + "limit {} out of bounds of [1, {}]", + limit, config.default_query_limit + ))) } else { - Some(limit_value as u16) + Ok(limit) } - }) - .ok_or(drive::error::Error::Query(QuerySyntaxError::InvalidLimit( - format!("limit greater than max limit {}", config.max_query_limit), - )))?; + } + )); let response = if prove { let query = ContestedDocumentVotePollVotesDriveQuery { diff --git a/packages/rs-drive-abci/src/query/voting/contested_resources/v0/mod.rs b/packages/rs-drive-abci/src/query/voting/contested_resources/v0/mod.rs index 48315a868a4..d61cfb24e7a 100644 --- a/packages/rs-drive-abci/src/query/voting/contested_resources/v0/mod.rs +++ b/packages/rs-drive-abci/src/query/voting/contested_resources/v0/mod.rs @@ -127,20 +127,21 @@ impl Platform { Err(e) => return Ok(QueryValidationResult::new_with_error(e)), }; - let limit = count - .map_or(Some(config.default_query_limit), |limit_value| { - if limit_value == 0 - || limit_value > u16::MAX as u32 - || limit_value as u16 > config.default_query_limit - { - None + let limit = check_validation_result_with_data!(count.map_or( + Ok(config.default_query_limit), + |limit| { + let limit = u16::try_from(limit) + .map_err(|_| QueryError::InvalidArgument("limit out of bounds".to_string()))?; + if limit == 0 || limit > config.default_query_limit { + Err(QueryError::InvalidArgument(format!( + "limit {} out of bounds of [1, {}]", + limit, config.default_query_limit + ))) } else { - Some(limit_value as u16) + Ok(limit) } - }) - .ok_or(drive::error::Error::Query(QuerySyntaxError::InvalidLimit( - format!("limit greater than max limit {}", config.max_query_limit), - )))?; + } + )); let result = start_at_value_info .map(|start_at_value_info| { diff --git a/packages/rs-drive/src/error/query.rs b/packages/rs-drive/src/error/query.rs index f51c776f100..1166638edb4 100644 --- a/packages/rs-drive/src/error/query.rs +++ b/packages/rs-drive/src/error/query.rs @@ -142,6 +142,6 @@ pub enum QuerySyntaxError { UnknownIndex(String), /// Missing index values for query - #[error("missing index values error: {0}")] + #[error("incorrect index values error: {0}")] IndexValuesError(String), } diff --git a/packages/rs-drive/src/query/vote_polls_by_document_type_query.rs b/packages/rs-drive/src/query/vote_polls_by_document_type_query.rs index 104f954b977..c657d7acc2a 100644 --- a/packages/rs-drive/src/query/vote_polls_by_document_type_query.rs +++ b/packages/rs-drive/src/query/vote_polls_by_document_type_query.rs @@ -298,6 +298,7 @@ impl<'a> ResolvedVotePollsByDocumentTypeQuery<'a> { let document_type = self.document_type()?; let properties_iter = index.properties.iter(); let mut start_values_iter = self.start_index_values.iter(); + let has_end_index_values = !self.end_index_values.is_empty(); let mut end_values_iter = self.end_index_values.iter(); let mut start_values_vec = vec![]; let mut end_values_vec = vec![]; @@ -327,7 +328,14 @@ impl<'a> ResolvedVotePollsByDocumentTypeQuery<'a> { break; } } - let middle_index_property = middle_index_property.ok_or(Error::Query(QuerySyntaxError::IndexValuesError("the start index values and the end index values must be equal to the amount of properties in the contested index minus one, no middle property".to_string())))?; + let middle_index_property = middle_index_property.ok_or_else(|| { + let error_msg = if has_end_index_values { + "since end index values were provided, the start index values and the end index values must be equal to the amount of properties in the contested index minus one, we could not find a middle property".to_string() + } else { + "too many start values were provided, since no end index values were provided, the start index values must be less than the amount of properties in the contested index".to_string() + }; + Error::Query(QuerySyntaxError::IndexValuesError(error_msg)) + })?; Ok((start_values_vec, end_values_vec, middle_index_property)) } @@ -352,13 +360,14 @@ impl<'a> ResolvedVotePollsByDocumentTypeQuery<'a> { } pub(crate) fn result_path_index(&self) -> usize { - // 5 because of: + // 6 because of: // voting sub tree (112) // contested ('c') // voting part // contract id // document type name - 5 + self.start_index_values.len() + // 1 + 6 + self.start_index_values.len() } /// Operations to construct a path query. @@ -491,7 +500,7 @@ impl<'a> ResolvedVotePollsByDocumentTypeQuery<'a> { Err(Error::Drive(DriveError::CorruptedCodeExecution("the path length should always be bigger or equal to the result path index"))) } else { - // the result is in the path because we did not provide any end index values + // the result is in the path because we did provide end index values // like this <------ start index values (path) ---> Key // properties ------- --------- --------- ---------- ------- let inner_path_value_bytes = path.remove(result_path_index.unwrap()); diff --git a/packages/rs-sdk/tests/fetch/contested_resource.rs b/packages/rs-sdk/tests/fetch/contested_resource.rs index 3d8aeda42b6..f21257cef66 100644 --- a/packages/rs-sdk/tests/fetch/contested_resource.rs +++ b/packages/rs-sdk/tests/fetch/contested_resource.rs @@ -304,7 +304,7 @@ async fn contested_resources_fields() { ] }, expect: Ok( - r#"code: InvalidArgument, message: "missing index values error: the start index values and the end index"#, + r#"code: InvalidArgument, message: "incorrect index values error: the start index values and the end index"#, ), }, TestCase { diff --git a/packages/rs-sdk/tests/fetch/contested_resource_vote_state.rs b/packages/rs-sdk/tests/fetch/contested_resource_vote_state.rs index e1d4e2e8185..6d056a38d7a 100644 --- a/packages/rs-sdk/tests/fetch/contested_resource_vote_state.rs +++ b/packages/rs-sdk/tests/fetch/contested_resource_vote_state.rs @@ -352,7 +352,7 @@ async fn contested_resource_vote_states_fields() { ] }, expect: Ok( - r#"code: InvalidArgument, message: "missing index values error: the start index values and the end index"#, + r#"code: InvalidArgument, message: "incorrect index values error: the start index values and the end index"#, ), }, TestCase { From d5beaf08eb98cae0995e8c316b05450f77210b52 Mon Sep 17 00:00:00 2001 From: Lukasz Klimek <842586+lklimek@users.noreply.github.com> Date: Mon, 24 Jun 2024 21:09:10 +0200 Subject: [PATCH 14/55] test(sdk): minor renames --- .../fetch/contested_resource_vote_state.rs | 27 ++++++++++++------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/packages/rs-sdk/tests/fetch/contested_resource_vote_state.rs b/packages/rs-sdk/tests/fetch/contested_resource_vote_state.rs index e1d4e2e8185..dfb6c8e97c5 100644 --- a/packages/rs-sdk/tests/fetch/contested_resource_vote_state.rs +++ b/packages/rs-sdk/tests/fetch/contested_resource_vote_state.rs @@ -45,7 +45,6 @@ async fn contested_resource_vote_states_not_found() { contract_id: data_contract_id, }, allow_include_locked_and_abstaining_vote_tally: true, - // TODO test other result types result_type: ContestedDocumentVotePollDriveQueryResultType::DocumentsAndVoteTally, }; @@ -318,22 +317,22 @@ async fn contested_resource_vote_states_fields() { }, TestCase { // todo maybe this should fail? or return everything? - name: "index_values empty vec returns zero results PLAN-665", + name: "index_values empty vec returns error PLAN-665", query_mut_fn: |q| q.vote_poll.index_values = vec![], - expect: Ok(r#"Contenders { contenders: {},"#), + expect: Ok(r#"TODO error"#), }, TestCase { - name: "index_values empty string returns zero results", + name: "index_values empty string returns error PLAN-665", query_mut_fn: |q| q.vote_poll.index_values = vec![Value::Text("".to_string())], - expect: Ok("contenders: {}"), + expect: Ok("TODO error"), }, TestCase { - name: "index_values with one value returns results PLAN-665", + name: "index_values with one value returns error PLAN-665", query_mut_fn: |q| q.vote_poll.index_values = vec![Value::Text("dash".to_string())], - expect: Ok("contenders: {...}"), + expect: Ok("TODO error"), }, TestCase { - name: "index_values with two values returns contenders ", + name: "index_values with two values returns contenders", query_mut_fn: |q| { q.vote_poll.index_values = vec![ Value::Text("dash".to_string()), @@ -422,7 +421,11 @@ async fn contested_resource_vote_states_fields() { let mut failures: Vec<(&'static str, String)> = Default::default(); for test_case in test_cases { - tracing::debug!("Running test case: {}", test_case.name); + tracing::debug!( + test_case = test_case.name, + "Running test case: {}", + test_case.name + ); // create new sdk to ensure that test cases don't interfere with each other let sdk = cfg .setup_api(&format!( @@ -435,6 +438,12 @@ async fn contested_resource_vote_states_fields() { (test_case.query_mut_fn)(&mut query); let result = ContenderWithSerializedDocument::fetch_many(&sdk, query).await; + tracing::debug!( + test_case = test_case.name, + ?result, + "Result of test case {}", + test_case.name + ); match test_case.expect { Ok(expected) if result.is_ok() => { let result_string = format!("{:?}", result.as_ref().expect("result")); From 4784dc3a18eb1bbfffa867443cc45d171f72f955 Mon Sep 17 00:00:00 2001 From: Quantum Explorer Date: Tue, 25 Jun 2024 01:43:24 +0300 Subject: [PATCH 15/55] fix: masternode vote fixes --- Cargo.lock | 413 ++++-------------- packages/rs-dpp/src/errors/consensus/codes.rs | 2 + .../src/errors/consensus/state/state_error.rs | 8 + ...rnode_incorrect_voter_identity_id_error.rs | 57 +++ ...sternode_incorrect_voting_address_error.rs | 57 +++ .../voting/masternode_not_found_error.rs | 2 +- .../src/errors/consensus/state/voting/mod.rs | 2 + packages/rs-dpp/src/identifier/mod.rs | 30 ++ .../identity_public_key/methods/hash/mod.rs | 4 +- .../methods/hash/v0/mod.rs | 2 +- .../identity_public_key/v0/methods/mod.rs | 2 +- .../methods/create_basic_identity/mod.rs | 3 +- .../methods/create_basic_identity/v0/mod.rs | 4 +- .../accessors/mod.rs | 22 +- .../accessors/v0/mod.rs | 2 + .../masternode_vote_transition/v0/mod.rs | 2 + .../v0/state_transition_like.rs | 5 +- .../v0/v0_methods.rs | 11 +- .../methods/hash/v0/mod.rs | 2 +- .../create_owner_identity/v0/mod.rs | 5 +- .../create_voter_identity/v0/mod.rs | 5 +- .../disable_identity_keys/v0/mod.rs | 8 +- .../get_operator_identifier/mod.rs | 12 +- .../get_operator_identifier/v0/mod.rs | 20 +- .../get_voter_identifier/mod.rs | 46 +- .../get_voter_identifier/v0/mod.rs | 18 +- .../hash_protxhash_with_key_data/mod.rs | 46 -- .../hash_protxhash_with_key_data/v0/mod.rs | 20 - .../update_masternode_identities/mod.rs | 1 - .../update_operator_identity/v0/mod.rs | 8 +- .../update_voter_identity/v0/mod.rs | 6 +- .../types/execution_operation/mod.rs | 13 + .../state_transition/processor/v0/mod.rs | 14 +- .../masternode_vote/advanced_structure/mod.rs | 66 +++ .../advanced_structure/v0/mod.rs | 76 ++++ .../state_transitions/masternode_vote/mod.rs | 123 +++--- .../masternode_vote/state/v0/mod.rs | 23 +- .../masternode_vote/structure/mod.rs | 1 - .../masternode_vote/structure/v0/mod.rs | 17 - .../transform_into_action/v0/mod.rs | 2 + .../state_transition/state_transitions/mod.rs | 36 +- .../tests/strategy_tests/query.rs | 2 +- .../identity/masternode_vote_transition.rs | 4 +- .../contract/prove/prove_contracts/v0/mod.rs | 1 + .../mod.rs | 2 + .../v0/mod.rs | 11 +- .../v0/mod.rs | 1 + .../fetch/fetch_by_public_key_hashes/mod.rs | 2 +- .../v0/mod.rs | 8 +- .../v0/mod.rs | 2 +- .../v0/mod.rs | 2 +- .../v0/mod.rs | 4 +- .../key/fetch/fetch_identity_keys/v0/mod.rs | 1 + .../v0/mod.rs | 2 +- .../insert_reference_to_unique_key/v0/mod.rs | 2 +- .../identity/masternode_vote/mod.rs | 14 + .../identity/masternode_vote/transformer.rs | 7 + .../identity/masternode_vote/v0/mod.rs | 4 + .../masternode_vote/v0/transformer.rs | 10 + .../rs-platform-value/src/types/bytes_20.rs | 7 +- .../src/version/drive_abci_versions.rs | 5 +- .../src/version/mocks/v2_test.rs | 9 +- .../src/version/mocks/v3_test.rs | 9 +- .../rs-platform-version/src/version/v1.rs | 9 +- packages/rs-sdk/tests/fetch/identity.rs | 2 +- .../src/errors/consensus/consensus_error.rs | 4 + .../src/identity/identity_public_key/mod.rs | 5 +- 67 files changed, 678 insertions(+), 647 deletions(-) create mode 100644 packages/rs-dpp/src/errors/consensus/state/voting/masternode_incorrect_voter_identity_id_error.rs create mode 100644 packages/rs-dpp/src/errors/consensus/state/voting/masternode_incorrect_voting_address_error.rs delete mode 100644 packages/rs-drive-abci/src/execution/platform_events/core_based_updates/update_masternode_identities/hash_protxhash_with_key_data/mod.rs delete mode 100644 packages/rs-drive-abci/src/execution/platform_events/core_based_updates/update_masternode_identities/hash_protxhash_with_key_data/v0/mod.rs create mode 100644 packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/masternode_vote/advanced_structure/mod.rs create mode 100644 packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/masternode_vote/advanced_structure/v0/mod.rs delete mode 100644 packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/masternode_vote/structure/mod.rs delete mode 100644 packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/masternode_vote/structure/v0/mod.rs diff --git a/Cargo.lock b/Cargo.lock index 9f6c164398b..305a05017f5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -211,7 +211,7 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -222,7 +222,7 @@ checksum = "c6fa2087f2753a7da8cc1c0dbfcf89579dd57458e36769de5ac750b4671737ca" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -397,7 +397,7 @@ dependencies = [ "regex", "rustc-hash", "shlex", - "syn 2.0.66", + "syn 2.0.68", "which", ] @@ -418,7 +418,7 @@ dependencies = [ "regex", "rustc-hash", "shlex", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -548,7 +548,7 @@ dependencies = [ "proc-macro-crate 3.1.0", "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", "syn_derive", ] @@ -731,9 +731,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.0.99" +version = "1.0.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96c51067fd44124faa7f870b4b1c969379ad32b2ba805aa959430ceaa384f695" +checksum = "c891175c3fb232128f48de6590095e59198bbeb8620c310be349bfc3afd12c7b" dependencies = [ "jobserver", "libc", @@ -860,7 +860,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -1217,16 +1217,15 @@ dependencies = [ [[package]] name = "curve25519-dalek" -version = "4.1.2" +version = "4.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a677b8922c94e01bdbb12126b0bc852f00447528dee1782229af9c720c3f348" +checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be" dependencies = [ "cfg-if", "cpufeatures", "curve25519-dalek-derive", "digest", "fiat-crypto", - "platforms", "rustc_version", "subtle", "zeroize", @@ -1240,7 +1239,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -1266,7 +1265,7 @@ dependencies = [ "dapi-grpc", "heck 0.5.0", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -1290,7 +1289,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -1301,7 +1300,7 @@ checksum = "733cabb43482b1a1b53eee8583c2b9e8684d592215ea83efd305dd31bc2f0178" dependencies = [ "darling_core", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -1469,7 +1468,7 @@ dependencies = [ "proc-macro2", "quote", "rustc_version", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -1525,17 +1524,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "displaydoc" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.66", -] - [[package]] name = "dotenvy" version = "0.15.7" @@ -1791,7 +1779,7 @@ checksum = "f282cfdfe92516eb26c2af8589c274c7c17681f5ecc03c18255fe741c6aa64eb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -1879,7 +1867,7 @@ dependencies = [ "proc-macro2", "quote", "syn 1.0.109", - "synstructure 0.12.6", + "synstructure", ] [[package]] @@ -2125,7 +2113,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -2207,7 +2195,7 @@ checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" [[package]] name = "grovedb" version = "1.0.0-rc.2" -source = "git+https://github.com/dashpay/grovedb?branch=feat/QuerySumTree#0b32606fd4983899ca2b5865299f04b1a0accc98" +source = "git+https://github.com/dashpay/grovedb?branch=feat/QuerySumTree#8664b723330cc3850edbebd5f336b982f29ed23c" dependencies = [ "bincode 2.0.0-rc.3", "bitvec", @@ -2230,7 +2218,7 @@ dependencies = [ [[package]] name = "grovedb-costs" version = "1.0.0-rc.2" -source = "git+https://github.com/dashpay/grovedb?branch=feat/QuerySumTree#0b32606fd4983899ca2b5865299f04b1a0accc98" +source = "git+https://github.com/dashpay/grovedb?branch=feat/QuerySumTree#8664b723330cc3850edbebd5f336b982f29ed23c" dependencies = [ "integer-encoding", "intmap", @@ -2240,7 +2228,7 @@ dependencies = [ [[package]] name = "grovedb-merk" version = "1.0.0-rc.2" -source = "git+https://github.com/dashpay/grovedb?branch=feat/QuerySumTree#0b32606fd4983899ca2b5865299f04b1a0accc98" +source = "git+https://github.com/dashpay/grovedb?branch=feat/QuerySumTree#8664b723330cc3850edbebd5f336b982f29ed23c" dependencies = [ "blake3", "byteorder", @@ -2263,12 +2251,12 @@ dependencies = [ [[package]] name = "grovedb-path" version = "1.0.0-rc.2" -source = "git+https://github.com/dashpay/grovedb?branch=feat/QuerySumTree#0b32606fd4983899ca2b5865299f04b1a0accc98" +source = "git+https://github.com/dashpay/grovedb?branch=feat/QuerySumTree#8664b723330cc3850edbebd5f336b982f29ed23c" [[package]] name = "grovedb-storage" version = "1.0.0-rc.2" -source = "git+https://github.com/dashpay/grovedb?branch=feat/QuerySumTree#0b32606fd4983899ca2b5865299f04b1a0accc98" +source = "git+https://github.com/dashpay/grovedb?branch=feat/QuerySumTree#8664b723330cc3850edbebd5f336b982f29ed23c" dependencies = [ "blake3", "grovedb-costs", @@ -2279,7 +2267,7 @@ dependencies = [ "lazy_static", "num_cpus", "rocksdb", - "strum 0.26.2", + "strum 0.26.3", "tempfile", "thiserror", ] @@ -2287,7 +2275,7 @@ dependencies = [ [[package]] name = "grovedb-visualize" version = "1.0.0-rc.2" -source = "git+https://github.com/dashpay/grovedb?branch=feat/QuerySumTree#0b32606fd4983899ca2b5865299f04b1a0accc98" +source = "git+https://github.com/dashpay/grovedb?branch=feat/QuerySumTree#8664b723330cc3850edbebd5f336b982f29ed23c" dependencies = [ "hex", "itertools 0.12.1", @@ -2619,124 +2607,6 @@ dependencies = [ "cc", ] -[[package]] -name = "icu_collections" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" -dependencies = [ - "displaydoc", - "yoke", - "zerofrom", - "zerovec", -] - -[[package]] -name = "icu_locid" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" -dependencies = [ - "displaydoc", - "litemap", - "tinystr", - "writeable", - "zerovec", -] - -[[package]] -name = "icu_locid_transform" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" -dependencies = [ - "displaydoc", - "icu_locid", - "icu_locid_transform_data", - "icu_provider", - "tinystr", - "zerovec", -] - -[[package]] -name = "icu_locid_transform_data" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e" - -[[package]] -name = "icu_normalizer" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" -dependencies = [ - "displaydoc", - "icu_collections", - "icu_normalizer_data", - "icu_properties", - "icu_provider", - "smallvec", - "utf16_iter", - "utf8_iter", - "write16", - "zerovec", -] - -[[package]] -name = "icu_normalizer_data" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516" - -[[package]] -name = "icu_properties" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f8ac670d7422d7f76b32e17a5db556510825b29ec9154f235977c9caba61036" -dependencies = [ - "displaydoc", - "icu_collections", - "icu_locid_transform", - "icu_properties_data", - "icu_provider", - "tinystr", - "zerovec", -] - -[[package]] -name = "icu_properties_data" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569" - -[[package]] -name = "icu_provider" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" -dependencies = [ - "displaydoc", - "icu_locid", - "icu_provider_macros", - "stable_deref_trait", - "tinystr", - "writeable", - "yoke", - "zerofrom", - "zerovec", -] - -[[package]] -name = "icu_provider_macros" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.66", -] - [[package]] name = "ident_case" version = "1.0.1" @@ -2745,14 +2615,12 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" [[package]] name = "idna" -version = "1.0.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4716a3a0933a1d01c2f72450e89596eb51dd34ef3c211ccd875acdf1f8fe47ed" +checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" dependencies = [ - "icu_normalizer", - "icu_properties", - "smallvec", - "utf8_iter", + "unicode-bidi", + "unicode-normalization", ] [[package]] @@ -2995,9 +2863,9 @@ dependencies = [ [[package]] name = "lazy_static" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "lazycell" @@ -3025,9 +2893,9 @@ checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" [[package]] name = "libloading" -version = "0.8.3" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19" +checksum = "e310b3a6b5907f99202fcdb4960ff45b93735d7c7d96b760fcff8db2dc0e103d" dependencies = [ "cfg-if", "windows-targets 0.52.5", @@ -3082,12 +2950,6 @@ version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" -[[package]] -name = "litemap" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "643cb0b8d4fcc284004d5fd0d67ccf61dfffadb7f75e1e71bc420f4688a3a704" - [[package]] name = "lock_api" version = "0.4.12" @@ -3446,7 +3308,7 @@ checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -3576,7 +3438,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -3677,7 +3539,7 @@ checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -3722,7 +3584,7 @@ version = "1.0.0-dev.15" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", "virtue 0.0.14", ] @@ -3752,7 +3614,7 @@ name = "platform-value-convertible" version = "1.0.0-dev.15" dependencies = [ "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -3768,15 +3630,9 @@ version = "1.0.0-dev.15" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] -[[package]] -name = "platforms" -version = "3.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db23d408679286588f4d4644f965003d056e3dd5abcaaa938116871d7ce2fee7" - [[package]] name = "plotters" version = "0.3.6" @@ -3902,7 +3758,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f12335488a2f3b0a83b14edad48dca9879ce89b2edd10e80237e4e852dd645e" dependencies = [ "proc-macro2", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -3950,9 +3806,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.85" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22244ce15aa966053a896d1accb3a6e68469b97c7f33f284b99f0d576879fc23" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" dependencies = [ "unicode-ident", ] @@ -4016,7 +3872,7 @@ dependencies = [ "prost 0.12.6", "prost-types 0.12.6", "regex", - "syn 2.0.66", + "syn 2.0.68", "tempfile", ] @@ -4043,7 +3899,7 @@ dependencies = [ "itertools 0.12.1", "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -4685,7 +4541,7 @@ checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -4708,7 +4564,7 @@ checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -4761,7 +4617,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -4773,7 +4629,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -4978,9 +4834,9 @@ dependencies = [ [[package]] name = "strum" -version = "0.26.2" +version = "0.26.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d8cec3501a5194c432b2b7976db6b7d10ec95c253208b45f83f7136aa985e29" +checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" dependencies = [ "strum_macros 0.26.4", ] @@ -4995,7 +4851,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -5008,14 +4864,14 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] name = "subtle" -version = "2.5.0" +version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "subtle-encoding" @@ -5039,9 +4895,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.66" +version = "2.0.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c42f3f41a2de00b01c0aaad383c5a45241efc8b2d1eda5661812fda5f3cdcff5" +checksum = "901fa70d88b9d6c98022e23b4136f9f3e54e4662c3bc1bd1d84a42a9a0f0c1e9" dependencies = [ "proc-macro2", "quote", @@ -5057,7 +4913,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -5078,17 +4934,6 @@ dependencies = [ "unicode-xid", ] -[[package]] -name = "synstructure" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.66", -] - [[package]] name = "system-interface" version = "0.26.1" @@ -5255,7 +5100,7 @@ checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -5299,16 +5144,6 @@ dependencies = [ "time-core", ] -[[package]] -name = "tinystr" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" -dependencies = [ - "displaydoc", - "zerovec", -] - [[package]] name = "tinytemplate" version = "1.2.1" @@ -5372,7 +5207,7 @@ checksum = "5f5ae998a069d4b5aba8ee9dad856af7d520c3699e6159b185c2acd48155d39a" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -5571,7 +5406,7 @@ dependencies = [ "proc-macro2", "prost-build 0.12.6", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -5623,7 +5458,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -5711,12 +5546,27 @@ dependencies = [ "version_check", ] +[[package]] +name = "unicode-bidi" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" + [[package]] name = "unicode-ident" version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +[[package]] +name = "unicode-normalization" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" +dependencies = [ + "tinyvec", +] + [[package]] name = "unicode-width" version = "0.1.13" @@ -5754,27 +5604,15 @@ dependencies = [ [[package]] name = "url" -version = "2.5.1" +version = "2.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7c25da092f0a868cdf09e8674cd3b7ef3a7d92a24253e663a2fb85e2496de56" +checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" dependencies = [ "form_urlencoded", "idna", "percent-encoding", ] -[[package]] -name = "utf16_iter" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" - -[[package]] -name = "utf8_iter" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" - [[package]] name = "utf8parse" version = "0.2.2" @@ -5783,9 +5621,9 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" -version = "1.8.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a183cf7feeba97b4dd1c0d46788634f6221d87fa961b305bed08c851829efcc0" +checksum = "3ea73390fe27785838dcbf75b91b1d84799e28f1ce71e6f372a5dc2200c80de5" dependencies = [ "getrandom", "rand", @@ -5916,7 +5754,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", "wasm-bindgen-shared", ] @@ -5950,7 +5788,7 @@ checksum = "e128beba882dd1eb6200e1dc92ae6c5dbaa4311aa7bb211ca035779e5efc39f8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -6193,7 +6031,7 @@ checksum = "f55c5565959287c21dd0f4277ae3518dd2ae62679f655ee2dbc4396e19d210db" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -6288,7 +6126,7 @@ dependencies = [ "proc-macro2", "quote", "shellexpand", - "syn 2.0.66", + "syn 2.0.68", "witx", ] @@ -6300,7 +6138,7 @@ checksum = "31ae1ec11a17ea481539ee9a5719a278c9790d974060fbf71db4b2c05378780b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", "wiggle-generate", ] @@ -6536,18 +6374,6 @@ dependencies = [ "wast", ] -[[package]] -name = "write16" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" - -[[package]] -name = "writeable" -version = "0.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" - [[package]] name = "wyz" version = "0.5.1" @@ -6563,30 +6389,6 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec" -[[package]] -name = "yoke" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c5b1314b079b0930c31e3af543d8ee1757b1951ae1e1565ec704403a7240ca5" -dependencies = [ - "serde", - "stable_deref_trait", - "yoke-derive", - "zerofrom", -] - -[[package]] -name = "yoke-derive" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28cc31741b18cb6f1d5ff12f5b7523e3d6eb0852bbbad19d73905511d9849b95" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.66", - "synstructure 0.13.1", -] - [[package]] name = "zerocopy" version = "0.7.34" @@ -6604,28 +6406,7 @@ checksum = "15e934569e47891f7d9411f1a451d947a60e000ab3bd24fbb970f000387d1b3b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", -] - -[[package]] -name = "zerofrom" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91ec111ce797d0e0784a1116d0ddcdbea84322cd79e5d5ad173daeba4f93ab55" -dependencies = [ - "zerofrom-derive", -] - -[[package]] -name = "zerofrom-derive" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ea7b4a3637ea8669cedf0f1fd5c286a17f3de97b8dd5a70a6c167a1730e63a5" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.66", - "synstructure 0.13.1", + "syn 2.0.68", ] [[package]] @@ -6634,28 +6415,6 @@ version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" -[[package]] -name = "zerovec" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb2cc8827d6c0994478a15c53f374f46fbd41bea663d809b14744bc42e6b109c" -dependencies = [ - "yoke", - "zerofrom", - "zerovec-derive", -] - -[[package]] -name = "zerovec-derive" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97cf56601ee5052b4417d90c8755c6683473c926039908196cf35d99f893ebe7" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.66", -] - [[package]] name = "zip" version = "0.6.6" diff --git a/packages/rs-dpp/src/errors/consensus/codes.rs b/packages/rs-dpp/src/errors/consensus/codes.rs index 1f28d78248d..1b278f50f5d 100644 --- a/packages/rs-dpp/src/errors/consensus/codes.rs +++ b/packages/rs-dpp/src/errors/consensus/codes.rs @@ -232,6 +232,8 @@ impl ErrorWithCode for StateError { Self::VotePollNotAvailableForVotingError(_) => 40302, Self::MasternodeVotedTooManyTimesError(_) => 40303, Self::MasternodeVoteAlreadyPresentError(_) => 40304, + Self::MasternodeIncorrectVotingAddressError(_) => 40305, + Self::MasternodeIncorrectVoterIdentityIdError(_) => 40306, // Prefunded specialized balances Errors: 40400-40499 Self::PrefundedSpecializedBalanceInsufficientError(_) => 40400, diff --git a/packages/rs-dpp/src/errors/consensus/state/state_error.rs b/packages/rs-dpp/src/errors/consensus/state/state_error.rs index 4bee280e26c..05dad1b09db 100644 --- a/packages/rs-dpp/src/errors/consensus/state/state_error.rs +++ b/packages/rs-dpp/src/errors/consensus/state/state_error.rs @@ -37,6 +37,8 @@ use crate::consensus::state::identity::identity_public_key_already_exists_for_un use crate::consensus::state::identity::invalid_identity_contract_nonce_error::InvalidIdentityNonceError; use crate::consensus::state::prefunded_specialized_balances::prefunded_specialized_balance_insufficient_error::PrefundedSpecializedBalanceInsufficientError; use crate::consensus::state::prefunded_specialized_balances::prefunded_specialized_balance_not_found_error::PrefundedSpecializedBalanceNotFoundError; +use crate::consensus::state::voting::masternode_incorrect_voter_identity_id_error::MasternodeIncorrectVoterIdentityIdError; +use crate::consensus::state::voting::masternode_incorrect_voting_address_error::MasternodeIncorrectVotingAddressError; use crate::consensus::state::voting::masternode_not_found_error::MasternodeNotFoundError; use crate::consensus::state::voting::masternode_vote_already_present_error::MasternodeVoteAlreadyPresentError; use crate::consensus::state::voting::masternode_voted_too_many_times::MasternodeVotedTooManyTimesError; @@ -158,6 +160,12 @@ pub enum StateError { #[error(transparent)] MasternodeNotFoundError(MasternodeNotFoundError), + #[error(transparent)] + MasternodeIncorrectVoterIdentityIdError(MasternodeIncorrectVoterIdentityIdError), + + #[error(transparent)] + MasternodeIncorrectVotingAddressError(MasternodeIncorrectVotingAddressError), + #[error(transparent)] VotePollNotFoundError(VotePollNotFoundError), diff --git a/packages/rs-dpp/src/errors/consensus/state/voting/masternode_incorrect_voter_identity_id_error.rs b/packages/rs-dpp/src/errors/consensus/state/voting/masternode_incorrect_voter_identity_id_error.rs new file mode 100644 index 00000000000..4219e0df96c --- /dev/null +++ b/packages/rs-dpp/src/errors/consensus/state/voting/masternode_incorrect_voter_identity_id_error.rs @@ -0,0 +1,57 @@ +use crate::consensus::state::state_error::StateError; +use crate::consensus::ConsensusError; +use crate::errors::ProtocolError; +use bincode::{Decode, Encode}; +use platform_serialization_derive::{PlatformDeserialize, PlatformSerialize}; +use platform_value::Identifier; +use thiserror::Error; + +#[derive( + Error, Debug, Clone, PartialEq, Eq, Encode, Decode, PlatformSerialize, PlatformDeserialize, +)] +#[error("Masternode {pro_tx_hash} voter identity id is incorrect, expected is {expected_voter_identity_id}, provided is {provided_voter_identity_id}")] +#[platform_serialize(unversioned)] +pub struct MasternodeIncorrectVoterIdentityIdError { + /* + + DO NOT CHANGE ORDER OF FIELDS WITHOUT INTRODUCING OF NEW VERSION + + */ + pro_tx_hash: Identifier, + + expected_voter_identity_id: Identifier, + + provided_voter_identity_id: Identifier, +} + +impl MasternodeIncorrectVoterIdentityIdError { + pub fn new( + pro_tx_hash: Identifier, + expected_voter_identity_id: Identifier, + provided_voter_identity_id: Identifier, + ) -> Self { + Self { + pro_tx_hash, + expected_voter_identity_id, + provided_voter_identity_id, + } + } + + pub fn pro_tx_hash(&self) -> Identifier { + self.pro_tx_hash + } + + pub fn expected_voter_identity_id(&self) -> Identifier { + self.expected_voter_identity_id + } + + pub fn provided_voter_identity_id(&self) -> Identifier { + self.provided_voter_identity_id + } +} + +impl From for ConsensusError { + fn from(err: MasternodeIncorrectVoterIdentityIdError) -> Self { + Self::StateError(StateError::MasternodeIncorrectVoterIdentityIdError(err)) + } +} diff --git a/packages/rs-dpp/src/errors/consensus/state/voting/masternode_incorrect_voting_address_error.rs b/packages/rs-dpp/src/errors/consensus/state/voting/masternode_incorrect_voting_address_error.rs new file mode 100644 index 00000000000..5953eb86d39 --- /dev/null +++ b/packages/rs-dpp/src/errors/consensus/state/voting/masternode_incorrect_voting_address_error.rs @@ -0,0 +1,57 @@ +use crate::consensus::state::state_error::StateError; +use crate::consensus::ConsensusError; +use crate::errors::ProtocolError; +use bincode::{Decode, Encode}; +use platform_serialization_derive::{PlatformDeserialize, PlatformSerialize}; +use platform_value::{Bytes20, Identifier}; +use thiserror::Error; + +#[derive( + Error, Debug, Clone, PartialEq, Eq, Encode, Decode, PlatformSerialize, PlatformDeserialize, +)] +#[error("Masternode {pro_tx_hash} voting address is incorrect, current is {current_voting_address}, given is {given_voting_address}")] +#[platform_serialize(unversioned)] +pub struct MasternodeIncorrectVotingAddressError { + /* + + DO NOT CHANGE ORDER OF FIELDS WITHOUT INTRODUCING OF NEW VERSION + + */ + pro_tx_hash: Identifier, + + current_voting_address: Bytes20, + + given_voting_address: Bytes20, +} + +impl MasternodeIncorrectVotingAddressError { + pub fn new( + pro_tx_hash: Identifier, + current_voting_address: Bytes20, + given_voting_address: Bytes20, + ) -> Self { + Self { + pro_tx_hash, + current_voting_address, + given_voting_address, + } + } + + pub fn pro_tx_hash(&self) -> Identifier { + self.pro_tx_hash + } + + pub fn current_voting_address(&self) -> Bytes20 { + self.current_voting_address + } + + pub fn given_voting_address(&self) -> Bytes20 { + self.given_voting_address + } +} + +impl From for ConsensusError { + fn from(err: MasternodeIncorrectVotingAddressError) -> Self { + Self::StateError(StateError::MasternodeIncorrectVotingAddressError(err)) + } +} diff --git a/packages/rs-dpp/src/errors/consensus/state/voting/masternode_not_found_error.rs b/packages/rs-dpp/src/errors/consensus/state/voting/masternode_not_found_error.rs index 9a99ec13c95..f004cfe79d4 100644 --- a/packages/rs-dpp/src/errors/consensus/state/voting/masternode_not_found_error.rs +++ b/packages/rs-dpp/src/errors/consensus/state/voting/masternode_not_found_error.rs @@ -9,7 +9,7 @@ use thiserror::Error; #[derive( Error, Debug, Clone, PartialEq, Eq, Encode, Decode, PlatformSerialize, PlatformDeserialize, )] -#[error("Masternode {pro_tx_hash:?} not found")] +#[error("Masternode {pro_tx_hash} not found")] #[platform_serialize(unversioned)] pub struct MasternodeNotFoundError { /* diff --git a/packages/rs-dpp/src/errors/consensus/state/voting/mod.rs b/packages/rs-dpp/src/errors/consensus/state/voting/mod.rs index dcf121e8474..fcf092f07aa 100644 --- a/packages/rs-dpp/src/errors/consensus/state/voting/mod.rs +++ b/packages/rs-dpp/src/errors/consensus/state/voting/mod.rs @@ -1,3 +1,5 @@ +pub mod masternode_incorrect_voter_identity_id_error; +pub mod masternode_incorrect_voting_address_error; pub mod masternode_not_found_error; pub mod masternode_vote_already_present_error; pub mod masternode_voted_too_many_times; diff --git a/packages/rs-dpp/src/identifier/mod.rs b/packages/rs-dpp/src/identifier/mod.rs index ced6fa8aa88..ae691e0b762 100644 --- a/packages/rs-dpp/src/identifier/mod.rs +++ b/packages/rs-dpp/src/identifier/mod.rs @@ -1,2 +1,32 @@ pub use platform_value::Identifier; pub use platform_value::IDENTIFIER_MEDIA_TYPE as MEDIA_TYPE; +use sha2::{Digest, Sha256}; + +pub trait MasternodeIdentifiers { + fn create_voter_identifier(pro_tx_hash: &[u8; 32], voting_address: &[u8; 20]) -> Identifier; + + fn create_operator_identifier(pro_tx_hash: &[u8; 32], pub_key_operator: &[u8]) -> Identifier; +} + +trait IdentifierConstructorPrivate { + fn hash_protxhash_with_key_data(pro_tx_hash: &[u8; 32], key_data: &[u8]) -> Identifier; +} +impl MasternodeIdentifiers for Identifier { + fn create_voter_identifier(pro_tx_hash: &[u8; 32], voting_address: &[u8; 20]) -> Identifier { + Self::hash_protxhash_with_key_data(pro_tx_hash, voting_address) + } + + fn create_operator_identifier(pro_tx_hash: &[u8; 32], pub_key_operator: &[u8]) -> Identifier { + Self::hash_protxhash_with_key_data(pro_tx_hash, pub_key_operator) + } +} + +impl IdentifierConstructorPrivate for Identifier { + fn hash_protxhash_with_key_data(pro_tx_hash: &[u8; 32], key_data: &[u8]) -> Identifier { + let mut hasher = Sha256::new(); + hasher.update(pro_tx_hash); + hasher.update(key_data); + let bytes: [u8; 32] = hasher.finalize().into(); + bytes.into() + } +} diff --git a/packages/rs-dpp/src/identity/identity_public_key/methods/hash/mod.rs b/packages/rs-dpp/src/identity/identity_public_key/methods/hash/mod.rs index 3f70f1a6a81..6978a3035db 100644 --- a/packages/rs-dpp/src/identity/identity_public_key/methods/hash/mod.rs +++ b/packages/rs-dpp/src/identity/identity_public_key/methods/hash/mod.rs @@ -5,9 +5,9 @@ use crate::ProtocolError; pub use v0::*; impl IdentityPublicKeyHashMethodsV0 for IdentityPublicKey { - fn hash(&self) -> Result<[u8; 20], ProtocolError> { + fn public_key_hash(&self) -> Result<[u8; 20], ProtocolError> { match self { - IdentityPublicKey::V0(v0) => v0.hash(), + IdentityPublicKey::V0(v0) => v0.public_key_hash(), } } } diff --git a/packages/rs-dpp/src/identity/identity_public_key/methods/hash/v0/mod.rs b/packages/rs-dpp/src/identity/identity_public_key/methods/hash/v0/mod.rs index 350721baae7..7b656292e33 100644 --- a/packages/rs-dpp/src/identity/identity_public_key/methods/hash/v0/mod.rs +++ b/packages/rs-dpp/src/identity/identity_public_key/methods/hash/v0/mod.rs @@ -2,5 +2,5 @@ use crate::ProtocolError; pub trait IdentityPublicKeyHashMethodsV0 { /// Get the original public key hash - fn hash(&self) -> Result<[u8; 20], ProtocolError>; + fn public_key_hash(&self) -> Result<[u8; 20], ProtocolError>; } diff --git a/packages/rs-dpp/src/identity/identity_public_key/v0/methods/mod.rs b/packages/rs-dpp/src/identity/identity_public_key/v0/methods/mod.rs index 669334b6d5e..05232ed22a1 100644 --- a/packages/rs-dpp/src/identity/identity_public_key/v0/methods/mod.rs +++ b/packages/rs-dpp/src/identity/identity_public_key/v0/methods/mod.rs @@ -10,7 +10,7 @@ use platform_value::Bytes20; impl IdentityPublicKeyHashMethodsV0 for IdentityPublicKeyV0 { /// Get the original public key hash - fn hash(&self) -> Result<[u8; 20], ProtocolError> { + fn public_key_hash(&self) -> Result<[u8; 20], ProtocolError> { if self.data.is_empty() { return Err(ProtocolError::EmptyPublicKeyDataError); } diff --git a/packages/rs-dpp/src/identity/methods/create_basic_identity/mod.rs b/packages/rs-dpp/src/identity/methods/create_basic_identity/mod.rs index c4888be4b48..2da82b989ff 100644 --- a/packages/rs-dpp/src/identity/methods/create_basic_identity/mod.rs +++ b/packages/rs-dpp/src/identity/methods/create_basic_identity/mod.rs @@ -2,12 +2,13 @@ mod v0; use crate::prelude::Identity; use crate::ProtocolError; +use platform_value::Identifier; use platform_version::version::PlatformVersion; impl Identity { pub fn create_basic_identity( - id: [u8; 32], + id: Identifier, platform_version: &PlatformVersion, ) -> Result { match platform_version diff --git a/packages/rs-dpp/src/identity/methods/create_basic_identity/v0/mod.rs b/packages/rs-dpp/src/identity/methods/create_basic_identity/v0/mod.rs index a9a5f170b71..638a8603379 100644 --- a/packages/rs-dpp/src/identity/methods/create_basic_identity/v0/mod.rs +++ b/packages/rs-dpp/src/identity/methods/create_basic_identity/v0/mod.rs @@ -5,9 +5,9 @@ use std::collections::BTreeMap; impl Identity { #[inline(always)] - pub(super) fn create_basic_identity_v0(id: [u8; 32]) -> Self { + pub(super) fn create_basic_identity_v0(id: Identifier) -> Self { IdentityV0 { - id: Identifier::new(id), + id, revision: 0, balance: 0, public_keys: BTreeMap::new(), diff --git a/packages/rs-dpp/src/state_transition/state_transitions/identity/masternode_vote_transition/accessors/mod.rs b/packages/rs-dpp/src/state_transition/state_transitions/identity/masternode_vote_transition/accessors/mod.rs index ee47fec29a8..078e18f4376 100644 --- a/packages/rs-dpp/src/state_transition/state_transitions/identity/masternode_vote_transition/accessors/mod.rs +++ b/packages/rs-dpp/src/state_transition/state_transitions/identity/masternode_vote_transition/accessors/mod.rs @@ -7,15 +7,15 @@ use platform_value::Identifier; pub use v0::*; impl MasternodeVoteTransitionAccessorsV0 for MasternodeVoteTransition { - fn nonce(&self) -> IdentityNonce { + fn pro_tx_hash(&self) -> Identifier { match self { - MasternodeVoteTransition::V0(transition) => transition.nonce, + MasternodeVoteTransition::V0(transition) => transition.pro_tx_hash, } } - fn pro_tx_hash(&self) -> Identifier { + fn voter_identity_id(&self) -> Identifier { match self { - MasternodeVoteTransition::V0(transition) => transition.pro_tx_hash, + MasternodeVoteTransition::V0(transition) => transition.voter_identity_id, } } @@ -27,6 +27,14 @@ impl MasternodeVoteTransitionAccessorsV0 for MasternodeVoteTransition { } } + fn set_voter_identity_id(&mut self, voter_identity_id: Identifier) { + match self { + MasternodeVoteTransition::V0(transition) => { + transition.voter_identity_id = voter_identity_id; + } + } + } + fn vote(&self) -> &Vote { match self { MasternodeVoteTransition::V0(transition) => &transition.vote, @@ -40,4 +48,10 @@ impl MasternodeVoteTransitionAccessorsV0 for MasternodeVoteTransition { } } } + + fn nonce(&self) -> IdentityNonce { + match self { + MasternodeVoteTransition::V0(transition) => transition.nonce, + } + } } diff --git a/packages/rs-dpp/src/state_transition/state_transitions/identity/masternode_vote_transition/accessors/v0/mod.rs b/packages/rs-dpp/src/state_transition/state_transitions/identity/masternode_vote_transition/accessors/v0/mod.rs index e12b9c649d3..dd62754e0e0 100644 --- a/packages/rs-dpp/src/state_transition/state_transitions/identity/masternode_vote_transition/accessors/v0/mod.rs +++ b/packages/rs-dpp/src/state_transition/state_transitions/identity/masternode_vote_transition/accessors/v0/mod.rs @@ -4,7 +4,9 @@ use platform_value::Identifier; pub trait MasternodeVoteTransitionAccessorsV0 { fn pro_tx_hash(&self) -> Identifier; + fn voter_identity_id(&self) -> Identifier; fn set_pro_tx_hash(&mut self, pro_tx_hash: Identifier); + fn set_voter_identity_id(&mut self, voter_id: Identifier); fn vote(&self) -> &Vote; fn set_vote(&mut self, vote: Vote); fn nonce(&self) -> IdentityNonce; diff --git a/packages/rs-dpp/src/state_transition/state_transitions/identity/masternode_vote_transition/v0/mod.rs b/packages/rs-dpp/src/state_transition/state_transitions/identity/masternode_vote_transition/v0/mod.rs index 4d707ea1c32..e7be2b3c5f0 100644 --- a/packages/rs-dpp/src/state_transition/state_transitions/identity/masternode_vote_transition/v0/mod.rs +++ b/packages/rs-dpp/src/state_transition/state_transitions/identity/masternode_vote_transition/v0/mod.rs @@ -40,6 +40,7 @@ use serde::{Deserialize, Serialize}; pub struct MasternodeVoteTransitionV0 { // Own ST fields pub pro_tx_hash: Identifier, + pub voter_identity_id: Identifier, pub vote: Vote, pub nonce: IdentityNonce, #[platform_signable(exclude_from_sig_hash)] @@ -82,6 +83,7 @@ mod test { let mut rng = rand::thread_rng(); let transition = MasternodeVoteTransitionV0 { pro_tx_hash: Identifier::random(), + voting_address: rng.gen(), vote: Vote::ResourceVote(ResourceVote::V0(ResourceVoteV0 { vote_poll: VotePoll::ContestedDocumentResourceVotePoll( ContestedDocumentResourceVotePoll { diff --git a/packages/rs-dpp/src/state_transition/state_transitions/identity/masternode_vote_transition/v0/state_transition_like.rs b/packages/rs-dpp/src/state_transition/state_transitions/identity/masternode_vote_transition/v0/state_transition_like.rs index 03fda4a4f26..91a72646493 100644 --- a/packages/rs-dpp/src/state_transition/state_transitions/identity/masternode_vote_transition/v0/state_transition_like.rs +++ b/packages/rs-dpp/src/state_transition/state_transitions/identity/masternode_vote_transition/v0/state_transition_like.rs @@ -49,9 +49,8 @@ impl StateTransitionLike for MasternodeVoteTransitionV0 { // Setting does nothing } - /// Returns ID of the created contract fn modified_data_ids(&self) -> Vec { - vec![self.pro_tx_hash] + vec![self.voter_identity_id] } fn set_signature_bytes(&mut self, signature: Vec) { @@ -60,7 +59,7 @@ impl StateTransitionLike for MasternodeVoteTransitionV0 { /// Get owner ID fn owner_id(&self) -> Identifier { - self.pro_tx_hash + self.voter_identity_id } fn unique_identifiers(&self) -> Vec { diff --git a/packages/rs-dpp/src/state_transition/state_transitions/identity/masternode_vote_transition/v0/v0_methods.rs b/packages/rs-dpp/src/state_transition/state_transitions/identity/masternode_vote_transition/v0/v0_methods.rs index ad7fbd60fcd..179f1c07486 100644 --- a/packages/rs-dpp/src/state_transition/state_transitions/identity/masternode_vote_transition/v0/v0_methods.rs +++ b/packages/rs-dpp/src/state_transition/state_transitions/identity/masternode_vote_transition/v0/v0_methods.rs @@ -1,10 +1,13 @@ #[cfg(feature = "state-transition-signing")] +use crate::identifier::MasternodeIdentifiers; +#[cfg(feature = "state-transition-signing")] +use crate::identity::hash::IdentityPublicKeyHashMethodsV0; +#[cfg(feature = "state-transition-signing")] use crate::identity::signer::Signer; #[cfg(feature = "state-transition-signing")] use crate::identity::{IdentityPublicKey, SecurityLevel}; #[cfg(feature = "state-transition-signing")] use crate::prelude::IdentityNonce; -use crate::state_transition::masternode_vote_transition::v0::MasternodeVoteTransitionV0; #[cfg(feature = "state-transition-signing")] use crate::state_transition::masternode_vote_transition::MasternodeVoteTransition; #[cfg(feature = "state-transition-signing")] @@ -16,6 +19,8 @@ use crate::ProtocolError; #[cfg(feature = "state-transition-signing")] use platform_value::Identifier; +use crate::state_transition::masternode_vote_transition::v0::MasternodeVoteTransitionV0; + impl MasternodeVoteTransitionV0 { #[cfg(feature = "state-transition-signing")] pub fn try_from_vote_with_signer( @@ -25,8 +30,12 @@ impl MasternodeVoteTransitionV0 { masternode_voting_key: &IdentityPublicKey, nonce: IdentityNonce, ) -> Result { + let voting_address = masternode_voting_key.public_key_hash()?; + let voter_identity_id = + Identifier::create_voter_identifier(pro_tx_hash.as_bytes(), &voting_address); let masternode_vote_transition: MasternodeVoteTransition = MasternodeVoteTransitionV0 { pro_tx_hash, + voter_identity_id, vote, nonce, signature_public_key_id: 0, diff --git a/packages/rs-dpp/src/state_transition/state_transitions/identity/public_key_in_creation/methods/hash/v0/mod.rs b/packages/rs-dpp/src/state_transition/state_transitions/identity/public_key_in_creation/methods/hash/v0/mod.rs index deb51c0f7a3..2d4a33d3a75 100644 --- a/packages/rs-dpp/src/state_transition/state_transitions/identity/public_key_in_creation/methods/hash/v0/mod.rs +++ b/packages/rs-dpp/src/state_transition/state_transitions/identity/public_key_in_creation/methods/hash/v0/mod.rs @@ -7,6 +7,6 @@ impl IdentityPublicKeyInCreation { /// Get the original public key hash #[inline(always)] pub(super) fn hash_v0(&self) -> Result<[u8; 20], ProtocolError> { - Into::::into(self.clone()).hash() + Into::::into(self.clone()).public_key_hash() } } diff --git a/packages/rs-drive-abci/src/execution/platform_events/core_based_updates/update_masternode_identities/create_owner_identity/v0/mod.rs b/packages/rs-drive-abci/src/execution/platform_events/core_based_updates/update_masternode_identities/create_owner_identity/v0/mod.rs index 79c1c9d1268..eb4da99b897 100644 --- a/packages/rs-drive-abci/src/execution/platform_events/core_based_updates/update_masternode_identities/create_owner_identity/v0/mod.rs +++ b/packages/rs-drive-abci/src/execution/platform_events/core_based_updates/update_masternode_identities/create_owner_identity/v0/mod.rs @@ -2,6 +2,7 @@ use crate::error::Error; use crate::platform_types::platform::Platform; use crate::rpc::core::CoreRPCLike; use dashcore_rpc::dashcore_rpc_json::MasternodeListItem; +use dpp::identifier::Identifier; use dpp::identity::accessors::IdentityGettersV0; use dpp::identity::Identity; use dpp::version::PlatformVersion; @@ -24,8 +25,8 @@ where Ok(identity) } - fn get_owner_identifier(masternode: &MasternodeListItem) -> Result<[u8; 32], Error> { + fn get_owner_identifier(masternode: &MasternodeListItem) -> Result { let masternode_identifier: [u8; 32] = masternode.pro_tx_hash.into(); - Ok(masternode_identifier) + Ok(masternode_identifier.into()) } } diff --git a/packages/rs-drive-abci/src/execution/platform_events/core_based_updates/update_masternode_identities/create_voter_identity/v0/mod.rs b/packages/rs-drive-abci/src/execution/platform_events/core_based_updates/update_masternode_identities/create_voter_identity/v0/mod.rs index 68ec59fce8c..9268960874e 100644 --- a/packages/rs-drive-abci/src/execution/platform_events/core_based_updates/update_masternode_identities/create_voter_identity/v0/mod.rs +++ b/packages/rs-drive-abci/src/execution/platform_events/core_based_updates/update_masternode_identities/create_voter_identity/v0/mod.rs @@ -3,8 +3,10 @@ use crate::platform_types::platform::Platform; use crate::rpc::core::CoreRPCLike; use dashcore_rpc::dashcore_rpc_json::MasternodeListItem; use dpp::dashcore::hashes::Hash; +use dpp::identifier::MasternodeIdentifiers; use dpp::identity::accessors::IdentityGettersV0; use dpp::identity::Identity; +use dpp::prelude::Identifier; use dpp::version::PlatformVersion; impl Platform @@ -16,8 +18,7 @@ where voting_key: &[u8; 20], platform_version: &PlatformVersion, ) -> Result { - let voting_identifier = - Self::get_voter_identifier(pro_tx_hash, voting_key, platform_version)?; + let voting_identifier = Identifier::create_voter_identifier(pro_tx_hash, voting_key); let mut identity = Identity::create_basic_identity(voting_identifier, platform_version)?; identity.add_public_keys([Self::get_voter_identity_key( *voting_key, diff --git a/packages/rs-drive-abci/src/execution/platform_events/core_based_updates/update_masternode_identities/disable_identity_keys/v0/mod.rs b/packages/rs-drive-abci/src/execution/platform_events/core_based_updates/update_masternode_identities/disable_identity_keys/v0/mod.rs index 88b2ccbdf99..523e4e89039 100644 --- a/packages/rs-drive-abci/src/execution/platform_events/core_based_updates/update_masternode_identities/disable_identity_keys/v0/mod.rs +++ b/packages/rs-drive-abci/src/execution/platform_events/core_based_updates/update_masternode_identities/disable_identity_keys/v0/mod.rs @@ -40,14 +40,14 @@ where Self::get_voter_identifier_from_masternode_list_item(old_masternode, platform_version)?; let operator_key_request = IdentityKeysRequest { - identity_id: operator_identifier, + identity_id: operator_identifier.into_buffer(), request_type: KeyRequestType::AllKeys, limit: None, offset: None, }; let voter_key_request = IdentityKeysRequest { - identity_id: voter_identifier, + identity_id: voter_identifier.into_buffer(), request_type: KeyRequestType::AllKeys, limit: None, offset: None, @@ -95,7 +95,7 @@ where ); drive_operations.push(IdentityOperation(DisableIdentityKeys { - identity_id: operator_identifier, + identity_id: operator_identifier.into_buffer(), keys_ids: operator_identity_keys, })); @@ -108,7 +108,7 @@ where ); drive_operations.push(IdentityOperation(DisableIdentityKeys { - identity_id: voter_identifier, + identity_id: voter_identifier.into_buffer(), keys_ids: voter_identity_keys, })); diff --git a/packages/rs-drive-abci/src/execution/platform_events/core_based_updates/update_masternode_identities/get_operator_identifier/mod.rs b/packages/rs-drive-abci/src/execution/platform_events/core_based_updates/update_masternode_identities/get_operator_identifier/mod.rs index 8229de81ece..87f27b24f10 100644 --- a/packages/rs-drive-abci/src/execution/platform_events/core_based_updates/update_masternode_identities/get_operator_identifier/mod.rs +++ b/packages/rs-drive-abci/src/execution/platform_events/core_based_updates/update_masternode_identities/get_operator_identifier/mod.rs @@ -5,6 +5,7 @@ use crate::error::Error; use crate::platform_types::platform::Platform; use crate::rpc::core::CoreRPCLike; use dashcore_rpc::dashcore_rpc_json::MasternodeListItem; +use dpp::identifier::Identifier; use dpp::version::PlatformVersion; @@ -23,22 +24,21 @@ where /// /// # Returns /// - /// * Result<[u8; 32], Error> - Returns the derived operator identifier if successful. Otherwise, returns an error. + /// * Result - Returns the derived operator identifier if successful. Otherwise, returns an error. pub(super) fn get_operator_identifier_from_masternode_list_item( masternode: &MasternodeListItem, platform_version: &PlatformVersion, - ) -> Result<[u8; 32], Error> { + ) -> Result { match platform_version .drive_abci .methods .core_based_updates .masternode_updates - .get_operator_identifier + .get_operator_identifier_from_masternode_list_item { - 0 => Self::get_operator_identifier_from_masternode_list_item_v0( + 0 => Ok(Self::get_operator_identifier_from_masternode_list_item_v0( masternode, - platform_version, - ), + )), version => Err(Error::Execution(ExecutionError::UnknownVersionMismatch { method: "get_operator_identifier_from_masternode_list_item".to_string(), known_versions: vec![0], diff --git a/packages/rs-drive-abci/src/execution/platform_events/core_based_updates/update_masternode_identities/get_operator_identifier/v0/mod.rs b/packages/rs-drive-abci/src/execution/platform_events/core_based_updates/update_masternode_identities/get_operator_identifier/v0/mod.rs index 150172ff41d..20a09780697 100644 --- a/packages/rs-drive-abci/src/execution/platform_events/core_based_updates/update_masternode_identities/get_operator_identifier/v0/mod.rs +++ b/packages/rs-drive-abci/src/execution/platform_events/core_based_updates/update_masternode_identities/get_operator_identifier/v0/mod.rs @@ -1,32 +1,20 @@ -use crate::error::Error; use crate::platform_types::platform::Platform; use crate::rpc::core::CoreRPCLike; use dashcore_rpc::dashcore_rpc_json::MasternodeListItem; -use dpp::version::PlatformVersion; +use dpp::identifier::MasternodeIdentifiers; +use dpp::prelude::Identifier; impl Platform where C: CoreRPCLike, { - pub(super) fn get_operator_identifier_v0( - pro_tx_hash: &[u8; 32], - pub_key_operator: &[u8], - platform_version: &PlatformVersion, - ) -> Result<[u8; 32], Error> { - let operator_identifier = - Self::hash_protxhash_with_key_data(pro_tx_hash, pub_key_operator, platform_version)?; - Ok(operator_identifier) - } - pub(super) fn get_operator_identifier_from_masternode_list_item_v0( masternode: &MasternodeListItem, - platform_version: &PlatformVersion, - ) -> Result<[u8; 32], Error> { + ) -> Identifier { let pro_tx_hash = &masternode.pro_tx_hash.into(); - Self::get_operator_identifier_v0( + Identifier::create_operator_identifier( pro_tx_hash, masternode.state.pub_key_operator.as_slice(), - platform_version, ) } } diff --git a/packages/rs-drive-abci/src/execution/platform_events/core_based_updates/update_masternode_identities/get_voter_identifier/mod.rs b/packages/rs-drive-abci/src/execution/platform_events/core_based_updates/update_masternode_identities/get_voter_identifier/mod.rs index 25d6838f850..c82078fa8df 100644 --- a/packages/rs-drive-abci/src/execution/platform_events/core_based_updates/update_masternode_identities/get_voter_identifier/mod.rs +++ b/packages/rs-drive-abci/src/execution/platform_events/core_based_updates/update_masternode_identities/get_voter_identifier/mod.rs @@ -5,6 +5,7 @@ use crate::error::Error; use crate::platform_types::platform::Platform; use crate::rpc::core::CoreRPCLike; use dashcore_rpc::dashcore_rpc_json::MasternodeListItem; +use dpp::identifier::Identifier; use dpp::version::PlatformVersion; @@ -12,40 +13,6 @@ impl Platform where C: CoreRPCLike, { - /// Retrieves a voter identifier using the provided transaction hash and voting address. - /// - /// This function derives the voter identifier and delegates to a version-specific method depending on the platform version. - /// - /// # Arguments - /// - /// * pro_tx_hash - A reference to the transaction hash. - /// * voting_address - A reference to the voting address. - /// * platform_version - The version of the platform to determine which method to delegate to. - /// - /// # Returns - /// - /// * Result<[u8; 32], Error> - Returns the derived voter identifier if successful. Otherwise, returns an error. - pub(crate) fn get_voter_identifier( - pro_tx_hash: &[u8; 32], - voting_address: &[u8; 20], - platform_version: &PlatformVersion, - ) -> Result<[u8; 32], Error> { - match platform_version - .drive_abci - .methods - .core_based_updates - .masternode_updates - .get_voter_identifier - { - 0 => Self::get_voter_identifier_v0(pro_tx_hash, voting_address, platform_version), - version => Err(Error::Execution(ExecutionError::UnknownVersionMismatch { - method: "get_voter_identifier".to_string(), - known_versions: vec![0], - received: version, - })), - } - } - /// Retrieves a voter identifier based on the provided masternode list item. /// /// This function derives the voter identifier for a masternode and delegates to a version-specific method depending on the platform version. @@ -57,22 +24,21 @@ where /// /// # Returns /// - /// * Result<[u8; 32], Error> - Returns the derived voter identifier if successful. Otherwise, returns an error. + /// * Result - Returns the derived voter identifier if successful. Otherwise, returns an error. pub(crate) fn get_voter_identifier_from_masternode_list_item( masternode: &MasternodeListItem, platform_version: &PlatformVersion, - ) -> Result<[u8; 32], Error> { + ) -> Result { match platform_version .drive_abci .methods .core_based_updates .masternode_updates - .get_voter_identifier + .get_voter_identifier_from_masternode_list_item { - 0 => Self::get_voter_identifier_from_masternode_list_item_v0( + 0 => Ok(Self::get_voter_identifier_from_masternode_list_item_v0( masternode, - platform_version, - ), + )), version => Err(Error::Execution(ExecutionError::UnknownVersionMismatch { method: "get_voter_identifier_from_masternode_list_item".to_string(), known_versions: vec![0], diff --git a/packages/rs-drive-abci/src/execution/platform_events/core_based_updates/update_masternode_identities/get_voter_identifier/v0/mod.rs b/packages/rs-drive-abci/src/execution/platform_events/core_based_updates/update_masternode_identities/get_voter_identifier/v0/mod.rs index e7db6dc4a54..709879db084 100644 --- a/packages/rs-drive-abci/src/execution/platform_events/core_based_updates/update_masternode_identities/get_voter_identifier/v0/mod.rs +++ b/packages/rs-drive-abci/src/execution/platform_events/core_based_updates/update_masternode_identities/get_voter_identifier/v0/mod.rs @@ -1,29 +1,17 @@ -use crate::error::Error; use crate::platform_types::platform::Platform; use crate::rpc::core::CoreRPCLike; use dashcore_rpc::dashcore_rpc_json::MasternodeListItem; -use dpp::version::PlatformVersion; +use dpp::identifier::{Identifier, MasternodeIdentifiers}; impl Platform where C: CoreRPCLike, { - pub(super) fn get_voter_identifier_v0( - pro_tx_hash: &[u8; 32], - voting_address: &[u8; 20], - platform_version: &PlatformVersion, - ) -> Result<[u8; 32], Error> { - let voting_identifier = - Self::hash_protxhash_with_key_data(pro_tx_hash, voting_address, platform_version)?; - Ok(voting_identifier) - } - pub(super) fn get_voter_identifier_from_masternode_list_item_v0( masternode: &MasternodeListItem, - platform_version: &PlatformVersion, - ) -> Result<[u8; 32], Error> { + ) -> Identifier { let pro_tx_hash = &masternode.pro_tx_hash.into(); let voting_address = &masternode.state.voting_address; - Self::get_voter_identifier(pro_tx_hash, voting_address, platform_version) + Identifier::create_voter_identifier(pro_tx_hash, voting_address) } } diff --git a/packages/rs-drive-abci/src/execution/platform_events/core_based_updates/update_masternode_identities/hash_protxhash_with_key_data/mod.rs b/packages/rs-drive-abci/src/execution/platform_events/core_based_updates/update_masternode_identities/hash_protxhash_with_key_data/mod.rs deleted file mode 100644 index 88b1fcff76e..00000000000 --- a/packages/rs-drive-abci/src/execution/platform_events/core_based_updates/update_masternode_identities/hash_protxhash_with_key_data/mod.rs +++ /dev/null @@ -1,46 +0,0 @@ -mod v0; - -use crate::error::execution::ExecutionError; -use crate::error::Error; -use crate::platform_types::platform::Platform; -use crate::rpc::core::CoreRPCLike; -use dpp::version::PlatformVersion; - -impl Platform -where - C: CoreRPCLike, -{ - /// Hashes transaction hash with key data. - /// - /// This function performs the hash operation and delegates to a version-specific method depending on the platform version. - /// - /// # Arguments - /// - /// * pro_tx_hash - The provided transaction hash. - /// * key_data - The key data. - /// * platform_version - The version of the platform to determine which method to delegate to. - /// - /// # Returns - /// - /// * Result<[u8; 32], Error> - Returns a 32 byte hash if successful. Otherwise, returns an error. - pub(in crate::execution::platform_events::core_based_updates) fn hash_protxhash_with_key_data( - pro_tx_hash: &[u8; 32], - key_data: &[u8], - platform_version: &PlatformVersion, - ) -> Result<[u8; 32], Error> { - match platform_version - .drive_abci - .methods - .core_based_updates - .masternode_updates - .hash_protxhash_with_key_data - { - 0 => Self::hash_protxhash_with_key_data_v0(pro_tx_hash, key_data), - version => Err(Error::Execution(ExecutionError::UnknownVersionMismatch { - method: "hash_protxhash_with_key_data".to_string(), - known_versions: vec![0], - received: version, - })), - } - } -} diff --git a/packages/rs-drive-abci/src/execution/platform_events/core_based_updates/update_masternode_identities/hash_protxhash_with_key_data/v0/mod.rs b/packages/rs-drive-abci/src/execution/platform_events/core_based_updates/update_masternode_identities/hash_protxhash_with_key_data/v0/mod.rs deleted file mode 100644 index 3758afe7c5b..00000000000 --- a/packages/rs-drive-abci/src/execution/platform_events/core_based_updates/update_masternode_identities/hash_protxhash_with_key_data/v0/mod.rs +++ /dev/null @@ -1,20 +0,0 @@ -use crate::error::Error; -use crate::platform_types::platform::Platform; -use crate::rpc::core::CoreRPCLike; -use sha2::{Digest, Sha256}; - -impl Platform -where - C: CoreRPCLike, -{ - pub(super) fn hash_protxhash_with_key_data_v0( - pro_tx_hash: &[u8; 32], - key_data: &[u8], - ) -> Result<[u8; 32], Error> { - // todo: maybe change hash functions - let mut hasher = Sha256::new(); - hasher.update(pro_tx_hash); - hasher.update(key_data); - Ok(hasher.finalize().into()) - } -} diff --git a/packages/rs-drive-abci/src/execution/platform_events/core_based_updates/update_masternode_identities/mod.rs b/packages/rs-drive-abci/src/execution/platform_events/core_based_updates/update_masternode_identities/mod.rs index a0edc0c7698..e3168a64e75 100644 --- a/packages/rs-drive-abci/src/execution/platform_events/core_based_updates/update_masternode_identities/mod.rs +++ b/packages/rs-drive-abci/src/execution/platform_events/core_based_updates/update_masternode_identities/mod.rs @@ -7,7 +7,6 @@ mod get_operator_identity_keys; mod get_owner_identity_key; mod get_voter_identifier; mod get_voter_identity_key; -mod hash_protxhash_with_key_data; mod update_masternode_identities; mod update_operator_identity; mod update_owner_withdrawal_address; diff --git a/packages/rs-drive-abci/src/execution/platform_events/core_based_updates/update_masternode_identities/update_operator_identity/v0/mod.rs b/packages/rs-drive-abci/src/execution/platform_events/core_based_updates/update_masternode_identities/update_operator_identity/v0/mod.rs index 82e98c34774..a976dd57aee 100644 --- a/packages/rs-drive-abci/src/execution/platform_events/core_based_updates/update_masternode_identities/update_operator_identity/v0/mod.rs +++ b/packages/rs-drive-abci/src/execution/platform_events/core_based_updates/update_masternode_identities/update_operator_identity/v0/mod.rs @@ -78,7 +78,7 @@ where )?; let key_request = IdentityKeysRequest { - identity_id: old_operator_identifier, + identity_id: old_operator_identifier.to_buffer(), request_type: KeyRequestType::AllKeys, limit: None, offset: None, @@ -143,7 +143,7 @@ where if !old_operator_identity_key_ids_to_disable.is_empty() { drive_operations.push(IdentityOperation(DisableIdentityKeys { - identity_id: new_operator_identifier, + identity_id: new_operator_identifier.to_buffer(), keys_ids: old_operator_identity_key_ids_to_disable, })); } @@ -204,7 +204,7 @@ where } drive_operations.push(IdentityOperation(AddNewKeysToIdentity { - identity_id: new_operator_identifier, + identity_id: new_operator_identifier.to_buffer(), unique_keys_to_add, non_unique_keys_to_add, })); @@ -230,7 +230,7 @@ where if !old_operator_identity_key_ids_to_disable.is_empty() { drive_operations.push(IdentityOperation(DisableIdentityKeys { - identity_id: old_operator_identifier, + identity_id: old_operator_identifier.to_buffer(), keys_ids: old_operator_identity_key_ids_to_disable, })); } diff --git a/packages/rs-drive-abci/src/execution/platform_events/core_based_updates/update_masternode_identities/update_voter_identity/v0/mod.rs b/packages/rs-drive-abci/src/execution/platform_events/core_based_updates/update_masternode_identities/update_voter_identity/v0/mod.rs index 7a142ef5d0e..111e30ddc82 100644 --- a/packages/rs-drive-abci/src/execution/platform_events/core_based_updates/update_masternode_identities/update_voter_identity/v0/mod.rs +++ b/packages/rs-drive-abci/src/execution/platform_events/core_based_updates/update_masternode_identities/update_voter_identity/v0/mod.rs @@ -57,7 +57,7 @@ where Self::get_voter_identifier_from_masternode_list_item(old_masternode, platform_version)?; let key_request = IdentityKeysRequest { - identity_id: old_voter_identifier, + identity_id: old_voter_identifier.to_buffer(), request_type: KeyRequestType::AllKeys, limit: None, offset: None, @@ -84,7 +84,7 @@ where ); drive_operations.push(IdentityOperation(DisableIdentityKeys { - identity_id: old_voter_identifier, + identity_id: old_voter_identifier.to_buffer(), keys_ids: old_voter_identity_key_ids, })); @@ -127,7 +127,7 @@ where ); drive_operations.push(IdentityOperation(ReEnableIdentityKeys { - identity_id: old_voter_identifier, + identity_id: old_voter_identifier.into_buffer(), keys_ids: new_voter_identity_key_ids, })); } else { diff --git a/packages/rs-drive-abci/src/execution/types/execution_operation/mod.rs b/packages/rs-drive-abci/src/execution/types/execution_operation/mod.rs index 1eff4575291..d802596ae84 100644 --- a/packages/rs-drive-abci/src/execution/types/execution_operation/mod.rs +++ b/packages/rs-drive-abci/src/execution/types/execution_operation/mod.rs @@ -67,6 +67,7 @@ pub enum ValidationOperation { Protocol(ProtocolValidationOperation), RetrieveIdentity(RetrieveIdentityInfo), RetrievePrefundedSpecializedBalance, + SingleSha256(HashBlockCount), DoubleSha256(HashBlockCount), ValidateKeyStructure(KeyCount), // This is extremely cheap SignatureVerification(SignatureVerificationOperation), @@ -100,6 +101,18 @@ impl ValidationOperation { ValidationOperation::PrecalculatedOperation(precalculated_operation) => { fee_result.checked_add_assign(precalculated_operation.clone())?; } + ValidationOperation::SingleSha256(block_count) => { + fee_result.processing_fee = fee_result + .processing_fee + .checked_add( + platform_version.fee_version.hashing.single_sha256_base + + platform_version.fee_version.hashing.single_sha256_per_block + * (*block_count as u64), + ) + .ok_or(ExecutionError::Overflow( + "execution processing fee overflow error", + ))?; + } ValidationOperation::DoubleSha256(block_count) => { fee_result.processing_fee = fee_result .processing_fee diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/processor/v0/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/processor/v0/mod.rs index eace82dae7e..9ec26800a92 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/processor/v0/mod.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/processor/v0/mod.rs @@ -95,7 +95,7 @@ pub(super) fn process_state_transition_v0<'a, C: CoreRPCLike>( } } - // Only Data contract state transitions do not have basic structure validation + // Only Data contract state transitions and Masternode vote do not have basic structure validation if state_transition.has_basic_structure_validation() { // We validate basic structure validation after verifying the identity, // this is structure validation that does not require state and is already checked on check_tx @@ -181,7 +181,7 @@ pub(super) fn process_state_transition_v0<'a, C: CoreRPCLike>( } } - // Identity create and documents batch both have advanced structure validation with state + // Identity create, documents batch and masternode vote all have advanced structure validation with state let action = if state_transition.has_advanced_structure_validation_with_state() { // Currently used for identity create and documents batch let state_transition_action_result = state_transition.transform_into_action( @@ -752,6 +752,12 @@ impl StateTransitionStructureKnownInStateValidationV0 for StateTransition { platform_version, ) } + StateTransition::MasternodeVote(st) => st.validate_advanced_structure_from_state( + action, + maybe_identity, + execution_context, + platform_version, + ), _ => Ok(ConsensusValidationResult::new()), } } @@ -760,7 +766,9 @@ impl StateTransitionStructureKnownInStateValidationV0 for StateTransition { fn has_advanced_structure_validation_with_state(&self) -> bool { matches!( self, - StateTransition::DocumentsBatch(_) | StateTransition::IdentityCreate(_) + StateTransition::DocumentsBatch(_) + | StateTransition::IdentityCreate(_) + | StateTransition::MasternodeVote(_) ) } diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/masternode_vote/advanced_structure/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/masternode_vote/advanced_structure/mod.rs new file mode 100644 index 00000000000..b5b9d80edf4 --- /dev/null +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/masternode_vote/advanced_structure/mod.rs @@ -0,0 +1,66 @@ +use crate::error::execution::ExecutionError; +use crate::error::Error; +use crate::execution::types::state_transition_execution_context::StateTransitionExecutionContext; +use crate::execution::validation::state_transition::masternode_vote::advanced_structure::v0::MasternodeVoteStateTransitionAdvancedStructureValidationV0; +use crate::execution::validation::state_transition::processor::v0::StateTransitionStructureKnownInStateValidationV0; +use dpp::identity::PartialIdentity; +use dpp::prelude::ConsensusValidationResult; +use dpp::serialization::Signable; +use dpp::state_transition::masternode_vote_transition::MasternodeVoteTransition; +use drive::state_transition_action::StateTransitionAction; +use platform_version::version::PlatformVersion; + +pub(crate) mod v0; + +impl StateTransitionStructureKnownInStateValidationV0 for MasternodeVoteTransition { + fn validate_advanced_structure_from_state( + &self, + action: &StateTransitionAction, + identity: Option<&PartialIdentity>, + execution_context: &mut StateTransitionExecutionContext, + platform_version: &PlatformVersion, + ) -> Result, Error> { + match platform_version + .drive_abci + .validation_and_processing + .state_transitions + .masternode_vote_state_transition + .advanced_structure + { + Some(0) => { + let identity = + identity.ok_or(Error::Execution(ExecutionError::CorruptedCodeExecution( + "The identity must be known on advanced structure validation", + )))?; + let StateTransitionAction::MasternodeVoteAction(masternode_vote_action) = action + else { + return Err(Error::Execution(ExecutionError::CorruptedCodeExecution( + "action must be a masternode vote action", + ))); + }; + self.validate_advanced_structure_from_state_v0( + masternode_vote_action, + identity, + execution_context, + ) + } + Some(version) => Err(Error::Execution(ExecutionError::UnknownVersionMismatch { + method: "masternode vote transition: validate_advanced_structure".to_string(), + known_versions: vec![0], + received: version, + })), + None => Err(Error::Execution(ExecutionError::VersionNotActive { + method: "masternode vote transition: validate_advanced_structure".to_string(), + known_versions: vec![0], + })), + } + } + + fn has_advanced_structure_validation_with_state(&self) -> bool { + true + } + + fn requires_advanced_structure_validation_with_state_on_check_tx(&self) -> bool { + true + } +} diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/masternode_vote/advanced_structure/v0/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/masternode_vote/advanced_structure/v0/mod.rs new file mode 100644 index 00000000000..c75721f44a5 --- /dev/null +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/masternode_vote/advanced_structure/v0/mod.rs @@ -0,0 +1,76 @@ +use crate::error::execution::ExecutionError; +use crate::error::Error; +use crate::execution::types::execution_operation::ValidationOperation; +use crate::execution::types::state_transition_execution_context::{ + StateTransitionExecutionContext, StateTransitionExecutionContextMethodsV0, +}; +use dpp::consensus::state::voting::masternode_incorrect_voter_identity_id_error::MasternodeIncorrectVoterIdentityIdError; +use dpp::consensus::state::voting::masternode_incorrect_voting_address_error::MasternodeIncorrectVotingAddressError; +use dpp::dashcore::hashes::Hash; +use dpp::identifier::MasternodeIdentifiers; +use dpp::identity::hash::IdentityPublicKeyHashMethodsV0; +use dpp::identity::PartialIdentity; +use dpp::prelude::{ConsensusValidationResult, Identifier}; +use dpp::state_transition::masternode_vote_transition::accessors::MasternodeVoteTransitionAccessorsV0; +use dpp::state_transition::masternode_vote_transition::MasternodeVoteTransition; +use dpp::state_transition::StateTransitionIdentitySigned; +use drive::state_transition_action::identity::masternode_vote::MasternodeVoteTransitionAction; +use drive::state_transition_action::StateTransitionAction; + +pub(in crate::execution::validation::state_transition::state_transitions::masternode_vote) trait MasternodeVoteStateTransitionAdvancedStructureValidationV0 +{ + fn validate_advanced_structure_from_state_v0( + &self, + action: &MasternodeVoteTransitionAction, + identity: &PartialIdentity, + execution_context: &mut StateTransitionExecutionContext, + ) -> Result, Error>; +} + +impl MasternodeVoteStateTransitionAdvancedStructureValidationV0 for MasternodeVoteTransition { + fn validate_advanced_structure_from_state_v0( + &self, + action: &MasternodeVoteTransitionAction, + identity: &PartialIdentity, + execution_context: &mut StateTransitionExecutionContext, + ) -> Result, Error> { + let key = identity + .loaded_public_keys + .get(&self.signature_public_key_id()) + .ok_or(Error::Execution(ExecutionError::CorruptedCodeExecution( + "public key must be known", + )))?; + + let voting_address = key.public_key_hash()?; + if action.voting_address() != voting_address { + return Ok(ConsensusValidationResult::new_with_error( + MasternodeIncorrectVotingAddressError::new( + self.pro_tx_hash(), + action.voting_address().into(), + voting_address.into(), + ) + .into(), + )); + } + + // We also need to verify that the provided voter_id is correct + + execution_context.add_operation(ValidationOperation::SingleSha256(2)); + + let expected_voter_identity_id = + Identifier::create_voter_identifier(self.pro_tx_hash().as_bytes(), &voting_address); + + if expected_voter_identity_id != self.voter_identity_id() { + return Ok(ConsensusValidationResult::new_with_error( + MasternodeIncorrectVoterIdentityIdError::new( + self.pro_tx_hash(), + expected_voter_identity_id, + self.voter_identity_id(), + ) + .into(), + )); + } + + Ok(ConsensusValidationResult::new()) + } +} diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/masternode_vote/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/masternode_vote/mod.rs index 278bbdc735a..2e436f5200e 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/masternode_vote/mod.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/masternode_vote/mod.rs @@ -1,7 +1,7 @@ +mod advanced_structure; mod balance; mod nonce; mod state; -mod structure; mod transform_into_action; use dpp::block::block_info::BlockInfo; @@ -58,7 +58,7 @@ impl StateTransitionActionTransformerV0 for MasternodeVoteTransition { impl StateTransitionStateValidationV0 for MasternodeVoteTransition { fn validate_state( &self, - _action: Option, + action: Option, platform: &PlatformRef, _validation_mode: ValidationMode, _block_info: &BlockInfo, @@ -74,7 +74,7 @@ impl StateTransitionStateValidationV0 for MasternodeVoteTransition { .masternode_vote_state_transition .state { - 0 => self.validate_state_v0(platform, tx, platform_version), + 0 => self.validate_state_v0(action, platform, tx, platform_version), version => Err(Error::Execution(ExecutionError::UnknownVersionMismatch { method: "masternode votes state transition: validate_state".to_string(), known_versions: vec![0], @@ -1253,19 +1253,8 @@ mod tests { get_contested_resource_vote_state_request_v0, GetContestedResourceVoteStateRequestV0, }; - use dapi_grpc::platform::v0::get_contested_resource_vote_state_response::{ - get_contested_resource_vote_state_response_v0, - GetContestedResourceVoteStateResponseV0, - }; use dapi_grpc::platform::v0::{ - get_contested_resource_vote_state_request, - get_contested_resource_vote_state_response, GetContestedResourceVoteStateRequest, - }; - use dpp::document::Document; - use dpp::voting::contender_structs::{Contender, ContenderV0}; - use drive::query::vote_poll_vote_state_query::{ - ContestedDocumentVotePollDriveQueryResultType, - ResolvedContestedDocumentVotePollDriveQuery, + get_contested_resource_vote_state_request, GetContestedResourceVoteStateRequest, }; #[test] @@ -1285,7 +1274,7 @@ mod tests { platform_version, ); - let (masternode_1, signer_1, voting_key_1) = + let (pro_tx_hash_1, _masternode_1, signer_1, voting_key_1) = setup_masternode_identity(&mut platform, 29, platform_version); let platform_state = platform.state.load(); @@ -1297,7 +1286,7 @@ mod tests { TowardsIdentity(contender_1.id()), "quantum", &signer_1, - masternode_1.id(), + pro_tx_hash_1, &voting_key_1, 1, None, @@ -1435,7 +1424,7 @@ mod tests { platform_version, ); - let (masternode_1, signer_1, voting_key_1) = + let (pro_tx_hash_1, masternode_1, signer_1, voting_key_1) = setup_masternode_identity(&mut platform, 29, platform_version); let platform_state = platform.state.load(); @@ -1447,7 +1436,7 @@ mod tests { TowardsIdentity(contender_1.id()), "quantum", &signer_1, - masternode_1.id(), + pro_tx_hash_1, &voting_key_1, 1, None, @@ -2618,7 +2607,7 @@ mod tests { ); for i in 0..50 { - let (masternode, signer, voting_key) = + let (pro_tx_hash, masternode, signer, voting_key) = setup_masternode_identity(&mut platform, 10 + i, platform_version); let platform_state = platform.state.load(); @@ -2630,7 +2619,7 @@ mod tests { TowardsIdentity(contender_1.id()), "quantum", &signer, - masternode.id(), + pro_tx_hash, &voting_key, 1, None, @@ -2639,7 +2628,7 @@ mod tests { } for i in 0..5 { - let (masternode, signer, voting_key) = + let (pro_tx_hash, masternode, signer, voting_key) = setup_masternode_identity(&mut platform, 100 + i, platform_version); let platform_state = platform.state.load(); @@ -2651,7 +2640,7 @@ mod tests { TowardsIdentity(contender_2.id()), "quantum", &signer, - masternode.id(), + pro_tx_hash, &voting_key, 1, None, @@ -2660,7 +2649,7 @@ mod tests { } for i in 0..8 { - let (masternode, signer, voting_key) = + let (pro_tx_hash, masternode, signer, voting_key) = setup_masternode_identity(&mut platform, 200 + i, platform_version); let platform_state = platform.state.load(); @@ -2672,7 +2661,7 @@ mod tests { TowardsIdentity(contender_3.id()), "quantum", &signer, - masternode.id(), + pro_tx_hash, &voting_key, 1, None, @@ -2742,7 +2731,7 @@ mod tests { // let's add another 50 votes for i in 0..50 { - let (masternode, signer, voting_key) = + let (pro_tx_hash, masternode, signer, voting_key) = setup_masternode_identity(&mut platform, 400 + i, platform_version); let platform_state = platform.state.load(); @@ -2754,7 +2743,7 @@ mod tests { TowardsIdentity(contender_1.id()), "quantum", &signer, - masternode.id(), + pro_tx_hash, &voting_key, 1, None, @@ -2778,7 +2767,7 @@ mod tests { // let's add another vote for i in 0..1 { - let (masternode, signer, voting_key) = + let (pro_tx_hash, masternode, signer, voting_key) = setup_masternode_identity(&mut platform, 500 + i, platform_version); let platform_state = platform.state.load(); @@ -2790,7 +2779,7 @@ mod tests { TowardsIdentity(contender_1.id()), "quantum", &signer, - masternode.id(), + pro_tx_hash, &voting_key, 1, None, @@ -2861,7 +2850,7 @@ mod tests { ); for i in 0..50 { - let (masternode, signer, voting_key) = + let (pro_tx_hash, masternode, signer, voting_key) = setup_masternode_identity(&mut platform, 10 + i, platform_version); let platform_state = platform.state.load(); @@ -2873,7 +2862,7 @@ mod tests { TowardsIdentity(contender_1.id()), "quantum", &signer, - masternode.id(), + pro_tx_hash, &voting_key, 1, None, @@ -2882,7 +2871,7 @@ mod tests { } for i in 0..5 { - let (masternode, signer, voting_key) = + let (pro_tx_hash, masternode, signer, voting_key) = setup_masternode_identity(&mut platform, 100 + i, platform_version); let platform_state = platform.state.load(); @@ -2894,7 +2883,7 @@ mod tests { TowardsIdentity(contender_2.id()), "quantum", &signer, - masternode.id(), + pro_tx_hash, &voting_key, 1, None, @@ -2903,7 +2892,7 @@ mod tests { } for i in 0..8 { - let (masternode, signer, voting_key) = + let (pro_tx_hash, masternode, signer, voting_key) = setup_masternode_identity(&mut platform, 200 + i, platform_version); let platform_state = platform.state.load(); @@ -2915,7 +2904,7 @@ mod tests { TowardsIdentity(contender_3.id()), "quantum", &signer, - masternode.id(), + pro_tx_hash, &voting_key, 1, None, @@ -3178,7 +3167,7 @@ mod tests { platform_version, ); - let (masternode, signer, voting_key) = + let (pro_tx_hash, _masternode, signer, voting_key) = setup_masternode_identity(&mut platform, 10, platform_version); // Now let's perform a few votes @@ -3192,7 +3181,7 @@ mod tests { TowardsIdentity(contender_1_quantum.id()), "quantum", &signer, - masternode.id(), + pro_tx_hash, &voting_key, 1, None, @@ -3208,7 +3197,7 @@ mod tests { TowardsIdentity(contender_2_cooldog.id()), "cooldog", &signer, - masternode.id(), + pro_tx_hash, &voting_key, 2, None, @@ -3224,7 +3213,7 @@ mod tests { ResourceVoteChoice::Lock, "superman", &signer, - masternode.id(), + pro_tx_hash, &voting_key, 3, None, @@ -3235,7 +3224,7 @@ mod tests { &platform, &platform_state, &dpns_contract, - masternode.id(), + pro_tx_hash, None, true, None, @@ -3340,7 +3329,7 @@ mod tests { platform_version, ); - let (masternode, signer, voting_key) = + let (pro_tx_hash, _masternode, signer, voting_key) = setup_masternode_identity(&mut platform, 10, platform_version); // Now let's perform a few votes @@ -3354,7 +3343,7 @@ mod tests { TowardsIdentity(contender_1_quantum.id()), "quantum", &signer, - masternode.id(), + pro_tx_hash, &voting_key, 1, None, @@ -3370,7 +3359,7 @@ mod tests { TowardsIdentity(contender_2_cooldog.id()), "cooldog", &signer, - masternode.id(), + pro_tx_hash, &voting_key, 2, None, @@ -3386,7 +3375,7 @@ mod tests { ResourceVoteChoice::Lock, "superman", &signer, - masternode.id(), + pro_tx_hash, &voting_key, 3, None, @@ -3397,7 +3386,7 @@ mod tests { &platform, &platform_state, &dpns_contract, - masternode.id(), + pro_tx_hash, None, true, None, @@ -5083,7 +5072,7 @@ mod tests { assert_eq!(start_balance_after_more_contenders, dash_to_credits!(0.8)); for i in 0..50 { - let (masternode, signer, voting_key) = + let (pro_tx_hash, masternode, signer, voting_key) = setup_masternode_identity(&mut platform, 10 + i, platform_version); let platform_state = platform.state.load(); @@ -5095,7 +5084,7 @@ mod tests { TowardsIdentity(contender_1.id()), "quantum", &signer, - masternode.id(), + pro_tx_hash, &voting_key, 1, None, @@ -5114,7 +5103,7 @@ mod tests { assert_eq!(balance_after_50_votes, dash_to_credits!(0.795)); for i in 0..5 { - let (masternode, signer, voting_key) = + let (pro_tx_hash, masternode, signer, voting_key) = setup_masternode_identity(&mut platform, 100 + i, platform_version); let platform_state = platform.state.load(); @@ -5126,7 +5115,7 @@ mod tests { TowardsIdentity(contender_2.id()), "quantum", &signer, - masternode.id(), + pro_tx_hash, &voting_key, 1, None, @@ -5191,7 +5180,7 @@ mod tests { assert_eq!(start_balance_after_more_contenders, dash_to_credits!(0.8)); for i in 0..50 { - let (masternode, signer, voting_key) = + let (pro_tx_hash, masternode, signer, voting_key) = setup_masternode_identity(&mut platform, 10 + i, platform_version); let platform_state = platform.state.load(); @@ -5203,7 +5192,7 @@ mod tests { TowardsIdentity(contender_1.id()), "quantum", &signer, - masternode.id(), + pro_tx_hash, &voting_key, 1, None, @@ -5222,7 +5211,7 @@ mod tests { assert_eq!(balance_after_50_votes, dash_to_credits!(0.795)); for i in 0..5 { - let (masternode, signer, voting_key) = + let (pro_tx_hash, masternode, signer, voting_key) = setup_masternode_identity(&mut platform, 100 + i, platform_version); let platform_state = platform.state.load(); @@ -5234,7 +5223,7 @@ mod tests { TowardsIdentity(contender_2.id()), "quantum", &signer, - masternode.id(), + pro_tx_hash, &voting_key, 1, None, @@ -6466,7 +6455,7 @@ mod tests { platform_version, ); - let (masternode, signer, voting_key) = + let (pro_tx_hash, _masternode, signer, voting_key) = setup_masternode_identity(&mut platform, 10, platform_version); let platform_state = platform.state.load(); @@ -6478,7 +6467,7 @@ mod tests { TowardsIdentity(contender_1.id()), "quantum", &signer, - masternode.id(), + pro_tx_hash, &voting_key, 1, None, @@ -6492,7 +6481,7 @@ mod tests { TowardsIdentity(contender_1.id()), "quantum", &signer, - masternode.id(), + pro_tx_hash, &voting_key, 2, Some("Masternode vote is already present for masternode 4iroeiNBeBYZetCt21kW7FGyczE8WqoqzZ48YAHwyV7R voting for ContestedDocumentResourceVotePoll(ContestedDocumentResourceVotePoll { contract_id: GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec, document_type_name: domain, index_name: parentNameAndLabel, index_values: [string dash, string quantum] })"), @@ -6517,7 +6506,7 @@ mod tests { platform_version, ); - let (masternode, signer, voting_key) = + let (pro_tx_hash, _masternode, signer, voting_key) = setup_masternode_identity(&mut platform, 10, platform_version); let platform_state = platform.state.load(); @@ -6529,7 +6518,7 @@ mod tests { TowardsIdentity(contender_1.id()), "quantum", &signer, - masternode.id(), + pro_tx_hash, &voting_key, 1, None, @@ -6543,7 +6532,7 @@ mod tests { TowardsIdentity(contender_2.id()), "quantum", &signer, - masternode.id(), + pro_tx_hash, &voting_key, 2, None, @@ -6598,7 +6587,7 @@ mod tests { platform_version, ); - let (masternode, signer, voting_key) = + let (pro_tx_hash, _masternode, signer, voting_key) = setup_masternode_identity(&mut platform, 10, platform_version); let platform_state = platform.state.load(); @@ -6610,7 +6599,7 @@ mod tests { TowardsIdentity(contender_1.id()), "quantum", &signer, - masternode.id(), + pro_tx_hash, &voting_key, 1, None, @@ -6624,7 +6613,7 @@ mod tests { TowardsIdentity(contender_2.id()), "quantum", &signer, - masternode.id(), + pro_tx_hash, &voting_key, 2, None, @@ -6638,7 +6627,7 @@ mod tests { Lock, "quantum", &signer, - masternode.id(), + pro_tx_hash, &voting_key, 3, None, @@ -6652,7 +6641,7 @@ mod tests { Abstain, "quantum", &signer, - masternode.id(), + pro_tx_hash, &voting_key, 4, None, @@ -6666,7 +6655,7 @@ mod tests { TowardsIdentity(contender_1.id()), "quantum", &signer, - masternode.id(), + pro_tx_hash, &voting_key, 5, None, @@ -6680,7 +6669,7 @@ mod tests { TowardsIdentity(contender_2.id()), "quantum", &signer, - masternode.id(), + pro_tx_hash, &voting_key, 6, Some("Masternode with id: 4iroeiNBeBYZetCt21kW7FGyczE8WqoqzZ48YAHwyV7R already voted 5 times and is trying to vote again, they can only vote 5 times"), @@ -6766,7 +6755,7 @@ mod tests { .expect("expected a vector of 50 masternode identities") .iter() .take(10) - .map(|(identity, _, _)| identity.id()) + .map(|(pro_tx_hash, _, _, _)| *pro_tx_hash) .collect(); let platform_state_before_masternode_identity_removals = diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/masternode_vote/state/v0/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/masternode_vote/state/v0/mod.rs index 81c6587bd8a..cde77903a56 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/masternode_vote/state/v0/mod.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/masternode_vote/state/v0/mod.rs @@ -8,7 +8,7 @@ use dpp::consensus::ConsensusError; use dpp::prelude::ConsensusValidationResult; use dpp::state_transition::masternode_vote_transition::MasternodeVoteTransition; -use crate::execution::validation::state_transition::masternode_vote::transform_into_action::v0::MasternodeVoteStateTransitionTransformIntoActionValidationV0; +use crate::error::execution::ExecutionError; use dpp::version::PlatformVersion; use dpp::voting::vote_info_storage::contested_document_vote_poll_stored_info::{ ContestedDocumentVotePollStatus, ContestedDocumentVotePollStoredInfoV0Getters, @@ -23,6 +23,7 @@ pub(in crate::execution::validation::state_transition::state_transitions::master { fn validate_state_v0( &self, + action: Option, platform: &PlatformRef, tx: TransactionArg, platform_version: &PlatformVersion, @@ -32,20 +33,20 @@ pub(in crate::execution::validation::state_transition::state_transitions::master impl MasternodeVoteStateTransitionStateValidationV0 for MasternodeVoteTransition { fn validate_state_v0( &self, + action: Option, platform: &PlatformRef, tx: TransactionArg, platform_version: &PlatformVersion, ) -> Result, Error> { - let result = self.transform_into_action_v0(platform, tx, platform_version)?; - - if !result.is_valid() { - return Ok(ConsensusValidationResult::new_with_errors(result.errors)); - } - - let action = result.into_data()?; + let Some(StateTransitionAction::MasternodeVoteAction(masternode_vote_action)) = action + else { + return Err(Error::Execution(ExecutionError::CorruptedCodeExecution( + "action should be known in validate state for masternode vote transition", + ))); + }; // We need to make sure that the vote poll exists and is in started state - match action.vote_ref() { + match masternode_vote_action.vote_ref() { ResolvedVote::ResolvedResourceVote(resource_vote) => { let vote_poll = resource_vote.vote_poll(); match vote_poll { @@ -85,7 +86,9 @@ impl MasternodeVoteStateTransitionStateValidationV0 for MasternodeVoteTransition )) } ContestedDocumentVotePollStatus::Started(_) => { - Ok(ConsensusValidationResult::new_with_data(action.into())) + Ok(ConsensusValidationResult::new_with_data( + masternode_vote_action.into(), + )) } } } diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/masternode_vote/structure/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/masternode_vote/structure/mod.rs deleted file mode 100644 index 9a1925de7fc..00000000000 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/masternode_vote/structure/mod.rs +++ /dev/null @@ -1 +0,0 @@ -pub(crate) mod v0; diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/masternode_vote/structure/v0/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/masternode_vote/structure/v0/mod.rs deleted file mode 100644 index f8073c437de..00000000000 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/masternode_vote/structure/v0/mod.rs +++ /dev/null @@ -1,17 +0,0 @@ -// use dpp::platform_value:: -use crate::error::Error; -use dpp::state_transition::masternode_vote_transition::MasternodeVoteTransition; -use dpp::validation::SimpleConsensusValidationResult; - -pub(in crate::execution::validation::state_transition::state_transitions::masternode_vote) trait MasternodeVoteStateTransitionStructureValidationV0 -{ - fn validate_base_structure_v0(&self) -> Result; -} - -impl MasternodeVoteStateTransitionStructureValidationV0 for MasternodeVoteTransition { - fn validate_base_structure_v0(&self) -> Result { - let result = SimpleConsensusValidationResult::new(); - - Ok(result) - } -} diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/masternode_vote/transform_into_action/v0/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/masternode_vote/transform_into_action/v0/mod.rs index d5dcb1aa631..6ce39536b41 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/masternode_vote/transform_into_action/v0/mod.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/masternode_vote/transform_into_action/v0/mod.rs @@ -2,6 +2,7 @@ use crate::error::Error; use crate::platform_types::platform::PlatformRef; use dashcore_rpc::dashcore_rpc_json::MasternodeType; use dpp::consensus::state::state_error::StateError; +use dpp::consensus::state::voting::masternode_incorrect_voting_address_error::MasternodeIncorrectVotingAddressError; use dpp::consensus::state::voting::masternode_not_found_error::MasternodeNotFoundError; use dpp::consensus::state::voting::masternode_vote_already_present_error::MasternodeVoteAlreadyPresentError; use dpp::consensus::state::voting::masternode_voted_too_many_times::MasternodeVotedTooManyTimesError; @@ -120,6 +121,7 @@ impl MasternodeVoteStateTransitionTransformIntoActionValidationV0 for Masternode Ok(ConsensusValidationResult::new_with_data( MasternodeVoteTransitionAction::transform_from_transition( self, + masternode.state.voting_address, strength, previous_resource_vote_choice_to_remove, platform.drive, diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/mod.rs index 8fb200a5deb..6966ee0ae40 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/mod.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/mod.rs @@ -84,7 +84,9 @@ mod tests { use dpp::data_contract::document_type::random_document::{CreateRandomDocument, DocumentFieldFillSize, DocumentFieldFillType}; use dpp::document::{Document, DocumentV0Getters, DocumentV0Setters}; use dpp::document::serialization_traits::DocumentPlatformConversionMethodsV0; + use dpp::identifier::MasternodeIdentifiers; use dpp::identity::accessors::IdentityGettersV0; + use dpp::identity::hash::IdentityPublicKeyHashMethodsV0; use dpp::platform_value::{Bytes32, Value}; use dpp::serialization::PlatformSerializable; use dpp::state_transition::documents_batch_transition::DocumentsBatchTransition; @@ -172,7 +174,7 @@ mod tests { platform: &mut TempPlatform, seed: u64, platform_version: &PlatformVersion, - ) -> (Identity, SimpleSigner, IdentityPublicKey) { + ) -> (Identifier, Identity, SimpleSigner, IdentityPublicKey) { let mut signer = SimpleSigner::default(); let mut rng = StdRng::seed_from_u64(seed); @@ -183,8 +185,17 @@ mod tests { signer.add_key(voting_key.clone(), voting_private_key.clone()); + let pro_tx_hash_bytes: [u8; 32] = rng.gen(); + + let voting_address = voting_key + .public_key_hash() + .expect("expected a public key hash"); + + let voter_identifier = + Identifier::create_voter_identifier(&pro_tx_hash_bytes, &voting_address); + let identity: Identity = IdentityV0 { - id: Identifier::random_with_rng(&mut rng), + id: voter_identifier, public_keys: BTreeMap::from([(0, voting_key.clone())]), balance: 0, revision: 0, @@ -207,7 +218,7 @@ mod tests { let mut platform_state = platform.state.load().clone().deref().clone(); - let pro_tx_hash = ProTxHash::from_byte_array(identity.id().to_buffer()); + let pro_tx_hash = ProTxHash::from_byte_array(pro_tx_hash_bytes); let random_ip = Ipv4Addr::new( rng.gen_range(0..255), @@ -232,7 +243,7 @@ mod tests { pose_ban_height: None, revocation_reason: 0, owner_address: rng.gen(), - voting_address: rng.gen(), + voting_address, payout_address: rng.gen(), pub_key_operator: vec![], operator_payout_address: None, @@ -245,7 +256,7 @@ mod tests { platform.state.store(Arc::new(platform_state)); - (identity, signer, voting_key) + (pro_tx_hash_bytes.into(), identity, signer, voting_key) } pub(in crate::execution::validation::state_transition::state_transitions) fn take_down_masternode_identities( @@ -930,7 +941,7 @@ mod tests { resource_vote_choice: ResourceVoteChoice, name: &str, signer: &SimpleSigner, - masternode_id: Identifier, + pro_tx_hash: Identifier, voting_key: &IdentityPublicKey, nonce: IdentityNonce, expect_error: Option<&str>, @@ -956,7 +967,7 @@ mod tests { let masternode_vote_transition = MasternodeVoteTransition::try_from_vote_with_signer( vote, signer, - masternode_id, + pro_tx_hash, voting_key, nonce, platform_version, @@ -1008,10 +1019,10 @@ mod tests { count: u64, start_seed: u64, platform_version: &PlatformVersion, - ) -> Vec<(Identity, SimpleSigner, IdentityPublicKey)> { + ) -> Vec<(Identifier, Identity, SimpleSigner, IdentityPublicKey)> { let mut masternode_infos = vec![]; for i in 0..count { - let (masternode, signer, voting_key) = + let (pro_tx_hash_bytes, voting_identity, signer, voting_key) = setup_masternode_identity(platform, start_seed + i, platform_version); let platform_state = platform.state.load(); @@ -1023,14 +1034,14 @@ mod tests { resource_vote_choice, name, &signer, - masternode.id(), + pro_tx_hash_bytes, &voting_key, 1, None, platform_version, ); - masternode_infos.push((masternode, signer, voting_key)); + masternode_infos.push((pro_tx_hash_bytes, voting_identity, signer, voting_key)); } masternode_infos } @@ -1042,7 +1053,8 @@ mod tests { name: &str, start_seed: u64, platform_version: &PlatformVersion, - ) -> BTreeMap> { + ) -> BTreeMap> + { let mut count_aggregate = start_seed; let mut masternodes_by_vote_choice = BTreeMap::new(); for (resource_vote_choice, count) in resource_vote_choices.into_iter() { diff --git a/packages/rs-drive-abci/tests/strategy_tests/query.rs b/packages/rs-drive-abci/tests/strategy_tests/query.rs index c8825c7dfef..899d3f2b85e 100644 --- a/packages/rs-drive-abci/tests/strategy_tests/query.rs +++ b/packages/rs-drive-abci/tests/strategy_tests/query.rs @@ -221,7 +221,7 @@ impl QueryStrategy { let key_num = rng.gen_range(0..unique_public_keys.len()); let public_key = unique_public_keys[key_num].1; Some(( - public_key.hash().unwrap(), + public_key.public_key_hash().unwrap(), identity.clone().into_partial_identity_info_no_balance(), )) } diff --git a/packages/rs-drive/src/drive/batch/transitions/identity/masternode_vote_transition.rs b/packages/rs-drive/src/drive/batch/transitions/identity/masternode_vote_transition.rs index 7615ab8806d..8f5e4c98862 100644 --- a/packages/rs-drive/src/drive/batch/transitions/identity/masternode_vote_transition.rs +++ b/packages/rs-drive/src/drive/batch/transitions/identity/masternode_vote_transition.rs @@ -17,6 +17,7 @@ impl DriveHighLevelOperationConverter for MasternodeVoteTransitionAction { _epoch: &Epoch, platform_version: &PlatformVersion, ) -> Result>, Error> { + let voter_identity_id = self.voter_identity_id(); let pro_tx_hash = self.pro_tx_hash(); let nonce = self.nonce(); let strength = self.vote_strength(); @@ -27,10 +28,11 @@ impl DriveHighLevelOperationConverter for MasternodeVoteTransitionAction { let drive_operations = vec![ IdentityOperation(IdentityOperationType::UpdateIdentityNonce { - identity_id: pro_tx_hash.into_buffer(), + identity_id: voter_identity_id.into_buffer(), nonce, }), IdentityOperation(IdentityOperationType::MasternodeCastVote { + // Votes are cast based on masternode pro_tx_hash, and not the voter identity id voter_pro_tx_hash: pro_tx_hash.to_buffer(), strength, vote, diff --git a/packages/rs-drive/src/drive/contract/prove/prove_contracts/v0/mod.rs b/packages/rs-drive/src/drive/contract/prove/prove_contracts/v0/mod.rs index 5dc4b5daa7c..fbf7cd32694 100644 --- a/packages/rs-drive/src/drive/contract/prove/prove_contracts/v0/mod.rs +++ b/packages/rs-drive/src/drive/contract/prove/prove_contracts/v0/mod.rs @@ -38,6 +38,7 @@ impl Drive { // we first need to fetch all contracts let contracts = self.grove_get_raw_path_query_with_optional( &contracts_query, + true, transaction, &mut vec![], &platform_version.drive, diff --git a/packages/rs-drive/src/drive/grove_operations/grove_get_raw_path_query_with_optional/mod.rs b/packages/rs-drive/src/drive/grove_operations/grove_get_raw_path_query_with_optional/mod.rs index ea275621730..0efd91799cf 100644 --- a/packages/rs-drive/src/drive/grove_operations/grove_get_raw_path_query_with_optional/mod.rs +++ b/packages/rs-drive/src/drive/grove_operations/grove_get_raw_path_query_with_optional/mod.rs @@ -24,6 +24,7 @@ impl Drive { pub fn grove_get_raw_path_query_with_optional( &self, path_query: &PathQuery, + error_if_intermediate_path_tree_not_present: bool, transaction: TransactionArg, drive_operations: &mut Vec, drive_version: &DriveVersion, @@ -35,6 +36,7 @@ impl Drive { { 0 => self.grove_get_raw_path_query_with_optional_v0( path_query, + error_if_intermediate_path_tree_not_present, transaction, drive_operations, ), diff --git a/packages/rs-drive/src/drive/grove_operations/grove_get_raw_path_query_with_optional/v0/mod.rs b/packages/rs-drive/src/drive/grove_operations/grove_get_raw_path_query_with_optional/v0/mod.rs index f285d941a89..ee4188f2133 100644 --- a/packages/rs-drive/src/drive/grove_operations/grove_get_raw_path_query_with_optional/v0/mod.rs +++ b/packages/rs-drive/src/drive/grove_operations/grove_get_raw_path_query_with_optional/v0/mod.rs @@ -12,12 +12,17 @@ impl Drive { pub(super) fn grove_get_raw_path_query_with_optional_v0( &self, path_query: &PathQuery, + error_if_intermediate_path_tree_not_present: bool, transaction: TransactionArg, drive_operations: &mut Vec, ) -> Result, Error> { - let CostContext { value, cost } = - self.grove - .query_raw_keys_optional(path_query, true, true, true, transaction); + let CostContext { value, cost } = self.grove.query_raw_keys_optional( + path_query, + true, + true, + error_if_intermediate_path_tree_not_present, + transaction, + ); drive_operations.push(CalculatedCostOperation(cost)); value.map_err(Error::GroveDB) } diff --git a/packages/rs-drive/src/drive/identity/fetch/fetch_by_public_key_hashes/fetch_identity_ids_by_unique_public_key_hashes/v0/mod.rs b/packages/rs-drive/src/drive/identity/fetch/fetch_by_public_key_hashes/fetch_identity_ids_by_unique_public_key_hashes/v0/mod.rs index f68ac5b6aa0..e9dbc2869da 100644 --- a/packages/rs-drive/src/drive/identity/fetch/fetch_by_public_key_hashes/fetch_identity_ids_by_unique_public_key_hashes/v0/mod.rs +++ b/packages/rs-drive/src/drive/identity/fetch/fetch_by_public_key_hashes/fetch_identity_ids_by_unique_public_key_hashes/v0/mod.rs @@ -49,6 +49,7 @@ impl Drive { let path_query = PathQuery::new(unique_key_hashes, sized_query); self.grove_get_raw_path_query_with_optional( &path_query, + true, transaction, drive_operations, &platform_version.drive, diff --git a/packages/rs-drive/src/drive/identity/fetch/fetch_by_public_key_hashes/mod.rs b/packages/rs-drive/src/drive/identity/fetch/fetch_by_public_key_hashes/mod.rs index 04a935c7533..322ee93ec8b 100644 --- a/packages/rs-drive/src/drive/identity/fetch/fetch_by_public_key_hashes/mod.rs +++ b/packages/rs-drive/src/drive/identity/fetch/fetch_by_public_key_hashes/mod.rs @@ -58,7 +58,7 @@ mod tests { assert_eq!(public_keys.len(), 5); for (_, key) in public_keys { - let hash = key.hash().expect("expected to get hash"); + let hash = key.public_key_hash().expect("expected to get hash"); if key.key_type().is_unique_key_type() { let identity_id = drive .fetch_identity_id_by_unique_public_key_hash( diff --git a/packages/rs-drive/src/drive/identity/fetch/prove/prove_full_identities_by_unique_public_key_hashes/v0/mod.rs b/packages/rs-drive/src/drive/identity/fetch/prove/prove_full_identities_by_unique_public_key_hashes/v0/mod.rs index 592adeafe05..517b4d38f6a 100644 --- a/packages/rs-drive/src/drive/identity/fetch/prove/prove_full_identities_by_unique_public_key_hashes/v0/mod.rs +++ b/packages/rs-drive/src/drive/identity/fetch/prove/prove_full_identities_by_unique_public_key_hashes/v0/mod.rs @@ -89,7 +89,9 @@ mod tests { .filter(|public_key| public_key.key_type().is_unique_key_type()) .map(move |public_key| { ( - public_key.hash().expect("expected to be 20 bytes"), + public_key + .public_key_hash() + .expect("expected to be 20 bytes"), Some(identity.clone()), ) }) @@ -105,7 +107,9 @@ mod tests { .filter(|public_key| public_key.key_type().is_unique_key_type()) .map(move |public_key| { ( - public_key.hash().expect("expected to be 20 bytes"), + public_key + .public_key_hash() + .expect("expected to be 20 bytes"), Some(identity.id().to_buffer()), ) }) diff --git a/packages/rs-drive/src/drive/identity/fetch/prove/prove_full_identity_by_unique_public_key_hash/v0/mod.rs b/packages/rs-drive/src/drive/identity/fetch/prove/prove_full_identity_by_unique_public_key_hash/v0/mod.rs index 51a3f8f3efd..daddf41b23d 100644 --- a/packages/rs-drive/src/drive/identity/fetch/prove/prove_full_identity_by_unique_public_key_hash/v0/mod.rs +++ b/packages/rs-drive/src/drive/identity/fetch/prove/prove_full_identity_by_unique_public_key_hash/v0/mod.rs @@ -79,7 +79,7 @@ mod tests { .values() .find(|public_key| public_key.key_type().is_unique_key_type()) .expect("expected a unique key") - .hash() + .public_key_hash() .expect("expected to hash data"); let proof = drive diff --git a/packages/rs-drive/src/drive/identity/fetch/prove/prove_identity_id_by_unique_public_key_hash/v0/mod.rs b/packages/rs-drive/src/drive/identity/fetch/prove/prove_identity_id_by_unique_public_key_hash/v0/mod.rs index 38ba9a005c1..4e148bf7919 100644 --- a/packages/rs-drive/src/drive/identity/fetch/prove/prove_identity_id_by_unique_public_key_hash/v0/mod.rs +++ b/packages/rs-drive/src/drive/identity/fetch/prove/prove_identity_id_by_unique_public_key_hash/v0/mod.rs @@ -60,7 +60,7 @@ mod tests { .values() .find(|public_key| public_key.key_type().is_unique_key_type()) .expect("expected a unique key") - .hash() + .public_key_hash() .expect("expected to hash data"); let proof = drive diff --git a/packages/rs-drive/src/drive/identity/fetch/prove/prove_identity_ids_by_unique_public_key_hashes/v0/mod.rs b/packages/rs-drive/src/drive/identity/fetch/prove/prove_identity_ids_by_unique_public_key_hashes/v0/mod.rs index a0c5b03100d..20bafb60162 100644 --- a/packages/rs-drive/src/drive/identity/fetch/prove/prove_identity_ids_by_unique_public_key_hashes/v0/mod.rs +++ b/packages/rs-drive/src/drive/identity/fetch/prove/prove_identity_ids_by_unique_public_key_hashes/v0/mod.rs @@ -71,7 +71,9 @@ mod tests { .filter(|public_key| public_key.key_type().is_unique_key_type()) .map(move |public_key| { ( - public_key.hash().expect("expected to be 20 bytes"), + public_key + .public_key_hash() + .expect("expected to be 20 bytes"), Some(identity.id().to_buffer()), ) }) diff --git a/packages/rs-drive/src/drive/identity/key/fetch/fetch_identity_keys/v0/mod.rs b/packages/rs-drive/src/drive/identity/key/fetch/fetch_identity_keys/v0/mod.rs index 76bd3f6986b..2521f5eb778 100644 --- a/packages/rs-drive/src/drive/identity/key/fetch/fetch_identity_keys/v0/mod.rs +++ b/packages/rs-drive/src/drive/identity/key/fetch/fetch_identity_keys/v0/mod.rs @@ -56,6 +56,7 @@ impl Drive { let result = self.grove_get_raw_path_query_with_optional( &path_query, + false, transaction, drive_operations, &platform_version.drive, diff --git a/packages/rs-drive/src/drive/identity/key/insert_key_hash_identity_reference/insert_reference_to_non_unique_key/v0/mod.rs b/packages/rs-drive/src/drive/identity/key/insert_key_hash_identity_reference/insert_reference_to_non_unique_key/v0/mod.rs index 9f7301d33c7..c9be32bd6fa 100644 --- a/packages/rs-drive/src/drive/identity/key/insert_key_hash_identity_reference/insert_reference_to_non_unique_key/v0/mod.rs +++ b/packages/rs-drive/src/drive/identity/key/insert_key_hash_identity_reference/insert_reference_to_non_unique_key/v0/mod.rs @@ -28,7 +28,7 @@ impl Drive { drive_version: &DriveVersion, ) -> Result, Error> { let mut drive_operations = vec![]; - let hash_vec = identity_key.hash()?; + let hash_vec = identity_key.public_key_hash()?; let key_hash = hash_vec.as_slice().try_into().map_err(|_| { Error::Drive(DriveError::CorruptedCodeExecution("key hash not 20 bytes")) })?; diff --git a/packages/rs-drive/src/drive/identity/key/insert_key_hash_identity_reference/insert_reference_to_unique_key/v0/mod.rs b/packages/rs-drive/src/drive/identity/key/insert_key_hash_identity_reference/insert_reference_to_unique_key/v0/mod.rs index b7981f71dae..770a3af080d 100644 --- a/packages/rs-drive/src/drive/identity/key/insert_key_hash_identity_reference/insert_reference_to_unique_key/v0/mod.rs +++ b/packages/rs-drive/src/drive/identity/key/insert_key_hash_identity_reference/insert_reference_to_unique_key/v0/mod.rs @@ -28,7 +28,7 @@ impl Drive { drive_version: &DriveVersion, ) -> Result, Error> { let mut drive_operations = vec![]; - let hash_vec = identity_key.hash()?; + let hash_vec = identity_key.public_key_hash()?; let key_hash = hash_vec.as_slice().try_into().map_err(|_| { Error::Drive(DriveError::CorruptedCodeExecution("key hash not 20 bytes")) })?; diff --git a/packages/rs-drive/src/state_transition_action/identity/masternode_vote/mod.rs b/packages/rs-drive/src/state_transition_action/identity/masternode_vote/mod.rs index f5dc84a8de7..53013ef0c12 100644 --- a/packages/rs-drive/src/state_transition_action/identity/masternode_vote/mod.rs +++ b/packages/rs-drive/src/state_transition_action/identity/masternode_vote/mod.rs @@ -27,6 +27,20 @@ impl MasternodeVoteTransitionAction { } } + /// the voter identity id + pub fn voter_identity_id(&self) -> Identifier { + match self { + MasternodeVoteTransitionAction::V0(transition) => transition.voter_identity_id, + } + } + + /// the masternode list state based voting address + pub fn voting_address(&self) -> [u8; 20] { + match self { + MasternodeVoteTransitionAction::V0(transition) => transition.voting_address, + } + } + /// Resource votes pub fn vote_ref(&self) -> &ResolvedVote { match self { diff --git a/packages/rs-drive/src/state_transition_action/identity/masternode_vote/transformer.rs b/packages/rs-drive/src/state_transition_action/identity/masternode_vote/transformer.rs index c9c702fab0f..7b646f6dd8b 100644 --- a/packages/rs-drive/src/state_transition_action/identity/masternode_vote/transformer.rs +++ b/packages/rs-drive/src/state_transition_action/identity/masternode_vote/transformer.rs @@ -4,6 +4,7 @@ use crate::state_transition_action::identity::masternode_vote::v0::{ MasternodeVoteTransitionActionV0, PreviousVoteCount, }; use crate::state_transition_action::identity::masternode_vote::MasternodeVoteTransitionAction; +use dpp::identifier::Identifier; use dpp::state_transition::masternode_vote_transition::MasternodeVoteTransition; use dpp::voting::vote_choices::resource_vote_choice::ResourceVoteChoice; use grovedb::TransactionArg; @@ -15,6 +16,7 @@ impl MasternodeVoteTransitionAction { /// # Parameters /// /// - `value`: The owned `MasternodeVoteTransition` to transform. + /// - `voter_identity_id`: The pre-calculated voter identity id, if it isn't given we will calculate it /// - `masternode_strength`: The strength of the masternode, normal ones have 1, evonodes have 4 /// - `drive`: A reference to the `Drive` instance. /// - `transaction`: The transaction argument. @@ -25,6 +27,7 @@ impl MasternodeVoteTransitionAction { /// A `Result` containing the transformed `MasternodeVoteTransitionAction`, or an `Error` if the transformation fails. pub fn transform_from_owned_transition( value: MasternodeVoteTransition, + voting_address: [u8; 20], masternode_strength: u8, previous_resource_vote_choice_to_remove: Option<(ResourceVoteChoice, PreviousVoteCount)>, drive: &Drive, @@ -35,6 +38,7 @@ impl MasternodeVoteTransitionAction { MasternodeVoteTransition::V0(v0) => Ok( MasternodeVoteTransitionActionV0::transform_from_owned_transition( v0, + voting_address, masternode_strength, previous_resource_vote_choice_to_remove, drive, @@ -51,6 +55,7 @@ impl MasternodeVoteTransitionAction { /// # Parameters /// /// - `value`: A reference to the `MasternodeVoteTransition` to transform. + /// - `voter_identity_id`: The pre-calculated voter identity id, if it isn't given we will calculate it /// - `masternode_strength`: The strength of the masternode, normal ones have 1, evonodes have 4 /// - `drive`: A reference to the `Drive` instance. /// - `transaction`: The transaction argument. @@ -61,6 +66,7 @@ impl MasternodeVoteTransitionAction { /// A `Result` containing the transformed `MasternodeVoteTransitionAction`, or an `Error` if the transformation fails. pub fn transform_from_transition( value: &MasternodeVoteTransition, + voting_address: [u8; 20], masternode_strength: u8, previous_resource_vote_choice_to_remove: Option<(ResourceVoteChoice, PreviousVoteCount)>, drive: &Drive, @@ -71,6 +77,7 @@ impl MasternodeVoteTransitionAction { MasternodeVoteTransition::V0(v0) => { Ok(MasternodeVoteTransitionActionV0::transform_from_transition( v0, + voting_address, masternode_strength, previous_resource_vote_choice_to_remove, drive, diff --git a/packages/rs-drive/src/state_transition_action/identity/masternode_vote/v0/mod.rs b/packages/rs-drive/src/state_transition_action/identity/masternode_vote/v0/mod.rs index 414700a4170..9461bb882cb 100644 --- a/packages/rs-drive/src/state_transition_action/identity/masternode_vote/v0/mod.rs +++ b/packages/rs-drive/src/state_transition_action/identity/masternode_vote/v0/mod.rs @@ -13,6 +13,10 @@ pub type PreviousVoteCount = u16; pub struct MasternodeVoteTransitionActionV0 { /// the pro tx hash identifier of the masternode pub pro_tx_hash: Identifier, + /// The voter identity id is made by hashing the pro_tx_hash and the voting address + pub voter_identity_id: Identifier, + /// The voting address used + pub voting_address: [u8; 20], /// masternode type vote strength, masternodes have 1, evonodes have 4 pub vote_strength: u8, /// the resource votes diff --git a/packages/rs-drive/src/state_transition_action/identity/masternode_vote/v0/transformer.rs b/packages/rs-drive/src/state_transition_action/identity/masternode_vote/v0/transformer.rs index 9966ba6c0f4..53643a327f1 100644 --- a/packages/rs-drive/src/state_transition_action/identity/masternode_vote/v0/transformer.rs +++ b/packages/rs-drive/src/state_transition_action/identity/masternode_vote/v0/transformer.rs @@ -4,6 +4,8 @@ use crate::error::Error; use crate::state_transition_action::identity::masternode_vote::v0::{ MasternodeVoteTransitionActionV0, PreviousVoteCount, }; +use dpp::identifier::MasternodeIdentifiers; +use dpp::prelude::Identifier; use dpp::state_transition::state_transitions::identity::masternode_vote_transition::v0::MasternodeVoteTransitionV0; use dpp::voting::vote_choices::resource_vote_choice::ResourceVoteChoice; use grovedb::TransactionArg; @@ -12,6 +14,7 @@ use platform_version::version::PlatformVersion; impl MasternodeVoteTransitionActionV0 { pub(crate) fn transform_from_owned_transition( value: MasternodeVoteTransitionV0, + voting_address: [u8; 20], masternode_strength: u8, previous_resource_vote_choice_to_remove: Option<(ResourceVoteChoice, PreviousVoteCount)>, drive: &Drive, @@ -20,6 +23,7 @@ impl MasternodeVoteTransitionActionV0 { ) -> Result { let MasternodeVoteTransitionV0 { pro_tx_hash, + voter_identity_id, vote, nonce, .. @@ -27,6 +31,8 @@ impl MasternodeVoteTransitionActionV0 { let resolved_vote = vote.resolve_owned(drive, transaction, platform_version)?; Ok(MasternodeVoteTransitionActionV0 { pro_tx_hash, + voter_identity_id, + voting_address, vote_strength: masternode_strength, vote: resolved_vote, previous_resource_vote_choice_to_remove, @@ -36,6 +42,7 @@ impl MasternodeVoteTransitionActionV0 { pub(crate) fn transform_from_transition( value: &MasternodeVoteTransitionV0, + voting_address: [u8; 20], masternode_strength: u8, previous_resource_vote_choice_to_remove: Option<(ResourceVoteChoice, PreviousVoteCount)>, drive: &Drive, @@ -44,6 +51,7 @@ impl MasternodeVoteTransitionActionV0 { ) -> Result { let MasternodeVoteTransitionV0 { pro_tx_hash, + voter_identity_id, vote, nonce, .. @@ -51,6 +59,8 @@ impl MasternodeVoteTransitionActionV0 { let resolved_vote = vote.resolve(drive, transaction, platform_version)?; Ok(MasternodeVoteTransitionActionV0 { pro_tx_hash: *pro_tx_hash, + voter_identity_id: *voter_identity_id, + voting_address, vote_strength: masternode_strength, vote: resolved_vote, previous_resource_vote_choice_to_remove, diff --git a/packages/rs-platform-value/src/types/bytes_20.rs b/packages/rs-platform-value/src/types/bytes_20.rs index abb156173ae..1baca634b7a 100644 --- a/packages/rs-platform-value/src/types/bytes_20.rs +++ b/packages/rs-platform-value/src/types/bytes_20.rs @@ -1,6 +1,6 @@ use crate::string_encoding::Encoding; use crate::types::encoding_string_to_encoding; -use crate::{string_encoding, Error, Value}; +use crate::{string_encoding, Error, Identifier, Value}; use base64::prelude::BASE64_STANDARD; use base64::Engine; use bincode::{Decode, Encode}; @@ -16,6 +16,11 @@ impl AsRef<[u8]> for Bytes20 { &self.0 } } +impl std::fmt::Display for Bytes20 { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.to_string(Encoding::Base58)) + } +} impl Bytes20 { pub fn new(buffer: [u8; 20]) -> Self { diff --git a/packages/rs-platform-version/src/version/drive_abci_versions.rs b/packages/rs-platform-version/src/version/drive_abci_versions.rs index 9105063036a..e90434f98a9 100644 --- a/packages/rs-platform-version/src/version/drive_abci_versions.rs +++ b/packages/rs-platform-version/src/version/drive_abci_versions.rs @@ -226,12 +226,11 @@ pub struct DriveAbciMasternodeIdentitiesUpdatesMethodVersions { pub get_voter_identity_key: FeatureVersion, pub get_operator_identity_keys: FeatureVersion, pub get_owner_identity_key: FeatureVersion, - pub get_voter_identifier: FeatureVersion, - pub get_operator_identifier: FeatureVersion, + pub get_voter_identifier_from_masternode_list_item: FeatureVersion, + pub get_operator_identifier_from_masternode_list_item: FeatureVersion, pub create_operator_identity: FeatureVersion, pub create_owner_identity: FeatureVersion, pub create_voter_identity: FeatureVersion, - pub hash_protxhash_with_key_data: FeatureVersion, pub disable_identity_keys: FeatureVersion, pub update_masternode_identities: FeatureVersion, pub update_operator_identity: FeatureVersion, diff --git a/packages/rs-platform-version/src/version/mocks/v2_test.rs b/packages/rs-platform-version/src/version/mocks/v2_test.rs index b7afb54b69c..3226a4c1d0a 100644 --- a/packages/rs-platform-version/src/version/mocks/v2_test.rs +++ b/packages/rs-platform-version/src/version/mocks/v2_test.rs @@ -594,12 +594,11 @@ pub const TEST_PLATFORM_V2: PlatformVersion = PlatformVersion { get_voter_identity_key: 0, get_operator_identity_keys: 0, get_owner_identity_key: 0, - get_voter_identifier: 0, - get_operator_identifier: 0, + get_voter_identifier_from_masternode_list_item: 0, + get_operator_identifier_from_masternode_list_item: 0, create_operator_identity: 0, create_owner_identity: 0, create_voter_identity: 0, - hash_protxhash_with_key_data: 0, disable_identity_keys: 0, update_masternode_identities: 0, update_operator_identity: 0, @@ -743,8 +742,8 @@ pub const TEST_PLATFORM_V2: PlatformVersion = PlatformVersion { transform_into_action: 0, }, masternode_vote_state_transition: DriveAbciStateTransitionValidationVersion { - basic_structure: Some(0), - advanced_structure: None, + basic_structure: None, + advanced_structure: Some(0), identity_signatures: None, advanced_minimum_balance_pre_check: Some(0), nonce: Some(0), diff --git a/packages/rs-platform-version/src/version/mocks/v3_test.rs b/packages/rs-platform-version/src/version/mocks/v3_test.rs index cb1fa1403ee..10659e4ceb6 100644 --- a/packages/rs-platform-version/src/version/mocks/v3_test.rs +++ b/packages/rs-platform-version/src/version/mocks/v3_test.rs @@ -594,12 +594,11 @@ pub const TEST_PLATFORM_V3: PlatformVersion = PlatformVersion { get_voter_identity_key: 0, get_operator_identity_keys: 0, get_owner_identity_key: 0, - get_voter_identifier: 0, - get_operator_identifier: 0, + get_voter_identifier_from_masternode_list_item: 0, + get_operator_identifier_from_masternode_list_item: 0, create_operator_identity: 0, create_owner_identity: 0, create_voter_identity: 0, - hash_protxhash_with_key_data: 0, disable_identity_keys: 0, update_masternode_identities: 0, update_operator_identity: 0, @@ -743,8 +742,8 @@ pub const TEST_PLATFORM_V3: PlatformVersion = PlatformVersion { transform_into_action: 0, }, masternode_vote_state_transition: DriveAbciStateTransitionValidationVersion { - basic_structure: Some(0), - advanced_structure: None, + basic_structure: None, + advanced_structure: Some(0), identity_signatures: None, advanced_minimum_balance_pre_check: Some(0), nonce: Some(0), diff --git a/packages/rs-platform-version/src/version/v1.rs b/packages/rs-platform-version/src/version/v1.rs index e8cc2b4857b..9fa917130b0 100644 --- a/packages/rs-platform-version/src/version/v1.rs +++ b/packages/rs-platform-version/src/version/v1.rs @@ -593,12 +593,11 @@ pub const PLATFORM_V1: PlatformVersion = PlatformVersion { get_voter_identity_key: 0, get_operator_identity_keys: 0, get_owner_identity_key: 0, - get_voter_identifier: 0, - get_operator_identifier: 0, + get_voter_identifier_from_masternode_list_item: 0, + get_operator_identifier_from_masternode_list_item: 0, create_operator_identity: 0, create_owner_identity: 0, create_voter_identity: 0, - hash_protxhash_with_key_data: 0, disable_identity_keys: 0, update_masternode_identities: 0, update_operator_identity: 0, @@ -742,8 +741,8 @@ pub const PLATFORM_V1: PlatformVersion = PlatformVersion { transform_into_action: 0, }, masternode_vote_state_transition: DriveAbciStateTransitionValidationVersion { - basic_structure: Some(0), - advanced_structure: None, + basic_structure: None, + advanced_structure: Some(0), identity_signatures: None, advanced_minimum_balance_pre_check: Some(0), nonce: Some(0), diff --git a/packages/rs-sdk/tests/fetch/identity.rs b/packages/rs-sdk/tests/fetch/identity.rs index 56af35020e5..ad5a458960f 100644 --- a/packages/rs-sdk/tests/fetch/identity.rs +++ b/packages/rs-sdk/tests/fetch/identity.rs @@ -45,7 +45,7 @@ async fn test_identity_read_by_key() { .first_key_value() .expect("need at least one pubkey") .1 - .hash() + .public_key_hash() .expect("public key hash"); let identity2 = Identity::fetch(&sdk, PublicKeyHash(key_hash)) diff --git a/packages/wasm-dpp/src/errors/consensus/consensus_error.rs b/packages/wasm-dpp/src/errors/consensus/consensus_error.rs index d9b85d92ca1..d06ff20c7ab 100644 --- a/packages/wasm-dpp/src/errors/consensus/consensus_error.rs +++ b/packages/wasm-dpp/src/errors/consensus/consensus_error.rs @@ -74,6 +74,7 @@ use dpp::consensus::state::identity::identity_public_key_already_exists_for_uniq use dpp::consensus::state::identity::master_public_key_update_error::MasterPublicKeyUpdateError; use dpp::consensus::state::prefunded_specialized_balances::prefunded_specialized_balance_insufficient_error::PrefundedSpecializedBalanceInsufficientError; use dpp::consensus::state::prefunded_specialized_balances::prefunded_specialized_balance_not_found_error::PrefundedSpecializedBalanceNotFoundError; +use dpp::consensus::state::voting::masternode_incorrect_voting_address_error::MasternodeIncorrectVotingAddressError; use dpp::consensus::state::voting::masternode_not_found_error::MasternodeNotFoundError; use dpp::consensus::state::voting::masternode_vote_already_present_error::MasternodeVoteAlreadyPresentError; use dpp::consensus::state::voting::masternode_voted_too_many_times::MasternodeVotedTooManyTimesError; @@ -280,6 +281,9 @@ pub fn from_state_error(state_error: &StateError) -> JsValue { StateError::MasternodeVoteAlreadyPresentError(e) => { generic_consensus_error!(MasternodeVoteAlreadyPresentError, e).into() } + StateError::MasternodeIncorrectVotingAddressError(e) => { + generic_consensus_error!(MasternodeIncorrectVotingAddressError, e).into() + } } } diff --git a/packages/wasm-dpp/src/identity/identity_public_key/mod.rs b/packages/wasm-dpp/src/identity/identity_public_key/mod.rs index bf07fd9bf4e..cf91b4e404c 100644 --- a/packages/wasm-dpp/src/identity/identity_public_key/mod.rs +++ b/packages/wasm-dpp/src/identity/identity_public_key/mod.rs @@ -133,7 +133,10 @@ impl IdentityPublicKeyWasm { #[wasm_bindgen(js_name=hash)] pub fn hash(&self) -> Result, JsValue> { - self.0.hash().map(|result| result.to_vec()).with_js_error() + self.0 + .public_key_hash() + .map(|result| result.to_vec()) + .with_js_error() } #[wasm_bindgen(js_name=isMaster)] From fb65aa28d3fc3182858eec1a55eff32ce6c3e9a6 Mon Sep 17 00:00:00 2001 From: Quantum Explorer Date: Tue, 25 Jun 2024 01:59:12 +0300 Subject: [PATCH 16/55] cleanup --- .../document_create_transition/v0/mod.rs | 2 - .../masternode_vote_transition/v0/mod.rs | 2 +- .../masternode_vote/advanced_structure/mod.rs | 3 +- .../advanced_structure/v0/mod.rs | 1 - .../state_transitions/masternode_vote/mod.rs | 38 ++++++++----------- .../transform_into_action/v0/mod.rs | 1 - .../verify_state_transitions.rs | 2 - .../tests/strategy_tests/voting_tests.rs | 15 ++------ .../v0/mod.rs | 1 - .../vote_polls_by_document_type_query.rs | 5 +-- .../identity/masternode_vote/transformer.rs | 1 - .../masternode_vote/v0/transformer.rs | 2 - .../rs-platform-value/src/types/bytes_20.rs | 2 +- .../src/errors/consensus/consensus_error.rs | 4 ++ packages/wasm-dpp/src/lib.rs | 1 - 15 files changed, 27 insertions(+), 53 deletions(-) diff --git a/packages/rs-dpp/src/state_transition/state_transitions/document/documents_batch_transition/document_transition/document_create_transition/v0/mod.rs b/packages/rs-dpp/src/state_transition/state_transitions/document/documents_batch_transition/document_transition/document_create_transition/v0/mod.rs index 17e5b782f32..b15cdf0e590 100644 --- a/packages/rs-dpp/src/state_transition/state_transitions/document/documents_batch_transition/document_transition/document_create_transition/v0/mod.rs +++ b/packages/rs-dpp/src/state_transition/state_transitions/document/documents_batch_transition/document_transition/document_create_transition/v0/mod.rs @@ -5,8 +5,6 @@ use bincode::{Decode, Encode}; #[cfg(feature = "state-transition-value-conversion")] use platform_value::btreemap_extensions::BTreeValueRemoveFromMapHelper; -#[cfg(feature = "state-transition-value-conversion")] -use platform_value::ValueMapHelper; use platform_value::{Identifier, Value}; #[cfg(feature = "state-transition-serde-conversion")] use serde::{Deserialize, Serialize}; diff --git a/packages/rs-dpp/src/state_transition/state_transitions/identity/masternode_vote_transition/v0/mod.rs b/packages/rs-dpp/src/state_transition/state_transitions/identity/masternode_vote_transition/v0/mod.rs index e7be2b3c5f0..eac9dc34b5e 100644 --- a/packages/rs-dpp/src/state_transition/state_transitions/identity/masternode_vote_transition/v0/mod.rs +++ b/packages/rs-dpp/src/state_transition/state_transitions/identity/masternode_vote_transition/v0/mod.rs @@ -83,7 +83,7 @@ mod test { let mut rng = rand::thread_rng(); let transition = MasternodeVoteTransitionV0 { pro_tx_hash: Identifier::random(), - voting_address: rng.gen(), + voter_identity_id: Identifier::random(), vote: Vote::ResourceVote(ResourceVote::V0(ResourceVoteV0 { vote_poll: VotePoll::ContestedDocumentResourceVotePoll( ContestedDocumentResourceVotePoll { diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/masternode_vote/advanced_structure/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/masternode_vote/advanced_structure/mod.rs index b5b9d80edf4..b44732c3d07 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/masternode_vote/advanced_structure/mod.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/masternode_vote/advanced_structure/mod.rs @@ -5,10 +5,9 @@ use crate::execution::validation::state_transition::masternode_vote::advanced_st use crate::execution::validation::state_transition::processor::v0::StateTransitionStructureKnownInStateValidationV0; use dpp::identity::PartialIdentity; use dpp::prelude::ConsensusValidationResult; -use dpp::serialization::Signable; use dpp::state_transition::masternode_vote_transition::MasternodeVoteTransition; +use dpp::version::PlatformVersion; use drive::state_transition_action::StateTransitionAction; -use platform_version::version::PlatformVersion; pub(crate) mod v0; diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/masternode_vote/advanced_structure/v0/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/masternode_vote/advanced_structure/v0/mod.rs index c75721f44a5..0773f388402 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/masternode_vote/advanced_structure/v0/mod.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/masternode_vote/advanced_structure/v0/mod.rs @@ -6,7 +6,6 @@ use crate::execution::types::state_transition_execution_context::{ }; use dpp::consensus::state::voting::masternode_incorrect_voter_identity_id_error::MasternodeIncorrectVoterIdentityIdError; use dpp::consensus::state::voting::masternode_incorrect_voting_address_error::MasternodeIncorrectVotingAddressError; -use dpp::dashcore::hashes::Hash; use dpp::identifier::MasternodeIdentifiers; use dpp::identity::hash::IdentityPublicKeyHashMethodsV0; use dpp::identity::PartialIdentity; diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/masternode_vote/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/masternode_vote/mod.rs index 2e436f5200e..f1dacfd1416 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/masternode_vote/mod.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/masternode_vote/mod.rs @@ -779,10 +779,6 @@ mod tests { .verify_contests_proof(proof.grovedb_proof.as_ref(), platform_version) .expect("expected to verify proof"); - let dash_encoded = - bincode::encode_to_vec(Value::Text("dash".to_string()), config) - .expect("expected to encode the word dash"); - assert_eq!( contests.first(), Some(Value::Text("dash".to_string())).as_ref() @@ -821,10 +817,6 @@ mod tests { let index_name = "parentNameAndLabel".to_string(); - let config = bincode::config::standard() - .with_big_endian() - .with_no_limit(); - { let query_validation_result = platform .query_contested_resources( @@ -1087,7 +1079,7 @@ mod tests { let platform_state = platform.state.load(); - let (_contender_1, _contender_2, dpns_contract) = create_dpns_name_contest( + let (_contender_1, _contender_2, _dpns_contract) = create_dpns_name_contest( &mut platform, &platform_state, 7, @@ -1095,7 +1087,7 @@ mod tests { platform_version, ); - let (_contender_3, _contender_4, dpns_contract) = create_dpns_name_contest( + let (_contender_3, _contender_4, _dpns_contract) = create_dpns_name_contest( &mut platform, &platform_state, 8, @@ -1424,7 +1416,7 @@ mod tests { platform_version, ); - let (pro_tx_hash_1, masternode_1, signer_1, voting_key_1) = + let (pro_tx_hash_1, _masternode_1, signer_1, voting_key_1) = setup_masternode_identity(&mut platform, 29, platform_version); let platform_state = platform.state.load(); @@ -2607,7 +2599,7 @@ mod tests { ); for i in 0..50 { - let (pro_tx_hash, masternode, signer, voting_key) = + let (pro_tx_hash, _masternode, signer, voting_key) = setup_masternode_identity(&mut platform, 10 + i, platform_version); let platform_state = platform.state.load(); @@ -2628,7 +2620,7 @@ mod tests { } for i in 0..5 { - let (pro_tx_hash, masternode, signer, voting_key) = + let (pro_tx_hash, _masternode, signer, voting_key) = setup_masternode_identity(&mut platform, 100 + i, platform_version); let platform_state = platform.state.load(); @@ -2649,7 +2641,7 @@ mod tests { } for i in 0..8 { - let (pro_tx_hash, masternode, signer, voting_key) = + let (pro_tx_hash, _masternode, signer, voting_key) = setup_masternode_identity(&mut platform, 200 + i, platform_version); let platform_state = platform.state.load(); @@ -2731,7 +2723,7 @@ mod tests { // let's add another 50 votes for i in 0..50 { - let (pro_tx_hash, masternode, signer, voting_key) = + let (pro_tx_hash, _masternode, signer, voting_key) = setup_masternode_identity(&mut platform, 400 + i, platform_version); let platform_state = platform.state.load(); @@ -2767,7 +2759,7 @@ mod tests { // let's add another vote for i in 0..1 { - let (pro_tx_hash, masternode, signer, voting_key) = + let (pro_tx_hash, _masternode, signer, voting_key) = setup_masternode_identity(&mut platform, 500 + i, platform_version); let platform_state = platform.state.load(); @@ -2850,7 +2842,7 @@ mod tests { ); for i in 0..50 { - let (pro_tx_hash, masternode, signer, voting_key) = + let (pro_tx_hash, _masternode, signer, voting_key) = setup_masternode_identity(&mut platform, 10 + i, platform_version); let platform_state = platform.state.load(); @@ -2871,7 +2863,7 @@ mod tests { } for i in 0..5 { - let (pro_tx_hash, masternode, signer, voting_key) = + let (pro_tx_hash, _masternode, signer, voting_key) = setup_masternode_identity(&mut platform, 100 + i, platform_version); let platform_state = platform.state.load(); @@ -2892,7 +2884,7 @@ mod tests { } for i in 0..8 { - let (pro_tx_hash, masternode, signer, voting_key) = + let (pro_tx_hash, _masternode, signer, voting_key) = setup_masternode_identity(&mut platform, 200 + i, platform_version); let platform_state = platform.state.load(); @@ -5072,7 +5064,7 @@ mod tests { assert_eq!(start_balance_after_more_contenders, dash_to_credits!(0.8)); for i in 0..50 { - let (pro_tx_hash, masternode, signer, voting_key) = + let (pro_tx_hash, _masternode, signer, voting_key) = setup_masternode_identity(&mut platform, 10 + i, platform_version); let platform_state = platform.state.load(); @@ -5103,7 +5095,7 @@ mod tests { assert_eq!(balance_after_50_votes, dash_to_credits!(0.795)); for i in 0..5 { - let (pro_tx_hash, masternode, signer, voting_key) = + let (pro_tx_hash, _masternode, signer, voting_key) = setup_masternode_identity(&mut platform, 100 + i, platform_version); let platform_state = platform.state.load(); @@ -5180,7 +5172,7 @@ mod tests { assert_eq!(start_balance_after_more_contenders, dash_to_credits!(0.8)); for i in 0..50 { - let (pro_tx_hash, masternode, signer, voting_key) = + let (pro_tx_hash, _masternode, signer, voting_key) = setup_masternode_identity(&mut platform, 10 + i, platform_version); let platform_state = platform.state.load(); @@ -5211,7 +5203,7 @@ mod tests { assert_eq!(balance_after_50_votes, dash_to_credits!(0.795)); for i in 0..5 { - let (pro_tx_hash, masternode, signer, voting_key) = + let (pro_tx_hash, _masternode, signer, voting_key) = setup_masternode_identity(&mut platform, 100 + i, platform_version); let platform_state = platform.state.load(); diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/masternode_vote/transform_into_action/v0/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/masternode_vote/transform_into_action/v0/mod.rs index 6ce39536b41..6e17495d3c4 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/masternode_vote/transform_into_action/v0/mod.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/masternode_vote/transform_into_action/v0/mod.rs @@ -2,7 +2,6 @@ use crate::error::Error; use crate::platform_types::platform::PlatformRef; use dashcore_rpc::dashcore_rpc_json::MasternodeType; use dpp::consensus::state::state_error::StateError; -use dpp::consensus::state::voting::masternode_incorrect_voting_address_error::MasternodeIncorrectVotingAddressError; use dpp::consensus::state::voting::masternode_not_found_error::MasternodeNotFoundError; use dpp::consensus::state::voting::masternode_vote_already_present_error::MasternodeVoteAlreadyPresentError; use dpp::consensus::state::voting::masternode_voted_too_many_times::MasternodeVotedTooManyTimesError; diff --git a/packages/rs-drive-abci/tests/strategy_tests/verify_state_transitions.rs b/packages/rs-drive-abci/tests/strategy_tests/verify_state_transitions.rs index a5787e38d25..cbbe0306e49 100644 --- a/packages/rs-drive-abci/tests/strategy_tests/verify_state_transitions.rs +++ b/packages/rs-drive-abci/tests/strategy_tests/verify_state_transitions.rs @@ -23,8 +23,6 @@ use drive_abci::rpc::core::MockCoreRPCLike; use tenderdash_abci::proto::abci::ExecTxResult; use dpp::state_transition::documents_batch_transition::accessors::DocumentsBatchTransitionAccessorsV0; -use dpp::voting::vote_polls::VotePoll; -use dpp::voting::votes::resource_vote::accessors::v0::ResourceVoteGettersV0; use dpp::voting::votes::Vote; use drive::drive::votes::resolved::vote_polls::ResolvedVotePoll; use drive::drive::votes::resolved::votes::resolved_resource_vote::accessors::v0::ResolvedResourceVoteGettersV0; diff --git a/packages/rs-drive-abci/tests/strategy_tests/voting_tests.rs b/packages/rs-drive-abci/tests/strategy_tests/voting_tests.rs index 482ed23a994..80c40e66fd7 100644 --- a/packages/rs-drive-abci/tests/strategy_tests/voting_tests.rs +++ b/packages/rs-drive-abci/tests/strategy_tests/voting_tests.rs @@ -16,18 +16,11 @@ mod tests { use rand::SeedableRng; use simple_signer::signer::SimpleSigner; use std::collections::BTreeMap; - use dapi_grpc::platform::v0::{get_contested_resource_vote_state_request, get_contested_resource_vote_state_response, GetContestedResourceVoteStateRequest, GetContestedResourceVoteStateResponse}; + use dapi_grpc::platform::v0::{get_contested_resource_vote_state_request, get_contested_resource_vote_state_response, GetContestedResourceVoteStateRequest}; use dapi_grpc::platform::v0::get_contested_resource_vote_state_request::get_contested_resource_vote_state_request_v0::ResultType; use dapi_grpc::platform::v0::get_contested_resource_vote_state_request::GetContestedResourceVoteStateRequestV0; use dapi_grpc::platform::v0::get_contested_resource_vote_state_response::{get_contested_resource_vote_state_response_v0, GetContestedResourceVoteStateResponseV0}; use dpp::data_contract::document_type::accessors::DocumentTypeV0Getters; - use dpp::document::Document; - use dpp::document::serialization_traits::DocumentPlatformConversionMethodsV0; - use drive::drive::object_size_info::DataContractResolvedInfo; - use drive::drive::votes::resolved::vote_polls::contested_document_resource_vote_poll::ContestedDocumentResourceVotePollWithContractInfoAllowBorrowed; - use drive::query::vote_poll_vote_state_query::ContestedDocumentVotePollDriveQueryResultType::DocumentsAndVoteTally; - use drive::query::vote_poll_vote_state_query::ResolvedContestedDocumentVotePollDriveQuery; - use drive_abci::platform_types::platform_state::v0::PlatformStateV0Methods; use strategy_tests::frequency::Frequency; use strategy_tests::operations::{DocumentAction, DocumentOp, Operation, OperationType}; use strategy_tests::transitions::create_state_transitions_for_identities; @@ -265,9 +258,9 @@ mod tests { get_contested_resource_vote_state_response_v0::Result::ContestedResourceContenders( get_contested_resource_vote_state_response_v0::ContestedResourceContenders { contenders, - abstain_vote_tally, - lock_vote_tally, - finished_vote_info, + abstain_vote_tally: _, + lock_vote_tally: _, + finished_vote_info: _, }, ), ) = result diff --git a/packages/rs-drive/src/drive/document/insert_contested/add_contested_indices_for_contract_operations/v0/mod.rs b/packages/rs-drive/src/drive/document/insert_contested/add_contested_indices_for_contract_operations/v0/mod.rs index cae63385768..09e8e9717a7 100644 --- a/packages/rs-drive/src/drive/document/insert_contested/add_contested_indices_for_contract_operations/v0/mod.rs +++ b/packages/rs-drive/src/drive/document/insert_contested/add_contested_indices_for_contract_operations/v0/mod.rs @@ -13,7 +13,6 @@ use dpp::data_contract::document_type::accessors::DocumentTypeV0Getters; use crate::drive::defaults::DEFAULT_HASH_SIZE_U8; use crate::drive::votes::paths::{ - vote_contested_resource_active_polls_contract_document_tree_path_vec, vote_contested_resource_contract_documents_indexes_path_vec, RESOURCE_ABSTAIN_VOTE_TREE_KEY, RESOURCE_LOCK_VOTE_TREE_KEY, }; diff --git a/packages/rs-drive/src/query/vote_polls_by_document_type_query.rs b/packages/rs-drive/src/query/vote_polls_by_document_type_query.rs index c657d7acc2a..1f7c672d574 100644 --- a/packages/rs-drive/src/query/vote_polls_by_document_type_query.rs +++ b/packages/rs-drive/src/query/vote_polls_by_document_type_query.rs @@ -1,9 +1,6 @@ use super::ContractLookupFn; use crate::drive::object_size_info::DataContractResolvedInfo; -use crate::drive::votes::paths::{ - vote_contested_resource_active_polls_contract_document_tree_path_vec, - vote_contested_resource_contract_documents_indexes_path_vec, -}; +use crate::drive::votes::paths::vote_contested_resource_contract_documents_indexes_path_vec; #[cfg(feature = "server")] use crate::drive::Drive; use crate::error::contract::DataContractError; diff --git a/packages/rs-drive/src/state_transition_action/identity/masternode_vote/transformer.rs b/packages/rs-drive/src/state_transition_action/identity/masternode_vote/transformer.rs index 7b646f6dd8b..cfe706fcd9a 100644 --- a/packages/rs-drive/src/state_transition_action/identity/masternode_vote/transformer.rs +++ b/packages/rs-drive/src/state_transition_action/identity/masternode_vote/transformer.rs @@ -4,7 +4,6 @@ use crate::state_transition_action::identity::masternode_vote::v0::{ MasternodeVoteTransitionActionV0, PreviousVoteCount, }; use crate::state_transition_action::identity::masternode_vote::MasternodeVoteTransitionAction; -use dpp::identifier::Identifier; use dpp::state_transition::masternode_vote_transition::MasternodeVoteTransition; use dpp::voting::vote_choices::resource_vote_choice::ResourceVoteChoice; use grovedb::TransactionArg; diff --git a/packages/rs-drive/src/state_transition_action/identity/masternode_vote/v0/transformer.rs b/packages/rs-drive/src/state_transition_action/identity/masternode_vote/v0/transformer.rs index 53643a327f1..d304791db1f 100644 --- a/packages/rs-drive/src/state_transition_action/identity/masternode_vote/v0/transformer.rs +++ b/packages/rs-drive/src/state_transition_action/identity/masternode_vote/v0/transformer.rs @@ -4,8 +4,6 @@ use crate::error::Error; use crate::state_transition_action::identity::masternode_vote::v0::{ MasternodeVoteTransitionActionV0, PreviousVoteCount, }; -use dpp::identifier::MasternodeIdentifiers; -use dpp::prelude::Identifier; use dpp::state_transition::state_transitions::identity::masternode_vote_transition::v0::MasternodeVoteTransitionV0; use dpp::voting::vote_choices::resource_vote_choice::ResourceVoteChoice; use grovedb::TransactionArg; diff --git a/packages/rs-platform-value/src/types/bytes_20.rs b/packages/rs-platform-value/src/types/bytes_20.rs index 1baca634b7a..49c53f64fa2 100644 --- a/packages/rs-platform-value/src/types/bytes_20.rs +++ b/packages/rs-platform-value/src/types/bytes_20.rs @@ -1,6 +1,6 @@ use crate::string_encoding::Encoding; use crate::types::encoding_string_to_encoding; -use crate::{string_encoding, Error, Identifier, Value}; +use crate::{string_encoding, Error, Value}; use base64::prelude::BASE64_STANDARD; use base64::Engine; use bincode::{Decode, Encode}; diff --git a/packages/wasm-dpp/src/errors/consensus/consensus_error.rs b/packages/wasm-dpp/src/errors/consensus/consensus_error.rs index d06ff20c7ab..39ffb2896df 100644 --- a/packages/wasm-dpp/src/errors/consensus/consensus_error.rs +++ b/packages/wasm-dpp/src/errors/consensus/consensus_error.rs @@ -74,6 +74,7 @@ use dpp::consensus::state::identity::identity_public_key_already_exists_for_uniq use dpp::consensus::state::identity::master_public_key_update_error::MasterPublicKeyUpdateError; use dpp::consensus::state::prefunded_specialized_balances::prefunded_specialized_balance_insufficient_error::PrefundedSpecializedBalanceInsufficientError; use dpp::consensus::state::prefunded_specialized_balances::prefunded_specialized_balance_not_found_error::PrefundedSpecializedBalanceNotFoundError; +use dpp::consensus::state::voting::masternode_incorrect_voter_identity_id_error::MasternodeIncorrectVoterIdentityIdError; use dpp::consensus::state::voting::masternode_incorrect_voting_address_error::MasternodeIncorrectVotingAddressError; use dpp::consensus::state::voting::masternode_not_found_error::MasternodeNotFoundError; use dpp::consensus::state::voting::masternode_vote_already_present_error::MasternodeVoteAlreadyPresentError; @@ -284,6 +285,9 @@ pub fn from_state_error(state_error: &StateError) -> JsValue { StateError::MasternodeIncorrectVotingAddressError(e) => { generic_consensus_error!(MasternodeIncorrectVotingAddressError, e).into() } + StateError::MasternodeIncorrectVoterIdentityIdError(e) => { + generic_consensus_error!(MasternodeIncorrectVoterIdentityIdError, e).into() + } } } diff --git a/packages/wasm-dpp/src/lib.rs b/packages/wasm-dpp/src/lib.rs index e814c8a82bc..6d0aa9c50c1 100644 --- a/packages/wasm-dpp/src/lib.rs +++ b/packages/wasm-dpp/src/lib.rs @@ -7,7 +7,6 @@ pub use data_contract::*; pub use document::*; pub use identity::*; pub use metadata::*; -pub use voting::*; // pub use state_transition::*; mod dash_platform_protocol; From 6deef699038fff2f13e1588531e457a9be82a097 Mon Sep 17 00:00:00 2001 From: Quantum Explorer Date: Tue, 25 Jun 2024 02:05:41 +0300 Subject: [PATCH 17/55] cleanup --- packages/rs-dpp/src/data_contract/document_type/index/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/rs-dpp/src/data_contract/document_type/index/mod.rs b/packages/rs-dpp/src/data_contract/document_type/index/mod.rs index 61fba0a9ec3..12bae965b31 100644 --- a/packages/rs-dpp/src/data_contract/document_type/index/mod.rs +++ b/packages/rs-dpp/src/data_contract/document_type/index/mod.rs @@ -127,7 +127,7 @@ impl<'de> Deserialize<'de> for ContestedIndexFieldMatch { formatter.write_str("enum ContestedIndexFieldMatch") } - fn visit_enum(self, mut visitor: V) -> Result + fn visit_enum(self, visitor: V) -> Result where V: de::EnumAccess<'de>, { From f8e730d106c204080f6725860b4bab06eff6db83 Mon Sep 17 00:00:00 2001 From: Quantum Explorer Date: Tue, 25 Jun 2024 02:08:19 +0300 Subject: [PATCH 18/55] cleanup --- .../src/drive/contract/insert/insert_contract/v0/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/rs-drive/src/drive/contract/insert/insert_contract/v0/mod.rs b/packages/rs-drive/src/drive/contract/insert/insert_contract/v0/mod.rs index d4d5f7fae19..c538f969968 100644 --- a/packages/rs-drive/src/drive/contract/insert/insert_contract/v0/mod.rs +++ b/packages/rs-drive/src/drive/contract/insert/insert_contract/v0/mod.rs @@ -221,7 +221,7 @@ impl Drive { contract.id_ref().as_bytes(), ); - for (type_key, document_type) in document_types_with_contested_indexes.into_iter() { + for (type_key, _document_type) in document_types_with_contested_indexes.into_iter() { self.batch_insert_empty_tree( contested_unique_index_contract_document_types_path, KeyRef(type_key.as_bytes()), From cf731c6d7fa6f3024163bb0440fd4187014fc3b4 Mon Sep 17 00:00:00 2001 From: Quantum Explorer Date: Tue, 25 Jun 2024 09:25:49 +0300 Subject: [PATCH 19/55] small fix --- packages/rs-sdk/src/platform/transition/vote.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/rs-sdk/src/platform/transition/vote.rs b/packages/rs-sdk/src/platform/transition/vote.rs index 42caa451bc9..505109f4fc4 100644 --- a/packages/rs-sdk/src/platform/transition/vote.rs +++ b/packages/rs-sdk/src/platform/transition/vote.rs @@ -105,14 +105,14 @@ impl PutVote for Vote { Ok(_) => {} //todo make this more reliable Err(e) => { - if e.to_string().contains("already exists") { + return if e.to_string().contains("already exists") { let vote = Vote::fetch(sdk, VoteQuery::new(voter_pro_tx_hash, vote_poll_id)).await?; - return vote.ok_or(Error::DapiClientError( + vote.ok_or(Error::DapiClientError( "vote was proved to not exist but was said to exist".to_string(), - )); + )) } else { - return Err(e.into()); + Err(e.into()) } } } From 06094449b7b781195221e118a190e5f00fd04984 Mon Sep 17 00:00:00 2001 From: Lukasz Klimek <842586+lklimek@users.noreply.github.com> Date: Tue, 25 Jun 2024 11:32:15 +0200 Subject: [PATCH 20/55] test(sdk): mn voting tests updated and improved --- .../rs-sdk/tests/fetch/contested_resource.rs | 119 ++++++++++++++---- .../fetch/contested_resource_polls_by_ts.rs | 10 +- .../fetch/contested_resource_vote_state.rs | 36 +++--- 3 files changed, 115 insertions(+), 50 deletions(-) diff --git a/packages/rs-sdk/tests/fetch/contested_resource.rs b/packages/rs-sdk/tests/fetch/contested_resource.rs index f21257cef66..e6295fa640d 100644 --- a/packages/rs-sdk/tests/fetch/contested_resource.rs +++ b/packages/rs-sdk/tests/fetch/contested_resource.rs @@ -17,6 +17,7 @@ use drive::query::{ vote_polls_by_document_type_query::VotePollsByDocumentTypeQuery, }; use drive_proof_verifier::types::ContestedResource; +use std::panic::catch_unwind; pub(crate) const INDEX_VALUE: &str = "dada"; @@ -240,6 +241,11 @@ async fn contested_resources_fields() { } let test_cases: Vec = vec![ + TestCase { + name: "unmodified base query is Ok", + query_mut_fn: |_q| {}, + expect: Ok("aaa"), + }, TestCase { name: "index value empty string is Ok", query_mut_fn: |q| q.start_index_values = vec![Value::Text("".to_string())], @@ -267,7 +273,6 @@ async fn contested_resources_fields() { ), }, TestCase { - // this fails with code: Internal, see PLAN-563 name: "start_at_value wrong index type returns InvalidArgument PLAN-563", query_mut_fn: |q| q.start_at_value = Some((Value::Array(vec![]), true)), expect: Err(r#"code: InvalidArgument"#), @@ -283,19 +288,51 @@ async fn contested_resources_fields() { expect: Ok(r#"ContestedResources([])"#), }, TestCase { - // fails due to PLAN-662 - name: "start_index_values with two values PLAN-662", + name: "start_index_values with two values returns error", query_mut_fn: |q| { q.start_index_values = vec![ Value::Text("dash".to_string()), Value::Text("dada".to_string()), ] }, - expect: Ok(r#"ContestedResources([Value(Text("dash"))])"#), + expect: Err("incorrect index values error: too many start values were provided, since no end index values \ + were provided, the start index values must be less than the amount of properties in the contested index"), }, + TestCase { + name: "end_index_values one value with empty start_index_values returns 'dash'", + query_mut_fn: |q| { + q.start_index_values = vec![]; + q.end_index_values = vec![Value::Text("dada".to_string())]; + }, + expect:Ok(r#"ContestedResources([Value(Text("dash"))])"#), + }, + TestCase { + name: "end_index_values two values (1 nx) with empty start_index_values returns 'dash'", + query_mut_fn: |q| { + q.start_index_values = vec![]; + q.end_index_values = vec![Value::Text("dada".to_string()), Value::Text("non existing".to_string())]; + }, + expect:Ok(r#"ContestedResources([Value(Text("dash"))])"#), + }, + TestCase { + name: "end_index_values with 1 nx value 'aaa*' and empty start_index_values returns zero objects", + query_mut_fn: |q| { + q.start_index_values = vec![]; + q.end_index_values = vec![Value::Text("aaa non existing".to_string())]; + }, + expect:Ok(r#"ContestedResources([])"#), + }, + TestCase { + name: "end_index_values with 1 nx value 'zzz*' and empty start_index_values returns zero objects", + query_mut_fn: |q| { + q.start_index_values = vec![]; + q.end_index_values = vec![Value::Text("zzz non existing".to_string())]; + }, + expect:Ok(r#"ContestedResources([])"#), + }, TestCase { // fails due to PLAN-662 - name: "too many items in start_index_values PLAN-662", + name: "too many items in start_index_values returns error", query_mut_fn: |q| { q.start_index_values = vec![ Value::Text("dash".to_string()), @@ -303,32 +340,38 @@ async fn contested_resources_fields() { Value::Text("eee".to_string()), ] }, - expect: Ok( - r#"code: InvalidArgument, message: "incorrect index values error: the start index values and the end index"#, - ), + expect: Err("incorrect index values error: too many start values were provided, since no end index values \ + were provided, the start index values must be less than the amount of properties in the contested index"), }, TestCase { - // fails due to PLAN-663 - name: "Non existing end_index_values PLAN-663", - query_mut_fn: |q| q.end_index_values = vec![Value::Text("non existing".to_string())], + name: "Non existing end_index_values starting with zzz returns all previous values PLAN-667", + query_mut_fn: |q| { + q.end_index_values = vec![Value::Text("zzz non existing".to_string())] + }, + expect: Ok(r#"ContestedResources([Value(Text("dash"))])"#), + }, + TestCase { + name: "Non existing end_index_values starting with aaa returns nothing PLAN-667", + query_mut_fn: |q| { + q.end_index_values = vec![Value::Text("aaa non existing".to_string())] + }, expect: Ok(r#"ContestedResources([Value(Text("dash"))])"#), }, TestCase { // fails due to PLAN-663 - name: "wrong type of end_index_values should return InvalidArgument PLAN-663", + name: "wrong type of end_index_values should return InvalidArgument PLAN-663 PLAN-667", query_mut_fn: |q| q.end_index_values = vec![Value::Array(vec![0.into(), 1.into()])], - expect: Ok(r#"code: InvalidArgument"#), + expect: Err(r#"code: InvalidArgument a"#), }, TestCase { - // fails due to PLAN-664 - name: "limit 0 returns InvalidArgument PLAN-664", + name: "limit 0 returns InvalidArgument", query_mut_fn: |q| q.limit = Some(0), - expect: Ok(r#"code: InvalidArgument"#), + expect: Err(r#"code: InvalidArgument"#), }, TestCase { - name: "limit std::u16::MAX returns InvalidArgument PLAN-664", + name: "limit std::u16::MAX returns InvalidArgument", query_mut_fn: |q| q.limit = Some(std::u16::MAX), - expect: Ok(r#"code: InvalidArgument"#), + expect: Err(r#"code: InvalidArgument"#), }, ]; @@ -343,7 +386,6 @@ async fn contested_resources_fields() { document_type_name: cfg.existing_document_type_name.clone(), index_name: "parentNameAndLabel".to_string(), start_at_value: None, - // start_index_values: vec![], // Value(Text("dash")), Value(Text(""))]) start_index_values: vec![Value::Text("dash".to_string())], end_index_values: vec![], limit: None, @@ -362,15 +404,38 @@ async fn contested_resources_fields() { for test_case in test_cases { tracing::debug!("Running test case: {}", test_case.name); - // create new sdk to ensure that test cases don't interfere with each other - let sdk = cfg - .setup_api(&format!("contested_resources_fields_{}", test_case.name)) - .await; + // handle panics to not stop other test cases from running + let unwinded = catch_unwind(|| { + { + pollster::block_on(async { + // create new sdk to ensure that test cases don't interfere with each other + let sdk = cfg + .setup_api(&format!("contested_resources_fields_{}", test_case.name)) + .await; + + let mut query = base_query.clone(); + (test_case.query_mut_fn)(&mut query); + + ContestedResource::fetch_many(&sdk, query).await + }) + } + }); + let result = match unwinded { + Ok(r) => r, + Err(e) => { + let msg = if let Some(s) = e.downcast_ref::<&str>() { + s.to_string() + } else if let Some(s) = e.downcast_ref::() { + s.to_string() + } else { + format!("unknown panic type: {:?}", std::any::type_name_of_val(&e)) + }; - let mut query = base_query.clone(); - (test_case.query_mut_fn)(&mut query); + failures.push((test_case.name, format!("PANIC: {}", msg))); + continue; // continue to next test case + } + }; - let result = ContestedResource::fetch_many(&sdk, query).await; match test_case.expect { Ok(expected) if result.is_ok() => { let result_string = format!("{:?}", result.as_ref().expect("result")); @@ -409,7 +474,7 @@ async fn contested_resources_fields() { .join("\n* "); panic!( - "{} test cases failed:\n{}\n\n{}\n", + "{} test cases failed:\n* {}\n\n{}\n", failures.len(), failed_cases, failures diff --git a/packages/rs-sdk/tests/fetch/contested_resource_polls_by_ts.rs b/packages/rs-sdk/tests/fetch/contested_resource_polls_by_ts.rs index 3f970fa6ef6..61cc66f258b 100644 --- a/packages/rs-sdk/tests/fetch/contested_resource_polls_by_ts.rs +++ b/packages/rs-sdk/tests/fetch/contested_resource_polls_by_ts.rs @@ -86,8 +86,8 @@ async fn vote_polls_by_ts_order() { let (prev_ts, _) = &enumerated[&(i - 1)]; if order_ascending { assert!( - ts >= prev_ts, - "ascending order: item {} ({}) must be >= than item {} ({})", + ts > prev_ts, + "ascending order: item {} ({}) must be > than item {} ({})", ts, i, prev_ts, @@ -95,8 +95,8 @@ async fn vote_polls_by_ts_order() { ); } else { assert!( - ts <= prev_ts, - "descending order: item {} ({}) must be >= than item {} ({})", + ts < prev_ts, + "descending order: item {} ({}) must be < than item {} ({})", ts, i, prev_ts, @@ -140,7 +140,7 @@ async fn vote_polls_by_ts_limit() { offset: None, order_ascending: true, start_time: None, - end_time: Some((test_start_time, true)), + end_time: Some((test_start_time, true)), // 1 month in future }; let all = VotePoll::fetch_many(&sdk, query_all.clone()) diff --git a/packages/rs-sdk/tests/fetch/contested_resource_vote_state.rs b/packages/rs-sdk/tests/fetch/contested_resource_vote_state.rs index fe256cd14ac..a7b6539e047 100644 --- a/packages/rs-sdk/tests/fetch/contested_resource_vote_state.rs +++ b/packages/rs-sdk/tests/fetch/contested_resource_vote_state.rs @@ -269,32 +269,32 @@ async fn contested_resource_vote_states_fields() { let test_cases: Vec = vec![ TestCase { - name: "limit 0 PLAN-664", + name: "limit 0", query_mut_fn: |q| q.limit = Some(0), - expect: Ok("..."), + expect:Err("limit 0 out of bounds of [1, 100]"), }, TestCase { - name: "limit std::u16::MAX PLAN-664", + name: "limit std::u16::MAX", query_mut_fn: |q| q.limit = Some(std::u16::MAX), - expect: Ok("..."), + expect: Err("limit 65535 out of bounds of [1, 100]"), }, TestCase { name: "offset not None", query_mut_fn: |q| q.offset = Some(1), expect: Err( - r#"Generic("ContestedDocumentVotePollDriveQuery.offset field is internal and must be set to None")"#, + "ContestedDocumentVotePollDriveQuery.offset field is internal and must be set to None", ), }, TestCase { // TODO: pagination test - name: "start_at does not exist", + name: "start_at does not exist should return next contenders", query_mut_fn: |q| q.start_at = Some(([0x11; 32], true)), expect: Ok("Contenders { contenders: {Identifier("), }, TestCase { - name: "start_at 0xff;32", + name: "start_at 0xff;32 should return zero contenders", query_mut_fn: |q| q.start_at = Some(([0xff; 32], true)), - expect: Ok("Contenders { contenders: {Identifier("), + expect: Ok("Contenders { contenders: {}, abstain_vote_tally: None, lock_vote_tally: None }"), }, TestCase { name: "non existing document type returns InvalidArgument", @@ -317,19 +317,21 @@ async fn contested_resource_vote_states_fields() { }, TestCase { // todo maybe this should fail? or return everything? - name: "index_values empty vec returns error PLAN-665", + name: "index_values empty vec returns error", query_mut_fn: |q| q.vote_poll.index_values = vec![], - expect: Ok(r#"TODO error"#), + expect: Err( + "query uses index parentNameAndLabel, this index has 2 properties, but the query provided 0 index values instead", + ), }, TestCase { - name: "index_values empty string returns error PLAN-665", + name: "index_values empty string returns error", query_mut_fn: |q| q.vote_poll.index_values = vec![Value::Text("".to_string())], - expect: Ok("TODO error"), + expect: Err("query uses index parentNameAndLabel, this index has 2 properties, but the query provided 1 index values instead"), }, TestCase { - name: "index_values with one value returns error PLAN-665", + name: "index_values with one value returns error", query_mut_fn: |q| q.vote_poll.index_values = vec![Value::Text("dash".to_string())], - expect: Ok("TODO error"), + expect: Err("query uses index parentNameAndLabel, this index has 2 properties, but the query provided 1 index values instead"), }, TestCase { name: "index_values with two values returns contenders", @@ -342,7 +344,7 @@ async fn contested_resource_vote_states_fields() { expect: Ok("contenders: {Identifier("), }, TestCase { - name: "index_values too many items should return error PLAN-665", + name: "index_values too many items should return error", query_mut_fn: |q| { q.vote_poll.index_values = vec![ Value::Text("dash".to_string()), @@ -350,9 +352,7 @@ async fn contested_resource_vote_states_fields() { Value::Text("eee".to_string()), ] }, - expect: Ok( - r#"code: InvalidArgument, message: "incorrect index values error: the start index values and the end index"#, - ), + expect:Err("query uses index parentNameAndLabel, this index has 2 properties, but the query provided 3 index values instead"), }, TestCase { name: "invalid contract id should cause InvalidArgument error", From cadcfddc540494e7f8989af8b53f43e3cdee933c Mon Sep 17 00:00:00 2001 From: Quantum Explorer Date: Tue, 25 Jun 2024 13:45:19 +0300 Subject: [PATCH 21/55] added error if too many end index values --- Cargo.lock | 413 ++++++++++++++---- .../state_transitions/masternode_vote/mod.rs | 98 +++++ .../vote_polls_by_document_type_query.rs | 7 +- 3 files changed, 431 insertions(+), 87 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 305a05017f5..9f6c164398b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -211,7 +211,7 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" dependencies = [ "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.66", ] [[package]] @@ -222,7 +222,7 @@ checksum = "c6fa2087f2753a7da8cc1c0dbfcf89579dd57458e36769de5ac750b4671737ca" dependencies = [ "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.66", ] [[package]] @@ -397,7 +397,7 @@ dependencies = [ "regex", "rustc-hash", "shlex", - "syn 2.0.68", + "syn 2.0.66", "which", ] @@ -418,7 +418,7 @@ dependencies = [ "regex", "rustc-hash", "shlex", - "syn 2.0.68", + "syn 2.0.66", ] [[package]] @@ -548,7 +548,7 @@ dependencies = [ "proc-macro-crate 3.1.0", "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.66", "syn_derive", ] @@ -731,9 +731,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.0.100" +version = "1.0.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c891175c3fb232128f48de6590095e59198bbeb8620c310be349bfc3afd12c7b" +checksum = "96c51067fd44124faa7f870b4b1c969379ad32b2ba805aa959430ceaa384f695" dependencies = [ "jobserver", "libc", @@ -860,7 +860,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.66", ] [[package]] @@ -1217,15 +1217,16 @@ dependencies = [ [[package]] name = "curve25519-dalek" -version = "4.1.3" +version = "4.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be" +checksum = "0a677b8922c94e01bdbb12126b0bc852f00447528dee1782229af9c720c3f348" dependencies = [ "cfg-if", "cpufeatures", "curve25519-dalek-derive", "digest", "fiat-crypto", + "platforms", "rustc_version", "subtle", "zeroize", @@ -1239,7 +1240,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.66", ] [[package]] @@ -1265,7 +1266,7 @@ dependencies = [ "dapi-grpc", "heck 0.5.0", "quote", - "syn 2.0.68", + "syn 2.0.66", ] [[package]] @@ -1289,7 +1290,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.68", + "syn 2.0.66", ] [[package]] @@ -1300,7 +1301,7 @@ checksum = "733cabb43482b1a1b53eee8583c2b9e8684d592215ea83efd305dd31bc2f0178" dependencies = [ "darling_core", "quote", - "syn 2.0.68", + "syn 2.0.66", ] [[package]] @@ -1468,7 +1469,7 @@ dependencies = [ "proc-macro2", "quote", "rustc_version", - "syn 2.0.68", + "syn 2.0.66", ] [[package]] @@ -1524,6 +1525,17 @@ dependencies = [ "winapi", ] +[[package]] +name = "displaydoc" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.66", +] + [[package]] name = "dotenvy" version = "0.15.7" @@ -1779,7 +1791,7 @@ checksum = "f282cfdfe92516eb26c2af8589c274c7c17681f5ecc03c18255fe741c6aa64eb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.66", ] [[package]] @@ -1867,7 +1879,7 @@ dependencies = [ "proc-macro2", "quote", "syn 1.0.109", - "synstructure", + "synstructure 0.12.6", ] [[package]] @@ -2113,7 +2125,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.66", ] [[package]] @@ -2195,7 +2207,7 @@ checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" [[package]] name = "grovedb" version = "1.0.0-rc.2" -source = "git+https://github.com/dashpay/grovedb?branch=feat/QuerySumTree#8664b723330cc3850edbebd5f336b982f29ed23c" +source = "git+https://github.com/dashpay/grovedb?branch=feat/QuerySumTree#0b32606fd4983899ca2b5865299f04b1a0accc98" dependencies = [ "bincode 2.0.0-rc.3", "bitvec", @@ -2218,7 +2230,7 @@ dependencies = [ [[package]] name = "grovedb-costs" version = "1.0.0-rc.2" -source = "git+https://github.com/dashpay/grovedb?branch=feat/QuerySumTree#8664b723330cc3850edbebd5f336b982f29ed23c" +source = "git+https://github.com/dashpay/grovedb?branch=feat/QuerySumTree#0b32606fd4983899ca2b5865299f04b1a0accc98" dependencies = [ "integer-encoding", "intmap", @@ -2228,7 +2240,7 @@ dependencies = [ [[package]] name = "grovedb-merk" version = "1.0.0-rc.2" -source = "git+https://github.com/dashpay/grovedb?branch=feat/QuerySumTree#8664b723330cc3850edbebd5f336b982f29ed23c" +source = "git+https://github.com/dashpay/grovedb?branch=feat/QuerySumTree#0b32606fd4983899ca2b5865299f04b1a0accc98" dependencies = [ "blake3", "byteorder", @@ -2251,12 +2263,12 @@ dependencies = [ [[package]] name = "grovedb-path" version = "1.0.0-rc.2" -source = "git+https://github.com/dashpay/grovedb?branch=feat/QuerySumTree#8664b723330cc3850edbebd5f336b982f29ed23c" +source = "git+https://github.com/dashpay/grovedb?branch=feat/QuerySumTree#0b32606fd4983899ca2b5865299f04b1a0accc98" [[package]] name = "grovedb-storage" version = "1.0.0-rc.2" -source = "git+https://github.com/dashpay/grovedb?branch=feat/QuerySumTree#8664b723330cc3850edbebd5f336b982f29ed23c" +source = "git+https://github.com/dashpay/grovedb?branch=feat/QuerySumTree#0b32606fd4983899ca2b5865299f04b1a0accc98" dependencies = [ "blake3", "grovedb-costs", @@ -2267,7 +2279,7 @@ dependencies = [ "lazy_static", "num_cpus", "rocksdb", - "strum 0.26.3", + "strum 0.26.2", "tempfile", "thiserror", ] @@ -2275,7 +2287,7 @@ dependencies = [ [[package]] name = "grovedb-visualize" version = "1.0.0-rc.2" -source = "git+https://github.com/dashpay/grovedb?branch=feat/QuerySumTree#8664b723330cc3850edbebd5f336b982f29ed23c" +source = "git+https://github.com/dashpay/grovedb?branch=feat/QuerySumTree#0b32606fd4983899ca2b5865299f04b1a0accc98" dependencies = [ "hex", "itertools 0.12.1", @@ -2607,6 +2619,124 @@ dependencies = [ "cc", ] +[[package]] +name = "icu_collections" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locid" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_locid_transform" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_locid_transform_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_locid_transform_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e" + +[[package]] +name = "icu_normalizer" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "utf16_iter", + "utf8_iter", + "write16", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516" + +[[package]] +name = "icu_properties" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f8ac670d7422d7f76b32e17a5db556510825b29ec9154f235977c9caba61036" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_locid_transform", + "icu_properties_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569" + +[[package]] +name = "icu_provider" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_provider_macros", + "stable_deref_trait", + "tinystr", + "writeable", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_provider_macros" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.66", +] + [[package]] name = "ident_case" version = "1.0.1" @@ -2615,12 +2745,14 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" [[package]] name = "idna" -version = "0.5.0" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" +checksum = "4716a3a0933a1d01c2f72450e89596eb51dd34ef3c211ccd875acdf1f8fe47ed" dependencies = [ - "unicode-bidi", - "unicode-normalization", + "icu_normalizer", + "icu_properties", + "smallvec", + "utf8_iter", ] [[package]] @@ -2863,9 +2995,9 @@ dependencies = [ [[package]] name = "lazy_static" -version = "1.5.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "lazycell" @@ -2893,9 +3025,9 @@ checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" [[package]] name = "libloading" -version = "0.8.4" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e310b3a6b5907f99202fcdb4960ff45b93735d7c7d96b760fcff8db2dc0e103d" +checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19" dependencies = [ "cfg-if", "windows-targets 0.52.5", @@ -2950,6 +3082,12 @@ version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" +[[package]] +name = "litemap" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "643cb0b8d4fcc284004d5fd0d67ccf61dfffadb7f75e1e71bc420f4688a3a704" + [[package]] name = "lock_api" version = "0.4.12" @@ -3308,7 +3446,7 @@ checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" dependencies = [ "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.66", ] [[package]] @@ -3438,7 +3576,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.66", ] [[package]] @@ -3539,7 +3677,7 @@ checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" dependencies = [ "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.66", ] [[package]] @@ -3584,7 +3722,7 @@ version = "1.0.0-dev.15" dependencies = [ "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.66", "virtue 0.0.14", ] @@ -3614,7 +3752,7 @@ name = "platform-value-convertible" version = "1.0.0-dev.15" dependencies = [ "quote", - "syn 2.0.68", + "syn 2.0.66", ] [[package]] @@ -3630,9 +3768,15 @@ version = "1.0.0-dev.15" dependencies = [ "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.66", ] +[[package]] +name = "platforms" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db23d408679286588f4d4644f965003d056e3dd5abcaaa938116871d7ce2fee7" + [[package]] name = "plotters" version = "0.3.6" @@ -3758,7 +3902,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f12335488a2f3b0a83b14edad48dca9879ce89b2edd10e80237e4e852dd645e" dependencies = [ "proc-macro2", - "syn 2.0.68", + "syn 2.0.66", ] [[package]] @@ -3806,9 +3950,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.86" +version = "1.0.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +checksum = "22244ce15aa966053a896d1accb3a6e68469b97c7f33f284b99f0d576879fc23" dependencies = [ "unicode-ident", ] @@ -3872,7 +4016,7 @@ dependencies = [ "prost 0.12.6", "prost-types 0.12.6", "regex", - "syn 2.0.68", + "syn 2.0.66", "tempfile", ] @@ -3899,7 +4043,7 @@ dependencies = [ "itertools 0.12.1", "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.66", ] [[package]] @@ -4541,7 +4685,7 @@ checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba" dependencies = [ "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.66", ] [[package]] @@ -4564,7 +4708,7 @@ checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.66", ] [[package]] @@ -4617,7 +4761,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.66", ] [[package]] @@ -4629,7 +4773,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.66", ] [[package]] @@ -4834,9 +4978,9 @@ dependencies = [ [[package]] name = "strum" -version = "0.26.3" +version = "0.26.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" +checksum = "5d8cec3501a5194c432b2b7976db6b7d10ec95c253208b45f83f7136aa985e29" dependencies = [ "strum_macros 0.26.4", ] @@ -4851,7 +4995,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.68", + "syn 2.0.66", ] [[package]] @@ -4864,14 +5008,14 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.68", + "syn 2.0.66", ] [[package]] name = "subtle" -version = "2.6.1" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" +checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" [[package]] name = "subtle-encoding" @@ -4895,9 +5039,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.68" +version = "2.0.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "901fa70d88b9d6c98022e23b4136f9f3e54e4662c3bc1bd1d84a42a9a0f0c1e9" +checksum = "c42f3f41a2de00b01c0aaad383c5a45241efc8b2d1eda5661812fda5f3cdcff5" dependencies = [ "proc-macro2", "quote", @@ -4913,7 +5057,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.66", ] [[package]] @@ -4934,6 +5078,17 @@ dependencies = [ "unicode-xid", ] +[[package]] +name = "synstructure" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.66", +] + [[package]] name = "system-interface" version = "0.26.1" @@ -5100,7 +5255,7 @@ checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" dependencies = [ "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.66", ] [[package]] @@ -5144,6 +5299,16 @@ dependencies = [ "time-core", ] +[[package]] +name = "tinystr" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" +dependencies = [ + "displaydoc", + "zerovec", +] + [[package]] name = "tinytemplate" version = "1.2.1" @@ -5207,7 +5372,7 @@ checksum = "5f5ae998a069d4b5aba8ee9dad856af7d520c3699e6159b185c2acd48155d39a" dependencies = [ "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.66", ] [[package]] @@ -5406,7 +5571,7 @@ dependencies = [ "proc-macro2", "prost-build 0.12.6", "quote", - "syn 2.0.68", + "syn 2.0.66", ] [[package]] @@ -5458,7 +5623,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.66", ] [[package]] @@ -5546,27 +5711,12 @@ dependencies = [ "version_check", ] -[[package]] -name = "unicode-bidi" -version = "0.3.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" - [[package]] name = "unicode-ident" version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" -[[package]] -name = "unicode-normalization" -version = "0.1.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" -dependencies = [ - "tinyvec", -] - [[package]] name = "unicode-width" version = "0.1.13" @@ -5604,15 +5754,27 @@ dependencies = [ [[package]] name = "url" -version = "2.5.2" +version = "2.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" +checksum = "f7c25da092f0a868cdf09e8674cd3b7ef3a7d92a24253e663a2fb85e2496de56" dependencies = [ "form_urlencoded", "idna", "percent-encoding", ] +[[package]] +name = "utf16_iter" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" + +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + [[package]] name = "utf8parse" version = "0.2.2" @@ -5621,9 +5783,9 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" -version = "1.9.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ea73390fe27785838dcbf75b91b1d84799e28f1ce71e6f372a5dc2200c80de5" +checksum = "a183cf7feeba97b4dd1c0d46788634f6221d87fa961b305bed08c851829efcc0" dependencies = [ "getrandom", "rand", @@ -5754,7 +5916,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.66", "wasm-bindgen-shared", ] @@ -5788,7 +5950,7 @@ checksum = "e128beba882dd1eb6200e1dc92ae6c5dbaa4311aa7bb211ca035779e5efc39f8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.66", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -6031,7 +6193,7 @@ checksum = "f55c5565959287c21dd0f4277ae3518dd2ae62679f655ee2dbc4396e19d210db" dependencies = [ "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.66", ] [[package]] @@ -6126,7 +6288,7 @@ dependencies = [ "proc-macro2", "quote", "shellexpand", - "syn 2.0.68", + "syn 2.0.66", "witx", ] @@ -6138,7 +6300,7 @@ checksum = "31ae1ec11a17ea481539ee9a5719a278c9790d974060fbf71db4b2c05378780b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.66", "wiggle-generate", ] @@ -6374,6 +6536,18 @@ dependencies = [ "wast", ] +[[package]] +name = "write16" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" + +[[package]] +name = "writeable" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" + [[package]] name = "wyz" version = "0.5.1" @@ -6389,6 +6563,30 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec" +[[package]] +name = "yoke" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c5b1314b079b0930c31e3af543d8ee1757b1951ae1e1565ec704403a7240ca5" +dependencies = [ + "serde", + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28cc31741b18cb6f1d5ff12f5b7523e3d6eb0852bbbad19d73905511d9849b95" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.66", + "synstructure 0.13.1", +] + [[package]] name = "zerocopy" version = "0.7.34" @@ -6406,7 +6604,28 @@ checksum = "15e934569e47891f7d9411f1a451d947a60e000ab3bd24fbb970f000387d1b3b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.66", +] + +[[package]] +name = "zerofrom" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91ec111ce797d0e0784a1116d0ddcdbea84322cd79e5d5ad173daeba4f93ab55" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ea7b4a3637ea8669cedf0f1fd5c286a17f3de97b8dd5a70a6c167a1730e63a5" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.66", + "synstructure 0.13.1", ] [[package]] @@ -6415,6 +6634,28 @@ version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" +[[package]] +name = "zerovec" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb2cc8827d6c0994478a15c53f374f46fbd41bea663d809b14744bc42e6b109c" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97cf56601ee5052b4417d90c8755c6683473c926039908196cf35d99f893ebe7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.66", +] + [[package]] name = "zip" version = "0.6.6" diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/masternode_vote/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/masternode_vote/mod.rs index f1dacfd1416..3e7d74f39e5 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/masternode_vote/mod.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/masternode_vote/mod.rs @@ -920,6 +920,104 @@ mod tests { } } + #[test] + fn test_non_existing_end_index_value_many_values() { + let platform_version = PlatformVersion::latest(); + let mut platform = TestPlatformBuilder::new() + .build_with_mock_rpc() + .set_genesis_state(); + + let platform_state = platform.state.load(); + + let (_contender_1, _contender_2, dpns_contract) = create_dpns_name_contest( + &mut platform, + &platform_state, + 7, + "quantum", + platform_version, + ); + + let domain = dpns_contract + .document_type_for_name("domain") + .expect("expected a profile document type"); + + let config = bincode::config::standard() + .with_big_endian() + .with_no_limit(); + + let encoded_non_existing_value_1 = + bincode::encode_to_vec(Value::Text("cashcash".to_string()), config) + .expect("expected to encode value"); + + let encoded_non_existing_value_2 = + bincode::encode_to_vec(Value::Text("cennnn".to_string()), config) + .expect("expected to encode value"); + + let index_name = "parentNameAndLabel".to_string(); + + { + let query_validation_error = platform + .query_contested_resources( + GetContestedResourcesRequest { + version: Some(get_contested_resources_request::Version::V0( + GetContestedResourcesRequestV0 { + contract_id: dpns_contract.id().to_vec(), + document_type_name: domain.name().clone(), + index_name: index_name.clone(), + start_index_values: vec![], + end_index_values: vec![ + encoded_non_existing_value_1.clone(), + encoded_non_existing_value_2.clone(), + ], + start_at_value_info: None, + count: None, + order_ascending: true, + prove: false, + }, + )), + }, + &platform_state, + platform_version, + ) + .expect("expected to execute query") + .first_error() + .map(|e| e.to_string()); + + assert_eq!(query_validation_error, Some("query syntax error: incorrect index values error: too many end index values were provided".to_string())); + } + + { + let query_validation_error = platform + .query_contested_resources( + GetContestedResourcesRequest { + version: Some(get_contested_resources_request::Version::V0( + GetContestedResourcesRequestV0 { + contract_id: dpns_contract.id().to_vec(), + document_type_name: domain.name().clone(), + index_name: index_name.clone(), + start_index_values: vec![], + end_index_values: vec![ + encoded_non_existing_value_1.clone(), + encoded_non_existing_value_2.clone(), + ], + start_at_value_info: None, + count: None, + order_ascending: true, + prove: true, + }, + )), + }, + &platform_state, + platform_version, + ) + .expect("expected to execute query") + .first_error() + .map(|e| e.to_string()); + + assert_eq!(query_validation_error, Some("query syntax error: incorrect index values error: too many end index values were provided".to_string())); + } + } + #[test] #[ignore] // Currently will have an issue due to a grovedb bug fn test_limit() { diff --git a/packages/rs-drive/src/query/vote_polls_by_document_type_query.rs b/packages/rs-drive/src/query/vote_polls_by_document_type_query.rs index 1f7c672d574..743bbe26ba7 100644 --- a/packages/rs-drive/src/query/vote_polls_by_document_type_query.rs +++ b/packages/rs-drive/src/query/vote_polls_by_document_type_query.rs @@ -325,11 +325,16 @@ impl<'a> ResolvedVotePollsByDocumentTypeQuery<'a> { break; } } + if end_values_iter.next().is_some() { + return Err(Error::Query(QuerySyntaxError::IndexValuesError( + "too many end index values were provided".to_string(), + ))); + } let middle_index_property = middle_index_property.ok_or_else(|| { let error_msg = if has_end_index_values { "since end index values were provided, the start index values and the end index values must be equal to the amount of properties in the contested index minus one, we could not find a middle property".to_string() } else { - "too many start values were provided, since no end index values were provided, the start index values must be less than the amount of properties in the contested index".to_string() + "too many start index values were provided, since no end index values were provided, the start index values must be less than the amount of properties in the contested index".to_string() }; Error::Query(QuerySyntaxError::IndexValuesError(error_msg)) })?; From 5834c1b2a1c92e9cd59cd1ec7e20c1a3176fde8c Mon Sep 17 00:00:00 2001 From: Lukasz Klimek <842586+lklimek@users.noreply.github.com> Date: Tue, 25 Jun 2024 14:08:39 +0200 Subject: [PATCH 22/55] feat(sdk): add OrderedBtreeMap that can be iterated in asc or desc order --- packages/rs-drive-proof-verifier/src/lib.rs | 1 + .../src/ordered_btreemap.rs | 130 ++++++++++++++++++ packages/rs-drive-proof-verifier/src/proof.rs | 2 +- packages/rs-drive-proof-verifier/src/types.rs | 16 ++- .../fetch/prefunded_specialized_balance.rs | 3 +- 5 files changed, 147 insertions(+), 5 deletions(-) create mode 100644 packages/rs-drive-proof-verifier/src/ordered_btreemap.rs diff --git a/packages/rs-drive-proof-verifier/src/lib.rs b/packages/rs-drive-proof-verifier/src/lib.rs index bf38d555ef7..21b45a876d3 100644 --- a/packages/rs-drive-proof-verifier/src/lib.rs +++ b/packages/rs-drive-proof-verifier/src/lib.rs @@ -3,6 +3,7 @@ /// Errors that can occur during proof verification pub mod error; +pub mod ordered_btreemap; /// Implementation of proof verification mod proof; mod provider; diff --git a/packages/rs-drive-proof-verifier/src/ordered_btreemap.rs b/packages/rs-drive-proof-verifier/src/ordered_btreemap.rs new file mode 100644 index 00000000000..16c9fc8f8a0 --- /dev/null +++ b/packages/rs-drive-proof-verifier/src/ordered_btreemap.rs @@ -0,0 +1,130 @@ +//! [BTreeMap] that can be ordered in either ascending or descending order. +use bincode::{Decode, Encode}; +use std::collections::btree_map::{Iter, Keys}; +use std::{collections::BTreeMap, iter::Rev}; + +/// Iterator that can be either forward or reverse. +/// +/// Used to iterate over items in a map in either ascending or descending order. +pub enum OrderedIterator { + /// Items are iterated in ascending order. + Ascending(I), + /// Items are iterated in descending order. + Descending(Rev), +} + +/// BTreeMap that can be ordered in either ascending or descending order. +#[derive(Clone, Debug, Default, derive_more::From)] +#[cfg_attr(feature = "mocks", derive(Encode, Decode))] + +pub struct OrderedBTreeMap { + /// The inner map. + inner: BTreeMap, + /// When set to true, the map will be ordered in ascending order. + order_ascending: bool, +} + +impl OrderedBTreeMap { + /// Create a new OrderedBTreeMap with provided ordering. + pub fn new(order_ascending: bool) -> Self { + Self { + inner: BTreeMap::new(), + order_ascending, + } + } + + /// Creates a new OrderedBTreeMap from a BTreeMap with the provided ordering. + /// + /// This function consumes the provided map to avoid cloning it, thus it is more efficient than + /// creating a new OrderedBTreeMap and then extending it with the provided map. + pub fn from_btreemap(map: BTreeMap, order_ascending: bool) -> Self { + Self { + inner: map, + order_ascending, + } + } + + /// Returns an iterator over the map. + /// + /// See [BTreemap::iter()] for more information. + pub fn iter(&self) -> OrderedIterator> { + if self.order_ascending { + OrderedIterator::Ascending(self.inner.iter()) + } else { + OrderedIterator::Descending(self.inner.iter().rev()) + } + } + + /// Returns true if the map is empty. + pub fn is_empty(&self) -> bool { + self.inner.is_empty() + } + + /// Returns the number of elements in the map. + pub fn len(&self) -> usize { + self.inner.len() + } + + /// Gets an iterator over the keys of the map, in sorted order. + pub fn keys(&self) -> OrderedIterator> { + if self.order_ascending { + OrderedIterator::Ascending(self.inner.keys()) + } else { + OrderedIterator::Descending(self.inner.keys().rev()) + } + } + + /// Gets all values in the map as a vector, ordered by key. + pub fn values_vec(&self) -> Vec<&V> { + self.iter().map(|(_k, v)| v).collect() + } +} + +impl From> for BTreeMap { + fn from(value: OrderedBTreeMap) -> Self { + value.inner + } +} + +impl Extend<(K, V)> for OrderedBTreeMap { + fn extend(&mut self, iter: T) + where + T: IntoIterator, + { + self.inner.extend(iter) + } +} + +impl From> for OrderedBTreeMap { + fn from(value: BTreeMap) -> Self { + Self { + inner: value, + order_ascending: true, // btreemap is always ordered in ascending order + } + } +} + +impl IntoIterator for OrderedBTreeMap { + type Item = (K, V); + type IntoIter = OrderedIterator< as IntoIterator>::IntoIter>; + + fn into_iter(self) -> Self::IntoIter { + let iter = self.inner.into_iter(); + if self.order_ascending { + OrderedIterator::Ascending(iter) + } else { + OrderedIterator::Descending(iter.rev()) + } + } +} + +impl Iterator for OrderedIterator { + type Item = I::Item; + + fn next(&mut self) -> Option { + match self { + OrderedIterator::Ascending(iter) => iter.next(), + OrderedIterator::Descending(iter) => iter.next(), + } + } +} diff --git a/packages/rs-drive-proof-verifier/src/proof.rs b/packages/rs-drive-proof-verifier/src/proof.rs index bdd0a506149..8363bcaa708 100644 --- a/packages/rs-drive-proof-verifier/src/proof.rs +++ b/packages/rs-drive-proof-verifier/src/proof.rs @@ -1665,7 +1665,7 @@ define_length!(Contenders, |x: &Contenders| x.contenders.len()); define_length!(Voters, |x: &Voters| x.0.len()); define_length!( VotePollsGroupedByTimestamp, - |x: &VotePollsGroupedByTimestamp| x.0.values().map(|v| v.len()).sum() + |x: &VotePollsGroupedByTimestamp| x.0.values_vec().into_iter().map(|v| v.len()).sum() ); trait IntoOption where diff --git a/packages/rs-drive-proof-verifier/src/types.rs b/packages/rs-drive-proof-verifier/src/types.rs index 5955c040de9..99d15ee1263 100644 --- a/packages/rs-drive-proof-verifier/src/types.rs +++ b/packages/rs-drive-proof-verifier/src/types.rs @@ -5,6 +5,7 @@ //! In this case, the [FromProof](crate::FromProof) trait is implemented for dedicated object type //! defined in this module. +use crate::ordered_btreemap::{OrderedBTreeMap, OrderedIterator}; use dpp::data_contract::document_type::DocumentType; use dpp::fee::Credits; use dpp::platform_value::Value; @@ -25,7 +26,9 @@ use dpp::{ util::deserializer::ProtocolVersion, }; use drive::grovedb::Element; +use std::collections::btree_map::IntoIter; use std::collections::{BTreeMap, BTreeSet}; + #[cfg(feature = "mocks")] use { bincode::{Decode, Encode}, @@ -293,19 +296,26 @@ impl From<&PrefundedSpecializedBalance> for Credits { derive(Encode, Decode, PlatformSerialize, PlatformDeserialize), platform_serialize(unversioned) )] -pub struct VotePollsGroupedByTimestamp(pub BTreeMap>); +pub struct VotePollsGroupedByTimestamp(pub OrderedBTreeMap>); /// Insert items into the map, appending them to the existing values for the same key. impl FromIterator<(u64, Vec)> for VotePollsGroupedByTimestamp { fn from_iter)>>(iter: T) -> Self { let mut map = BTreeMap::new(); + let mut order_ascending = true; + let mut prev = 0; for (timestamp, vote_poll) in iter { let entry = map.entry(timestamp).or_insert_with(Vec::new); entry.extend(vote_poll); + + if timestamp < prev { + order_ascending = false; + } + prev = timestamp; } - Self(map) + OrderedBTreeMap::from_btreemap(map, order_ascending).into() } } @@ -329,7 +339,7 @@ impl FromIterator<(u64, Option)> for VotePollsGroupedByTimestamp { impl IntoIterator for VotePollsGroupedByTimestamp { type Item = (u64, Vec); - type IntoIter = std::collections::btree_map::IntoIter>; + type IntoIter = OrderedIterator>>; fn into_iter(self) -> Self::IntoIter { self.0.into_iter() diff --git a/packages/rs-sdk/tests/fetch/prefunded_specialized_balance.rs b/packages/rs-sdk/tests/fetch/prefunded_specialized_balance.rs index 88d016783db..d2db8aa5f94 100644 --- a/packages/rs-sdk/tests/fetch/prefunded_specialized_balance.rs +++ b/packages/rs-sdk/tests/fetch/prefunded_specialized_balance.rs @@ -49,7 +49,8 @@ async fn test_prefunded_specialized_balance_ok() { let poll = polls .0 - .first_key_value() + .iter() + .next() .expect("need at least one vote poll timestamp") .1 .first() From a52e4ec9b7e7309636fb45a4f180539df0257d28 Mon Sep 17 00:00:00 2001 From: Lukasz Klimek <842586+lklimek@users.noreply.github.com> Date: Tue, 25 Jun 2024 14:55:38 +0200 Subject: [PATCH 23/55] build: update Cargo.lock --- Cargo.lock | 572 +++++++++++++++++++++-------------------------------- 1 file changed, 229 insertions(+), 343 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9f6c164398b..1edb655570a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,6 +17,17 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +[[package]] +name = "aes" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" +dependencies = [ + "cfg-if", + "cipher", + "cpufeatures", +] + [[package]] name = "ahash" version = "0.7.8" @@ -211,7 +222,7 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -222,7 +233,7 @@ checksum = "c6fa2087f2753a7da8cc1c0dbfcf89579dd57458e36769de5ac750b4671737ca" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -397,7 +408,7 @@ dependencies = [ "regex", "rustc-hash", "shlex", - "syn 2.0.66", + "syn 2.0.68", "which", ] @@ -407,7 +418,7 @@ version = "0.69.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a00dc851838a2120612785d195287475a3ac45514741da670b735818822129a0" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "cexpr", "clang-sys", "itertools 0.12.1", @@ -418,7 +429,7 @@ dependencies = [ "regex", "rustc-hash", "shlex", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -469,9 +480,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" [[package]] name = "bitvec" @@ -495,7 +506,7 @@ dependencies = [ "arrayvec", "cc", "cfg-if", - "constant_time_eq", + "constant_time_eq 0.3.0", ] [[package]] @@ -548,7 +559,7 @@ dependencies = [ "proc-macro-crate 3.1.0", "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", "syn_derive", ] @@ -616,6 +627,16 @@ dependencies = [ "serde", ] +[[package]] +name = "bzip2" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bdb116a6ef3f6c3698828873ad02c3014b3c85cadb88496095628e3ef1e347f8" +dependencies = [ + "bzip2-sys", + "libc", +] + [[package]] name = "bzip2-sys" version = "0.1.11+1.0.8" @@ -731,9 +752,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.0.99" +version = "1.0.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96c51067fd44124faa7f870b4b1c969379ad32b2ba805aa959430ceaa384f695" +checksum = "c891175c3fb232128f48de6590095e59198bbeb8620c310be349bfc3afd12c7b" dependencies = [ "jobserver", "libc", @@ -807,6 +828,16 @@ dependencies = [ "half", ] +[[package]] +name = "cipher" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" +dependencies = [ + "crypto-common", + "inout", +] + [[package]] name = "clang-sys" version = "1.8.1" @@ -860,7 +891,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -937,6 +968,12 @@ version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" +[[package]] +name = "constant_time_eq" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" + [[package]] name = "constant_time_eq" version = "0.3.0" @@ -1217,16 +1254,15 @@ dependencies = [ [[package]] name = "curve25519-dalek" -version = "4.1.2" +version = "4.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a677b8922c94e01bdbb12126b0bc852f00447528dee1782229af9c720c3f348" +checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be" dependencies = [ "cfg-if", "cpufeatures", "curve25519-dalek-derive", "digest", "fiat-crypto", - "platforms", "rustc_version", "subtle", "zeroize", @@ -1240,7 +1276,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -1266,7 +1302,7 @@ dependencies = [ "dapi-grpc", "heck 0.5.0", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -1290,7 +1326,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -1301,7 +1337,7 @@ checksum = "733cabb43482b1a1b53eee8583c2b9e8684d592215ea83efd305dd31bc2f0178" dependencies = [ "darling_core", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -1469,7 +1505,7 @@ dependencies = [ "proc-macro2", "quote", "rustc_version", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -1492,6 +1528,7 @@ checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ "block-buffer", "crypto-common", + "subtle", ] [[package]] @@ -1525,17 +1562,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "displaydoc" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.66", -] - [[package]] name = "dotenvy" version = "0.15.7" @@ -1791,7 +1817,7 @@ checksum = "f282cfdfe92516eb26c2af8589c274c7c17681f5ecc03c18255fe741c6aa64eb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -1879,7 +1905,7 @@ dependencies = [ "proc-macro2", "quote", "syn 1.0.109", - "synstructure 0.12.6", + "synstructure", ] [[package]] @@ -2125,7 +2151,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -2207,7 +2233,7 @@ checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" [[package]] name = "grovedb" version = "1.0.0-rc.2" -source = "git+https://github.com/dashpay/grovedb?branch=feat/QuerySumTree#0b32606fd4983899ca2b5865299f04b1a0accc98" +source = "git+https://github.com/dashpay/grovedb?branch=feat/QuerySumTree#d77bbf5bf6ab0eb48cca226fadc3764ca5c80d0f" dependencies = [ "bincode 2.0.0-rc.3", "bitvec", @@ -2225,12 +2251,13 @@ dependencies = [ "nohash-hasher", "tempfile", "thiserror", + "zip-extensions", ] [[package]] name = "grovedb-costs" version = "1.0.0-rc.2" -source = "git+https://github.com/dashpay/grovedb?branch=feat/QuerySumTree#0b32606fd4983899ca2b5865299f04b1a0accc98" +source = "git+https://github.com/dashpay/grovedb?branch=feat/QuerySumTree#d77bbf5bf6ab0eb48cca226fadc3764ca5c80d0f" dependencies = [ "integer-encoding", "intmap", @@ -2240,7 +2267,7 @@ dependencies = [ [[package]] name = "grovedb-merk" version = "1.0.0-rc.2" -source = "git+https://github.com/dashpay/grovedb?branch=feat/QuerySumTree#0b32606fd4983899ca2b5865299f04b1a0accc98" +source = "git+https://github.com/dashpay/grovedb?branch=feat/QuerySumTree#d77bbf5bf6ab0eb48cca226fadc3764ca5c80d0f" dependencies = [ "blake3", "byteorder", @@ -2263,12 +2290,12 @@ dependencies = [ [[package]] name = "grovedb-path" version = "1.0.0-rc.2" -source = "git+https://github.com/dashpay/grovedb?branch=feat/QuerySumTree#0b32606fd4983899ca2b5865299f04b1a0accc98" +source = "git+https://github.com/dashpay/grovedb?branch=feat/QuerySumTree#d77bbf5bf6ab0eb48cca226fadc3764ca5c80d0f" [[package]] name = "grovedb-storage" version = "1.0.0-rc.2" -source = "git+https://github.com/dashpay/grovedb?branch=feat/QuerySumTree#0b32606fd4983899ca2b5865299f04b1a0accc98" +source = "git+https://github.com/dashpay/grovedb?branch=feat/QuerySumTree#d77bbf5bf6ab0eb48cca226fadc3764ca5c80d0f" dependencies = [ "blake3", "grovedb-costs", @@ -2279,7 +2306,7 @@ dependencies = [ "lazy_static", "num_cpus", "rocksdb", - "strum 0.26.2", + "strum 0.26.3", "tempfile", "thiserror", ] @@ -2287,7 +2314,7 @@ dependencies = [ [[package]] name = "grovedb-visualize" version = "1.0.0-rc.2" -source = "git+https://github.com/dashpay/grovedb?branch=feat/QuerySumTree#0b32606fd4983899ca2b5865299f04b1a0accc98" +source = "git+https://github.com/dashpay/grovedb?branch=feat/QuerySumTree#d77bbf5bf6ab0eb48cca226fadc3764ca5c80d0f" dependencies = [ "hex", "itertools 0.12.1", @@ -2420,6 +2447,15 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3011d1213f159867b13cfd6ac92d2cd5f1345762c63be3554e84092d85a50bbd" +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest", +] + [[package]] name = "home" version = "0.5.9" @@ -2619,124 +2655,6 @@ dependencies = [ "cc", ] -[[package]] -name = "icu_collections" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" -dependencies = [ - "displaydoc", - "yoke", - "zerofrom", - "zerovec", -] - -[[package]] -name = "icu_locid" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" -dependencies = [ - "displaydoc", - "litemap", - "tinystr", - "writeable", - "zerovec", -] - -[[package]] -name = "icu_locid_transform" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" -dependencies = [ - "displaydoc", - "icu_locid", - "icu_locid_transform_data", - "icu_provider", - "tinystr", - "zerovec", -] - -[[package]] -name = "icu_locid_transform_data" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e" - -[[package]] -name = "icu_normalizer" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" -dependencies = [ - "displaydoc", - "icu_collections", - "icu_normalizer_data", - "icu_properties", - "icu_provider", - "smallvec", - "utf16_iter", - "utf8_iter", - "write16", - "zerovec", -] - -[[package]] -name = "icu_normalizer_data" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516" - -[[package]] -name = "icu_properties" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f8ac670d7422d7f76b32e17a5db556510825b29ec9154f235977c9caba61036" -dependencies = [ - "displaydoc", - "icu_collections", - "icu_locid_transform", - "icu_properties_data", - "icu_provider", - "tinystr", - "zerovec", -] - -[[package]] -name = "icu_properties_data" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569" - -[[package]] -name = "icu_provider" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" -dependencies = [ - "displaydoc", - "icu_locid", - "icu_provider_macros", - "stable_deref_trait", - "tinystr", - "writeable", - "yoke", - "zerofrom", - "zerovec", -] - -[[package]] -name = "icu_provider_macros" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.66", -] - [[package]] name = "ident_case" version = "1.0.1" @@ -2745,14 +2663,12 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" [[package]] name = "idna" -version = "1.0.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4716a3a0933a1d01c2f72450e89596eb51dd34ef3c211ccd875acdf1f8fe47ed" +checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" dependencies = [ - "icu_normalizer", - "icu_properties", - "smallvec", - "utf8_iter", + "unicode-bidi", + "unicode-normalization", ] [[package]] @@ -2777,6 +2693,15 @@ dependencies = [ "serde", ] +[[package]] +name = "inout" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" +dependencies = [ + "generic-array", +] + [[package]] name = "instant" version = "0.1.13" @@ -2995,9 +2920,9 @@ dependencies = [ [[package]] name = "lazy_static" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "lazycell" @@ -3025,9 +2950,9 @@ checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" [[package]] name = "libloading" -version = "0.8.3" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19" +checksum = "e310b3a6b5907f99202fcdb4960ff45b93735d7c7d96b760fcff8db2dc0e103d" dependencies = [ "cfg-if", "windows-targets 0.52.5", @@ -3039,7 +2964,7 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "libc", ] @@ -3082,12 +3007,6 @@ version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" -[[package]] -name = "litemap" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "643cb0b8d4fcc284004d5fd0d67ccf61dfffadb7f75e1e71bc420f4688a3a704" - [[package]] name = "lock_api" version = "0.4.12" @@ -3446,7 +3365,7 @@ checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -3559,7 +3478,7 @@ version = "0.10.64" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95a0481286a310808298130d22dd1fef0fa571e05a8f44ec801801e84b216b1f" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "cfg-if", "foreign-types", "libc", @@ -3576,7 +3495,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -3632,12 +3551,35 @@ dependencies = [ "windows-targets 0.52.5", ] +[[package]] +name = "password-hash" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7676374caaee8a325c9e7a2ae557f216c5563a171d6997b0ef8a65af35147700" +dependencies = [ + "base64ct", + "rand_core", + "subtle", +] + [[package]] name = "paste" version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" +[[package]] +name = "pbkdf2" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917" +dependencies = [ + "digest", + "hmac", + "password-hash", + "sha2", +] + [[package]] name = "peeking_take_while" version = "0.1.2" @@ -3677,7 +3619,7 @@ checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -3722,7 +3664,7 @@ version = "1.0.0-dev.15" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", "virtue 0.0.14", ] @@ -3752,7 +3694,7 @@ name = "platform-value-convertible" version = "1.0.0-dev.15" dependencies = [ "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -3768,15 +3710,9 @@ version = "1.0.0-dev.15" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] -[[package]] -name = "platforms" -version = "3.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db23d408679286588f4d4644f965003d056e3dd5abcaaa938116871d7ce2fee7" - [[package]] name = "plotters" version = "0.3.6" @@ -3902,7 +3838,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f12335488a2f3b0a83b14edad48dca9879ce89b2edd10e80237e4e852dd645e" dependencies = [ "proc-macro2", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -3950,9 +3886,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.85" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22244ce15aa966053a896d1accb3a6e68469b97c7f33f284b99f0d576879fc23" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" dependencies = [ "unicode-ident", ] @@ -4016,7 +3952,7 @@ dependencies = [ "prost 0.12.6", "prost-types 0.12.6", "regex", - "syn 2.0.66", + "syn 2.0.68", "tempfile", ] @@ -4043,7 +3979,7 @@ dependencies = [ "itertools 0.12.1", "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -4099,7 +4035,7 @@ version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57206b407293d2bcd3af849ce869d52068623f19e1b5ff8e8778e3309439682b" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "memchr", "unicase", ] @@ -4195,7 +4131,7 @@ version = "11.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e29830cbb1290e404f24c73af91c5d8d631ce7e128691e9477556b540cd01ecd" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", ] [[package]] @@ -4224,7 +4160,7 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c82cf8cff14456045f55ec4241383baeff27af886adb72ffb2162f99911de0fd" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", ] [[package]] @@ -4462,7 +4398,7 @@ version = "0.38.34" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "errno", "itoa", "libc", @@ -4613,7 +4549,7 @@ version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c627723fd09706bacdb5cf41499e95098555af3c3c29d014dc3c458ef6be11c0" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "core-foundation", "core-foundation-sys", "libc", @@ -4660,9 +4596,9 @@ dependencies = [ [[package]] name = "serde_bytes" -version = "0.11.14" +version = "0.11.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b8497c313fd43ab992087548117643f6fcd935cbf36f176ffda0aacf9591734" +checksum = "387cc504cb06bb40a96c8e04e951fe01854cf6bc921053c954e4a606d9675c6a" dependencies = [ "serde", ] @@ -4685,14 +4621,14 @@ checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] name = "serde_json" -version = "1.0.117" +version = "1.0.118" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "455182ea6142b14f93f4bc5320a2b31c1f266b66a4a5c858b013302a5d8cbfc3" +checksum = "d947f6b3163d8857ea16c4fa0dd4840d52f3041039a85decd46867eb1abef2e4" dependencies = [ "indexmap 2.2.6", "itoa", @@ -4708,7 +4644,7 @@ checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -4761,7 +4697,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -4773,7 +4709,18 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", +] + +[[package]] +name = "sha1" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", ] [[package]] @@ -4978,9 +4925,9 @@ dependencies = [ [[package]] name = "strum" -version = "0.26.2" +version = "0.26.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d8cec3501a5194c432b2b7976db6b7d10ec95c253208b45f83f7136aa985e29" +checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" dependencies = [ "strum_macros 0.26.4", ] @@ -4995,7 +4942,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -5008,14 +4955,14 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] name = "subtle" -version = "2.5.0" +version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "subtle-encoding" @@ -5039,9 +4986,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.66" +version = "2.0.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c42f3f41a2de00b01c0aaad383c5a45241efc8b2d1eda5661812fda5f3cdcff5" +checksum = "901fa70d88b9d6c98022e23b4136f9f3e54e4662c3bc1bd1d84a42a9a0f0c1e9" dependencies = [ "proc-macro2", "quote", @@ -5057,7 +5004,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -5078,24 +5025,13 @@ dependencies = [ "unicode-xid", ] -[[package]] -name = "synstructure" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.66", -] - [[package]] name = "system-interface" version = "0.26.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0682e006dd35771e392a6623ac180999a9a854b1d4a6c12fb2e804941c2b1f58" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "cap-fs-ext", "cap-std", "fd-lock", @@ -5255,7 +5191,7 @@ checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -5299,16 +5235,6 @@ dependencies = [ "time-core", ] -[[package]] -name = "tinystr" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" -dependencies = [ - "displaydoc", - "zerovec", -] - [[package]] name = "tinytemplate" version = "1.2.1" @@ -5321,9 +5247,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.6.0" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +checksum = "c55115c6fbe2d2bef26eb09ad74bde02d8255476fc0c7b515ef09fbb35742d82" dependencies = [ "tinyvec_macros", ] @@ -5372,7 +5298,7 @@ checksum = "5f5ae998a069d4b5aba8ee9dad856af7d520c3699e6159b185c2acd48155d39a" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -5571,7 +5497,7 @@ dependencies = [ "proc-macro2", "prost-build 0.12.6", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -5623,7 +5549,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -5711,12 +5637,27 @@ dependencies = [ "version_check", ] +[[package]] +name = "unicode-bidi" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" + [[package]] name = "unicode-ident" version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +[[package]] +name = "unicode-normalization" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" +dependencies = [ + "tinyvec", +] + [[package]] name = "unicode-width" version = "0.1.13" @@ -5754,27 +5695,15 @@ dependencies = [ [[package]] name = "url" -version = "2.5.1" +version = "2.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7c25da092f0a868cdf09e8674cd3b7ef3a7d92a24253e663a2fb85e2496de56" +checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" dependencies = [ "form_urlencoded", "idna", "percent-encoding", ] -[[package]] -name = "utf16_iter" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" - -[[package]] -name = "utf8_iter" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" - [[package]] name = "utf8parse" version = "0.2.2" @@ -5783,9 +5712,9 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" -version = "1.8.0" +version = "1.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a183cf7feeba97b4dd1c0d46788634f6221d87fa961b305bed08c851829efcc0" +checksum = "5de17fd2f7da591098415cff336e12965a28061ddace43b59cb3c430179c9439" dependencies = [ "getrandom", "rand", @@ -5882,7 +5811,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d888b611fee7d273dd057dc009d2dd3132736f36710ffd65657ac83628d1e3b" dependencies = [ "anyhow", - "bitflags 2.5.0", + "bitflags 2.6.0", "cap-rand", "cap-std", "io-extras", @@ -5916,7 +5845,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", "wasm-bindgen-shared", ] @@ -5950,7 +5879,7 @@ checksum = "e128beba882dd1eb6200e1dc92ae6c5dbaa4311aa7bb211ca035779e5efc39f8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -6193,7 +6122,7 @@ checksum = "f55c5565959287c21dd0f4277ae3518dd2ae62679f655ee2dbc4396e19d210db" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -6270,7 +6199,7 @@ checksum = "0afb26cd3269289bb314a361ff0a6685e5ce793b62181a9fe3f81ace15051697" dependencies = [ "anyhow", "async-trait", - "bitflags 2.5.0", + "bitflags 2.6.0", "thiserror", "tracing", "wasmtime", @@ -6288,7 +6217,7 @@ dependencies = [ "proc-macro2", "quote", "shellexpand", - "syn 2.0.66", + "syn 2.0.68", "witx", ] @@ -6300,7 +6229,7 @@ checksum = "31ae1ec11a17ea481539ee9a5719a278c9790d974060fbf71db4b2c05378780b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", "wiggle-generate", ] @@ -6507,7 +6436,7 @@ version = "0.36.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f9643b83820c0cd246ecabe5fa454dd04ba4fa67996369466d0747472d337346" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "windows-sys 0.52.0", ] @@ -6536,18 +6465,6 @@ dependencies = [ "wast", ] -[[package]] -name = "write16" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" - -[[package]] -name = "writeable" -version = "0.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" - [[package]] name = "wyz" version = "0.5.1" @@ -6563,30 +6480,6 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec" -[[package]] -name = "yoke" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c5b1314b079b0930c31e3af543d8ee1757b1951ae1e1565ec704403a7240ca5" -dependencies = [ - "serde", - "stable_deref_trait", - "yoke-derive", - "zerofrom", -] - -[[package]] -name = "yoke-derive" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28cc31741b18cb6f1d5ff12f5b7523e3d6eb0852bbbad19d73905511d9849b95" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.66", - "synstructure 0.13.1", -] - [[package]] name = "zerocopy" version = "0.7.34" @@ -6604,68 +6497,61 @@ checksum = "15e934569e47891f7d9411f1a451d947a60e000ab3bd24fbb970f000387d1b3b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] -name = "zerofrom" -version = "0.1.4" +name = "zeroize" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91ec111ce797d0e0784a1116d0ddcdbea84322cd79e5d5ad173daeba4f93ab55" -dependencies = [ - "zerofrom-derive", -] +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" [[package]] -name = "zerofrom-derive" -version = "0.1.4" +name = "zip" +version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ea7b4a3637ea8669cedf0f1fd5c286a17f3de97b8dd5a70a6c167a1730e63a5" +checksum = "760394e246e4c28189f19d488c058bf16f564016aefac5d32bb1f3b51d5e9261" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.66", - "synstructure 0.13.1", + "aes", + "byteorder", + "bzip2", + "constant_time_eq 0.1.5", + "crc32fast", + "crossbeam-utils", + "flate2", + "hmac", + "pbkdf2", + "sha1", + "time", + "zstd", ] [[package]] -name = "zeroize" -version = "1.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" - -[[package]] -name = "zerovec" -version = "0.10.2" +name = "zip-extensions" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb2cc8827d6c0994478a15c53f374f46fbd41bea663d809b14744bc42e6b109c" +checksum = "cecf62554c4ff96bce01a7ef123d160c3ffe9180638820f8b4d545c65b221b8c" dependencies = [ - "yoke", - "zerofrom", - "zerovec-derive", + "zip", ] [[package]] -name = "zerovec-derive" -version = "0.10.2" +name = "zstd" +version = "0.11.2+zstd.1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97cf56601ee5052b4417d90c8755c6683473c926039908196cf35d99f893ebe7" +checksum = "20cc960326ece64f010d2d2107537f26dc589a6573a316bd5b1dba685fa5fde4" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.66", + "zstd-safe", ] [[package]] -name = "zip" -version = "0.6.6" +name = "zstd-safe" +version = "5.0.2+zstd.1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "760394e246e4c28189f19d488c058bf16f564016aefac5d32bb1f3b51d5e9261" +checksum = "1d2a5585e04f9eea4b2a3d1eca508c4dee9592a89ef6f450c11719da0726f4db" dependencies = [ - "byteorder", - "crc32fast", - "crossbeam-utils", - "flate2", + "libc", + "zstd-sys", ] [[package]] From 43c259c60e0f4aec8dde3d5af4b353ee3a60fa01 Mon Sep 17 00:00:00 2001 From: Lukasz Klimek <842586+lklimek@users.noreply.github.com> Date: Tue, 25 Jun 2024 16:57:57 +0200 Subject: [PATCH 24/55] test(sdk): fix vote_polls_by_ts_limit --- .../rs-sdk/tests/fetch/contested_resource.rs | 10 +-- .../fetch/contested_resource_polls_by_ts.rs | 67 ++++++++++++------- 2 files changed, 49 insertions(+), 28 deletions(-) diff --git a/packages/rs-sdk/tests/fetch/contested_resource.rs b/packages/rs-sdk/tests/fetch/contested_resource.rs index e6295fa640d..e51aab350b9 100644 --- a/packages/rs-sdk/tests/fetch/contested_resource.rs +++ b/packages/rs-sdk/tests/fetch/contested_resource.rs @@ -307,12 +307,12 @@ async fn contested_resources_fields() { expect:Ok(r#"ContestedResources([Value(Text("dash"))])"#), }, TestCase { - name: "end_index_values two values (1 nx) with empty start_index_values returns 'dash'", + name: "end_index_values two values (1 nx) with empty start_index_values returns error", query_mut_fn: |q| { q.start_index_values = vec![]; q.end_index_values = vec![Value::Text("dada".to_string()), Value::Text("non existing".to_string())]; }, - expect:Ok(r#"ContestedResources([Value(Text("dash"))])"#), + expect:Err("too many end index values were provided"), }, TestCase { name: "end_index_values with 1 nx value 'aaa*' and empty start_index_values returns zero objects", @@ -442,7 +442,7 @@ async fn contested_resources_fields() { if !result_string.contains(expected) { failures.push(( test_case.name, - format!("expected: {:#?}\ngot: {:?}\n", expected, result), + format!("EXPECTED: {} GOT: {:?}\n", expected, result), )); } } @@ -451,14 +451,14 @@ async fn contested_resources_fields() { if !result.to_string().contains(expected) { failures.push(( test_case.name, - format!("expected: {:#?}\ngot {:?}\n", expected, result), + format!("EXPECTED: {} GOT: {:?}\n", expected, result), )); } } expected => { failures.push(( test_case.name, - format!("expected: {:#?}\ngot: {:?}\n", expected, result), + format!("EXPECTED: {:?} GOT: {:?}\n", expected, result), )); } } diff --git a/packages/rs-sdk/tests/fetch/contested_resource_polls_by_ts.rs b/packages/rs-sdk/tests/fetch/contested_resource_polls_by_ts.rs index 61cc66f258b..cb3273c5ba3 100644 --- a/packages/rs-sdk/tests/fetch/contested_resource_polls_by_ts.rs +++ b/packages/rs-sdk/tests/fetch/contested_resource_polls_by_ts.rs @@ -1,6 +1,7 @@ //! Test VotePollsByEndDateDriveQuery use crate::fetch::{common::setup_logs, config::Config}; +use chrono::Days; use dash_sdk::platform::FetchMany; use dpp::{identity::TimestampMillis, voting::vote_polls::VotePoll}; use drive::query::VotePollsByEndDateDriveQuery; @@ -129,18 +130,21 @@ async fn vote_polls_by_ts_limit() { .await .expect("prerequisities"); - // Given index with more than 2 contested resources + // Given index with more than 2 contested resources; note LIMIT must be > 1 const LIMIT: usize = 2; const LIMIT_ALL: usize = 100; - let test_start_time: TimestampMillis = chrono::Utc::now().timestamp_millis() as u64; + let _test_start_time: TimestampMillis = chrono::Utc::now().timestamp_millis() as u64; + let end_time = chrono::Utc::now() + .checked_add_days(Days::new(30)) + .expect("30 days in future"); let query_all = VotePollsByEndDateDriveQuery { limit: Some(LIMIT_ALL as u16), offset: None, order_ascending: true, start_time: None, - end_time: Some((test_start_time, true)), // 1 month in future + end_time: Some((end_time.timestamp_millis() as u64, true)), // 1 month in future }; let all = VotePoll::fetch_many(&sdk, query_all.clone()) @@ -152,13 +156,18 @@ async fn vote_polls_by_ts_limit() { let all_values = all.0.into_iter().collect::>(); - tracing::debug!(count_all_timestamps, "Count all"); - // When we query for 2 contested values at a time, we get all of them - let mut checked_count: usize = 0; - let mut start_time = None; + tracing::debug!( + count = count_all_timestamps, + all = ?all_values, + "All results" + ); for inclusive in [true, false] { - while checked_count < LIMIT_ALL { + // When we query for 2 contested values at a time, we get all of them + let mut checked_count: usize = 0; + let mut start_time = None; + + loop { let query = VotePollsByEndDateDriveQuery { limit: Some(LIMIT as u16), start_time, @@ -178,31 +187,43 @@ async fn vote_polls_by_ts_limit() { let length = rss.0.len(); for (j, current) in rss.0.iter().enumerate() { - let all_idx = if inclusive && (j + checked_count > 0) { + let all_idx = if inclusive && (checked_count > 0) { j + checked_count - 1 } else { j + checked_count }; let expected = &all_values[all_idx]; - assert_eq!(*current.0, expected.0, "timestamp should match"); - assert_eq!(current.1, &expected.1, "vote polls should match"); + assert_eq!( + *current.0, expected.0, + "inclusive {}: timestamp should match", + inclusive + ); + assert_eq!( + current.1, &expected.1, + "inclusive {}: vote polls should match", + inclusive + ); } - let expected = if checked_count + LIMIT > count_all_timestamps { - count_all_timestamps - checked_count + tracing::debug!(polls=?rss, checked_count, ?start_time, "Vote polls"); + + start_time = Some((last, inclusive)); + // when inclusive, we include the first item in checked_count only on first iteration + checked_count += if inclusive && checked_count != 0 { + length - 1 } else { - LIMIT + length }; - assert_eq!(length, expected as usize); - tracing::debug!(polls=?rss, checked_count, "Vote polls"); - start_time = Some((last, inclusive)); - checked_count += if inclusive { length - 1 } else { length }; + if (inclusive && length == 1) || (!inclusive && length == 0) { + break; + } } + + assert_eq!( + checked_count, count_all_timestamps, + "all vote polls should be checked when inclusive is {}", + inclusive + ); } - assert_eq!( - checked_count, - count_all_timestamps * 2, - "all vote polls should be checked twice (inclusive and exclusive)" - ); } From f5e706f4dbc0e5482681bfc2ddea743851033b37 Mon Sep 17 00:00:00 2001 From: Quantum Explorer Date: Wed, 26 Jun 2024 01:24:16 +0300 Subject: [PATCH 25/55] voting strategy tests --- Cargo.lock | 2 + .../rs-drive-abci/src/query/proofs/v0/mod.rs | 2 +- .../tests/strategy_tests/chain_lock_update.rs | 2 +- .../tests/strategy_tests/core_update_tests.rs | 6 +- .../tests/strategy_tests/execution.rs | 11 +- .../tests/strategy_tests/failures.rs | 13 +- .../tests/strategy_tests/main.rs | 134 ++++-- .../tests/strategy_tests/masternodes.rs | 69 ++- .../tests/strategy_tests/query.rs | 6 +- .../tests/strategy_tests/strategy.rs | 61 +++ .../strategy_tests/upgrade_fork_tests.rs | 22 +- .../tests/strategy_tests/voting_tests.rs | 400 +++++++++++++++++- .../drive/object_size_info/contract_info.rs | 13 + packages/strategy-tests/Cargo.toml | 2 + packages/strategy-tests/src/operations.rs | 138 +++++- 15 files changed, 803 insertions(+), 78 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9f6c164398b..3b570a56d88 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4953,6 +4953,8 @@ dependencies = [ "drive", "futures", "hex", + "platform-serialization", + "platform-serialization-derive", "platform-version", "rand", "rocksdb", diff --git a/packages/rs-drive-abci/src/query/proofs/v0/mod.rs b/packages/rs-drive-abci/src/query/proofs/v0/mod.rs index 4bd5bdf9c49..161461e96aa 100644 --- a/packages/rs-drive-abci/src/query/proofs/v0/mod.rs +++ b/packages/rs-drive-abci/src/query/proofs/v0/mod.rs @@ -96,7 +96,7 @@ impl Platform { contested_status, }) }) - .collect::, QueryError>>()); + .collect::, QueryError>>()); let vote_queries = check_validation_result_with_data!(votes .into_iter() diff --git a/packages/rs-drive-abci/tests/strategy_tests/chain_lock_update.rs b/packages/rs-drive-abci/tests/strategy_tests/chain_lock_update.rs index f80ec3645de..a210cb8beff 100644 --- a/packages/rs-drive-abci/tests/strategy_tests/chain_lock_update.rs +++ b/packages/rs-drive-abci/tests/strategy_tests/chain_lock_update.rs @@ -77,6 +77,6 @@ mod tests { .with_config(config.clone()) .build_with_mock_rpc(); - run_chain_for_strategy(&mut platform, 50, strategy, config, 13); + run_chain_for_strategy(&mut platform, 50, strategy, config, 13, &mut None); } } diff --git a/packages/rs-drive-abci/tests/strategy_tests/core_update_tests.rs b/packages/rs-drive-abci/tests/strategy_tests/core_update_tests.rs index 9b5e08ad33d..44ac67b3d75 100644 --- a/packages/rs-drive-abci/tests/strategy_tests/core_update_tests.rs +++ b/packages/rs-drive-abci/tests/strategy_tests/core_update_tests.rs @@ -77,7 +77,7 @@ mod tests { .with_config(config.clone()) .build_with_mock_rpc(); - let outcome = run_chain_for_strategy(&mut platform, 50, strategy, config, 13); + let outcome = run_chain_for_strategy(&mut platform, 50, strategy, config, 13, &mut None); // we expect to see quorums with banned members @@ -175,7 +175,7 @@ mod tests { .with_config(config.clone()) .build_with_mock_rpc(); - let outcome = run_chain_for_strategy(&mut platform, 50, strategy, config, 13); + let outcome = run_chain_for_strategy(&mut platform, 50, strategy, config, 13, &mut None); // we expect to see quorums with banned members @@ -264,7 +264,7 @@ mod tests { .with_config(config.clone()) .build_with_mock_rpc(); - let outcome = run_chain_for_strategy(&mut platform, 26, strategy, config, 13); + let outcome = run_chain_for_strategy(&mut platform, 26, strategy, config, 13, &mut None); // We should also see validator sets with less than the quorum size diff --git a/packages/rs-drive-abci/tests/strategy_tests/execution.rs b/packages/rs-drive-abci/tests/strategy_tests/execution.rs index 3db5a245faa..618e2546921 100644 --- a/packages/rs-drive-abci/tests/strategy_tests/execution.rs +++ b/packages/rs-drive-abci/tests/strategy_tests/execution.rs @@ -37,6 +37,7 @@ use drive_abci::test::fixture::abci::static_init_chain_request; use platform_version::version::PlatformVersion; use rand::prelude::{SliceRandom, StdRng}; use rand::{Rng, SeedableRng}; +use simple_signer::signer::SimpleSigner; use std::collections::{BTreeMap, HashMap}; use tenderdash_abci::proto::abci::{ResponseInitChain, ValidatorSetUpdate}; use tenderdash_abci::proto::crypto::public_key::Sum::Bls12381; @@ -46,13 +47,14 @@ use tenderdash_abci::Application; pub const GENESIS_TIME_MS: u64 = 1681094380000; -pub(crate) fn run_chain_for_strategy( - platform: &mut Platform, +pub(crate) fn run_chain_for_strategy<'a>( + platform: &'a mut Platform, block_count: u64, strategy: NetworkStrategy, config: PlatformConfig, seed: u64, -) -> ChainExecutionOutcome { + add_voting_keys_to_signer: &mut Option, +) -> ChainExecutionOutcome<'a> { let validator_quorum_count = strategy.validator_quorum_count; // In most tests 24 quorums let chain_lock_quorum_count = strategy.chain_lock_quorum_count; // In most tests 4 quorums when not the same as validator let validator_set_quorum_size = config.validator_set_quorum_size; @@ -115,6 +117,7 @@ pub(crate) fn run_chain_for_strategy( strategy.total_hpmns, generate_updates, &mut rng, + add_voting_keys_to_signer, ); let mut all_masternodes = initial_masternodes.clone(); @@ -165,6 +168,7 @@ pub(crate) fn run_chain_for_strategy( new_hpmns, generate_updates, &mut rng, + add_voting_keys_to_signer, ); if strategy.proposer_strategy.removed_masternodes.is_set() { @@ -207,6 +211,7 @@ pub(crate) fn run_chain_for_strategy( strategy.total_hpmns, None, &mut rng, + add_voting_keys_to_signer, ); ( initial_masternodes, diff --git a/packages/rs-drive-abci/tests/strategy_tests/failures.rs b/packages/rs-drive-abci/tests/strategy_tests/failures.rs index c1fe8150951..a02599128de 100644 --- a/packages/rs-drive-abci/tests/strategy_tests/failures.rs +++ b/packages/rs-drive-abci/tests/strategy_tests/failures.rs @@ -91,7 +91,7 @@ mod tests { .with_config(config.clone()) .build_with_mock_rpc(); - let outcome = run_chain_for_strategy(&mut platform, 10, strategy, config, 15); + let outcome = run_chain_for_strategy(&mut platform, 10, strategy, config, 15, &mut None); outcome .abci_app @@ -183,13 +183,20 @@ mod tests { signature: [2; 96].into(), }) }); - run_chain_for_strategy(&mut platform, 1, strategy.clone(), config.clone(), 15); + run_chain_for_strategy( + &mut platform, + 1, + strategy.clone(), + config.clone(), + 15, + &mut None, + ); //platform block didn't complete, so it should get another init chain strategy.failure_testing = None; - run_chain_for_strategy(&mut platform, 15, strategy, config, 15); + run_chain_for_strategy(&mut platform, 15, strategy, config, 15, &mut None); } // #[test] diff --git a/packages/rs-drive-abci/tests/strategy_tests/main.rs b/packages/rs-drive-abci/tests/strategy_tests/main.rs index b7976a10ca6..5c0f979f94d 100644 --- a/packages/rs-drive-abci/tests/strategy_tests/main.rs +++ b/packages/rs-drive-abci/tests/strategy_tests/main.rs @@ -130,7 +130,7 @@ mod tests { .with_config(config.clone()) .build_with_mock_rpc(); - run_chain_for_strategy(&mut platform, 100, strategy, config, 15); + run_chain_for_strategy(&mut platform, 100, strategy, config, 15, &mut None); } #[test] @@ -175,7 +175,7 @@ mod tests { .with_config(config.clone()) .build_with_mock_rpc(); - run_chain_for_strategy(&mut platform, 50, strategy, config, 13); + run_chain_for_strategy(&mut platform, 50, strategy, config, 13, &mut None); } #[test] @@ -233,7 +233,14 @@ mod tests { identity_nonce_counter, identity_contract_nonce_counter, .. - } = run_chain_for_strategy(&mut platform, 15, strategy.clone(), config.clone(), 40); + } = run_chain_for_strategy( + &mut platform, + 15, + strategy.clone(), + config.clone(), + 40, + &mut None, + ); let known_root_hash = abci_app .platform @@ -365,7 +372,14 @@ mod tests { identity_nonce_counter, identity_contract_nonce_counter, .. - } = run_chain_for_strategy(&mut platform, 15, strategy.clone(), config.clone(), 40); + } = run_chain_for_strategy( + &mut platform, + 15, + strategy.clone(), + config.clone(), + 40, + &mut None, + ); let known_root_hash = abci_app .platform @@ -485,7 +499,7 @@ mod tests { .with_config(config.clone()) .build_with_mock_rpc(); - let outcome = run_chain_for_strategy(&mut platform, 100, strategy, config, 15); + let outcome = run_chain_for_strategy(&mut platform, 100, strategy, config, 15, &mut None); let balance = outcome .abci_app @@ -547,7 +561,7 @@ mod tests { .with_config(config.clone()) .build_with_mock_rpc(); - run_chain_for_strategy(&mut platform, 1000, strategy, config, 15); + run_chain_for_strategy(&mut platform, 1000, strategy, config, 15, &mut None); } #[test] @@ -597,7 +611,7 @@ mod tests { .with_config(config.clone()) .build_with_mock_rpc(); - let outcome = run_chain_for_strategy(&mut platform, 1000, strategy, config, 15); + let outcome = run_chain_for_strategy(&mut platform, 1000, strategy, config, 15, &mut None); assert_eq!(outcome.masternode_identity_balances.len(), 100); let all_have_balances = outcome .masternode_identity_balances @@ -655,7 +669,7 @@ mod tests { .with_config(config.clone()) .build_with_mock_rpc(); - let outcome = run_chain_for_strategy(&mut platform, 1000, strategy, config, 15); + let outcome = run_chain_for_strategy(&mut platform, 1000, strategy, config, 15, &mut None); assert_eq!(outcome.masternode_identity_balances.len(), 100); let all_have_balances = outcome .masternode_identity_balances @@ -712,7 +726,7 @@ mod tests { .build_with_mock_rpc(); let ChainExecutionOutcome { abci_app, .. } = - run_chain_for_strategy(&mut platform, 2000, strategy, config, 40); + run_chain_for_strategy(&mut platform, 2000, strategy, config, 40, &mut None); // With these params if we didn't rotate we would have at most 240 // of the 500 hpmns that could get paid, however we are expecting that most @@ -792,7 +806,7 @@ mod tests { .build_with_mock_rpc(); let ChainExecutionOutcome { abci_app, .. } = - run_chain_for_strategy(&mut platform, 300, strategy, config, 43); + run_chain_for_strategy(&mut platform, 300, strategy, config, 43, &mut None); // With these params if we add new mns the hpmn masternode list would be 100, but we // can expect it to be much higher. @@ -859,7 +873,7 @@ mod tests { .build_with_mock_rpc(); let ChainExecutionOutcome { abci_app, .. } = - run_chain_for_strategy(&mut platform, 300, strategy, config, 43); + run_chain_for_strategy(&mut platform, 300, strategy, config, 43, &mut None); // With these params if we add new mns the hpmn masternode list would be randomly different than 100. @@ -924,7 +938,7 @@ mod tests { abci_app, proposers, .. - } = run_chain_for_strategy(&mut platform, 300, strategy, config, 43); + } = run_chain_for_strategy(&mut platform, 300, strategy, config, 43, &mut None); // With these params if we add new mns the hpmn masternode list would be randomly different than 100. @@ -1015,7 +1029,7 @@ mod tests { .with_config(config.clone()) .build_with_mock_rpc(); - let outcome = run_chain_for_strategy(&mut platform, 100, strategy, config, 15); + let outcome = run_chain_for_strategy(&mut platform, 100, strategy, config, 15, &mut None); assert_eq!(outcome.identities.len(), 100); } @@ -1070,7 +1084,7 @@ mod tests { .with_config(config.clone()) .build_with_mock_rpc(); - let outcome = run_chain_for_strategy(&mut platform, 150, strategy, config, 15); + let outcome = run_chain_for_strategy(&mut platform, 150, strategy, config, 15, &mut None); assert_eq!(outcome.identities.len(), 150); assert_eq!(outcome.masternode_identity_balances.len(), 100); let all_have_balances = outcome @@ -1150,7 +1164,7 @@ mod tests { .with_config(config.clone()) .build_with_mock_rpc(); - let outcome = run_chain_for_strategy(&mut platform, 1, strategy, config, 15); + let outcome = run_chain_for_strategy(&mut platform, 1, strategy, config, 15, &mut None); outcome .abci_app @@ -1269,7 +1283,7 @@ mod tests { .with_config(config.clone()) .build_with_mock_rpc(); - run_chain_for_strategy(&mut platform, 30, strategy, config, 15); + run_chain_for_strategy(&mut platform, 30, strategy, config, 15, &mut None); } #[test] @@ -1356,7 +1370,7 @@ mod tests { .with_config(config.clone()) .build_with_mock_rpc(); - let outcome = run_chain_for_strategy(&mut platform, 10, strategy, config, 15); + let outcome = run_chain_for_strategy(&mut platform, 10, strategy, config, 15, &mut None); outcome .abci_app @@ -1460,7 +1474,7 @@ mod tests { .with_config(config.clone()) .build_with_mock_rpc(); - run_chain_for_strategy(&mut platform, 100, strategy, config, 15); + run_chain_for_strategy(&mut platform, 100, strategy, config, 15, &mut None); } #[test] @@ -1542,7 +1556,8 @@ mod tests { .with_config(config.clone()) .build_with_mock_rpc(); - let outcome = run_chain_for_strategy(&mut platform, block_count, strategy, config, 15); + let outcome = + run_chain_for_strategy(&mut platform, block_count, strategy, config, 15, &mut None); assert_eq!(outcome.identities.len() as u64, block_count); assert_eq!(outcome.masternode_identity_balances.len(), 100); let all_have_balances = outcome @@ -1650,7 +1665,8 @@ mod tests { .with_config(config.clone()) .build_with_mock_rpc(); - let outcome = run_chain_for_strategy(&mut platform, block_count, strategy, config, 15); + let outcome = + run_chain_for_strategy(&mut platform, block_count, strategy, config, 15, &mut None); assert_eq!(outcome.identities.len() as u64, block_count); assert_eq!(outcome.masternode_identity_balances.len(), 100); let all_have_balances = outcome @@ -1759,7 +1775,8 @@ mod tests { .with_config(config.clone()) .build_with_mock_rpc(); - let outcome = run_chain_for_strategy(&mut platform, block_count, strategy, config, 15); + let outcome = + run_chain_for_strategy(&mut platform, block_count, strategy, config, 15, &mut None); assert_eq!(outcome.identities.len() as u64, block_count); assert_eq!(outcome.masternode_identity_balances.len(), 100); let all_have_balances = outcome @@ -1885,7 +1902,8 @@ mod tests { .with_config(config.clone()) .build_with_mock_rpc(); - let outcome = run_chain_for_strategy(&mut platform, block_count, strategy, config, 15); + let outcome = + run_chain_for_strategy(&mut platform, block_count, strategy, config, 15, &mut None); assert_eq!(outcome.identities.len() as u64, block_count); assert_eq!(outcome.masternode_identity_balances.len(), 100); let all_have_balances = outcome @@ -2010,7 +2028,8 @@ mod tests { .with_config(config.clone()) .build_with_mock_rpc(); - let outcome = run_chain_for_strategy(&mut platform, block_count, strategy, config, 15); + let outcome = + run_chain_for_strategy(&mut platform, block_count, strategy, config, 15, &mut None); for tx_results_per_block in outcome.state_transition_results_per_block.values() { for (state_transition, result) in tx_results_per_block { assert_eq!( @@ -2124,7 +2143,8 @@ mod tests { .with_config(config.clone()) .build_with_mock_rpc(); - let outcome = run_chain_for_strategy(&mut platform, block_count, strategy, config, 15); + let outcome = + run_chain_for_strategy(&mut platform, block_count, strategy, config, 15, &mut None); for tx_results_per_block in outcome.state_transition_results_per_block.values() { for (state_transition, _unused_result) in tx_results_per_block { // We can't ever get a documents batch transition, because the proposer will remove it from a block @@ -2238,7 +2258,8 @@ mod tests { .with_config(config.clone()) .build_with_mock_rpc(); - let outcome = run_chain_for_strategy(&mut platform, block_count, strategy, config, 15); + let outcome = + run_chain_for_strategy(&mut platform, block_count, strategy, config, 15, &mut None); assert_eq!(outcome.identities.len() as u64, 470); assert_eq!(outcome.masternode_identity_balances.len(), 100); let balance_count = outcome @@ -2367,7 +2388,8 @@ mod tests { .with_config(config.clone()) .build_with_mock_rpc(); - let outcome = run_chain_for_strategy(&mut platform, block_count, strategy, config, 15); + let outcome = + run_chain_for_strategy(&mut platform, block_count, strategy, config, 15, &mut None); assert_eq!(outcome.identities.len() as u64, 90); assert_eq!(outcome.masternode_identity_balances.len(), 100); let balance_count = outcome @@ -2512,7 +2534,8 @@ mod tests { .with_config(config.clone()) .build_with_mock_rpc(); - let outcome = run_chain_for_strategy(&mut platform, block_count, strategy, config, 15); + let outcome = + run_chain_for_strategy(&mut platform, block_count, strategy, config, 15, &mut None); assert_eq!(outcome.identities.len() as u64, 97); assert_eq!(outcome.masternode_identity_balances.len(), 100); let balance_count = outcome @@ -2579,7 +2602,7 @@ mod tests { .with_config(config.clone()) .build_with_mock_rpc(); - let outcome = run_chain_for_strategy(&mut platform, 10, strategy, config, 15); + let outcome = run_chain_for_strategy(&mut platform, 10, strategy, config, 15, &mut None); let max_initial_balance = 100000000000u64; // TODO: some centralized way for random test data (`arbitrary` maybe?) let balances = outcome @@ -2659,7 +2682,7 @@ mod tests { .with_config(config.clone()) .build_with_mock_rpc(); - let outcome = run_chain_for_strategy(&mut platform, 10, strategy, config, 15); + let outcome = run_chain_for_strategy(&mut platform, 10, strategy, config, 15, &mut None); let state = outcome.abci_app.platform.state.load(); let protocol_version = state.current_protocol_version_in_consensus(); let platform_version = PlatformVersion::get(protocol_version).unwrap(); @@ -2744,7 +2767,7 @@ mod tests { .with_config(config.clone()) .build_with_mock_rpc(); - let outcome = run_chain_for_strategy(&mut platform, 10, strategy, config, 15); + let outcome = run_chain_for_strategy(&mut platform, 10, strategy, config, 15, &mut None); let identities = outcome .abci_app @@ -2912,8 +2935,14 @@ mod tests { }, last_block_pooled_withdrawals_amount, ) = { - let outcome = - run_chain_for_strategy(&mut platform, 2, strategy.clone(), config.clone(), 1); + let outcome = run_chain_for_strategy( + &mut platform, + 2, + strategy.clone(), + config.clone(), + 1, + &mut None, + ); // Withdrawal transactions are not populated to block execution context yet assert_eq!(outcome.withdrawals.len(), 0); @@ -3423,7 +3452,8 @@ mod tests { }) }); - let outcome = run_chain_for_strategy(platform, 1, strategy.clone(), config.clone(), 7); + let outcome = + run_chain_for_strategy(platform, 1, strategy.clone(), config.clone(), 7, &mut None); outcomes.push(outcome); } @@ -3593,9 +3623,15 @@ mod tests { }) }); - let outcome_a = - run_chain_for_strategy(&mut platform_a, 18, strategy.clone(), config.clone(), 7); - let outcome_b = run_chain_for_strategy(&mut platform_b, 18, strategy, config, 7); + let outcome_a = run_chain_for_strategy( + &mut platform_a, + 18, + strategy.clone(), + config.clone(), + 7, + &mut None, + ); + let outcome_b = run_chain_for_strategy(&mut platform_b, 18, strategy, config, 7, &mut None); assert_eq!(outcome_a.end_epoch_index, outcome_b.end_epoch_index); // 100/18 assert_eq!(outcome_a.masternode_identity_balances.len(), 500); // 500 nodes assert_eq!(outcome_b.masternode_identity_balances.len(), 500); // 500 nodes @@ -3728,9 +3764,16 @@ mod tests { }) }); - let outcome_a = - run_chain_for_strategy(&mut platform_a, 100, strategy.clone(), config.clone(), 7); - let outcome_b = run_chain_for_strategy(&mut platform_b, 100, strategy, config, 7); + let outcome_a = run_chain_for_strategy( + &mut platform_a, + 100, + strategy.clone(), + config.clone(), + 7, + &mut None, + ); + let outcome_b = + run_chain_for_strategy(&mut platform_b, 100, strategy, config, 7, &mut None); assert_eq!(outcome_a.end_epoch_index, outcome_b.end_epoch_index); // 100/18 assert_eq!(outcome_a.masternode_identity_balances.len(), 500); // 500 nodes assert_eq!(outcome_b.masternode_identity_balances.len(), 500); // 500 nodes @@ -3845,7 +3888,14 @@ mod tests { identity_nonce_counter, identity_contract_nonce_counter, .. - } = run_chain_for_strategy(&mut platform, 100, strategy.clone(), config.clone(), 89); + } = run_chain_for_strategy( + &mut platform, + 100, + strategy.clone(), + config.clone(), + 89, + &mut None, + ); let state = abci_app.platform.state.load(); let protocol_version = state.current_protocol_version_in_consensus(); @@ -3976,7 +4026,7 @@ mod tests { .with_config(config.clone()) .build_with_mock_rpc(); - let outcome = run_chain_for_strategy(&mut platform, 15, strategy, config, 15); + let outcome = run_chain_for_strategy(&mut platform, 15, strategy, config, 15, &mut None); let _balances = &outcome .abci_app @@ -4031,7 +4081,7 @@ mod tests { .with_config(config.clone()) .build_with_mock_rpc(); - let outcome = run_chain_for_strategy(&mut platform, 1, strategy, config, 15); + let outcome = run_chain_for_strategy(&mut platform, 1, strategy, config, 15, &mut None); let state_transitions = outcome .state_transition_results_per_block .get(&1) diff --git a/packages/rs-drive-abci/tests/strategy_tests/masternodes.rs b/packages/rs-drive-abci/tests/strategy_tests/masternodes.rs index d240752a265..f10c37b5d07 100644 --- a/packages/rs-drive-abci/tests/strategy_tests/masternodes.rs +++ b/packages/rs-drive-abci/tests/strategy_tests/masternodes.rs @@ -3,9 +3,14 @@ use dashcore_rpc::dashcore::hashes::Hash; use dashcore_rpc::dashcore::{ProTxHash, QuorumHash, Txid}; use dashcore_rpc::dashcore_rpc_json::{DMNState, MasternodeListItem, MasternodeType}; use dpp::bls_signatures::PrivateKey as BlsPrivateKey; +use dpp::identity::hash::IdentityPublicKeyHashMethodsV0; +use dpp::identity::IdentityPublicKey; +use dpp::identity::KeyType::{ECDSA_HASH160, ECDSA_SECP256K1}; use drive_abci::mimic::test_quorum::TestQuorumInfo; +use platform_version::version::PlatformVersion; use rand::prelude::{IteratorRandom, StdRng}; use rand::Rng; +use simple_signer::signer::SimpleSigner; use std::collections::{BTreeMap, BTreeSet}; use std::net::{IpAddr, Ipv4Addr, SocketAddr}; use std::str::FromStr; @@ -33,6 +38,7 @@ pub fn generate_test_masternodes( hpmn_count: u16, updates: Option, rng: &mut StdRng, + add_voting_keys_to_signer: &mut Option, ) -> ( Vec, Vec, @@ -188,6 +194,21 @@ pub fn generate_test_masternodes( let hpmn_number_to_heights_http_port_changes = invert_btreemap(block_height_to_list_hpmn_http_port_changes); + fn generate_voting_address( + rng: &mut StdRng, + add_voting_keys_to_signer: &mut Option, + ) -> [u8; 20] { + if let Some(simple_signer) = add_voting_keys_to_signer { + let (identity_public_key, private_key) = + IdentityPublicKey::random_voting_key_with_rng(0, rng, PlatformVersion::latest()) + .expect("expected a random voting key"); + simple_signer.add_key(identity_public_key.clone(), private_key); + identity_public_key.public_key_hash().unwrap() + } else { + rng.gen() + } + } + for i in 0..masternode_count { let private_key_operator = BlsPrivateKey::generate_dash(rng).expect("expected to generate a private key"); @@ -212,7 +233,7 @@ pub fn generate_test_masternodes( pose_ban_height: None, revocation_reason: 0, owner_address: rng.gen::<[u8; 20]>(), - voting_address: rng.gen::<[u8; 20]>(), + voting_address: generate_voting_address(rng, add_voting_keys_to_signer), payout_address: rng.gen::<[u8; 20]>(), pub_key_operator, operator_payout_address: None, @@ -347,7 +368,7 @@ pub fn generate_test_masternodes( pose_ban_height: None, revocation_reason: 0, owner_address: rng.gen::<[u8; 20]>(), - voting_address: rng.gen::<[u8; 20]>(), + voting_address: generate_voting_address(rng, add_voting_keys_to_signer), payout_address: rng.gen::<[u8; 20]>(), pub_key_operator, operator_payout_address: None, @@ -581,9 +602,9 @@ mod tests { let mut rng2 = StdRng::seed_from_u64(12345); let (masternodes1, hpmn1) = - generate_test_masternodes(masternode_count, hpmn_count, None, &mut rng1); + generate_test_masternodes(masternode_count, hpmn_count, None, &mut rng1, &mut None); let (masternodes2, hpmn2) = - generate_test_masternodes(masternode_count, hpmn_count, None, &mut rng2); + generate_test_masternodes(masternode_count, hpmn_count, None, &mut rng2, &mut None); assert_eq!(masternodes1, masternodes2); assert_eq!(hpmn1, hpmn2); @@ -640,10 +661,20 @@ mod tests { let mut rng1 = StdRng::seed_from_u64(12345); let mut rng2 = StdRng::seed_from_u64(12345); - let (masternodes1, hpmn1) = - generate_test_masternodes(masternode_count, hpmn_count, updates.clone(), &mut rng1); - let (masternodes2, hpmn2) = - generate_test_masternodes(masternode_count, hpmn_count, updates.clone(), &mut rng2); + let (masternodes1, hpmn1) = generate_test_masternodes( + masternode_count, + hpmn_count, + updates.clone(), + &mut rng1, + &mut None, + ); + let (masternodes2, hpmn2) = generate_test_masternodes( + masternode_count, + hpmn_count, + updates.clone(), + &mut rng2, + &mut None, + ); assert_eq!(masternodes1, masternodes2); assert_eq!(hpmn1, hpmn2); @@ -666,9 +697,9 @@ mod tests { let hpmn_count = rng.gen_range(50..=150); let (masternodes1, hpmn1) = - generate_test_masternodes(masternode_count, hpmn_count, None, &mut rng1); + generate_test_masternodes(masternode_count, hpmn_count, None, &mut rng1, &mut None); let (masternodes2, hpmn2) = - generate_test_masternodes(masternode_count, hpmn_count, None, &mut rng2); + generate_test_masternodes(masternode_count, hpmn_count, None, &mut rng2, &mut None); assert_eq!(masternodes1, masternodes2); assert_eq!(hpmn1, hpmn2); @@ -736,10 +767,20 @@ mod tests { }, }); - let (masternodes1, hpmn1) = - generate_test_masternodes(masternode_count, hpmn_count, updates.clone(), &mut rng1); - let (masternodes2, hpmn2) = - generate_test_masternodes(masternode_count, hpmn_count, updates.clone(), &mut rng2); + let (masternodes1, hpmn1) = generate_test_masternodes( + masternode_count, + hpmn_count, + updates.clone(), + &mut rng1, + &mut None, + ); + let (masternodes2, hpmn2) = generate_test_masternodes( + masternode_count, + hpmn_count, + updates.clone(), + &mut rng2, + &mut None, + ); assert_eq!(masternodes1, masternodes2); assert_eq!(hpmn1, hpmn2); diff --git a/packages/rs-drive-abci/tests/strategy_tests/query.rs b/packages/rs-drive-abci/tests/strategy_tests/query.rs index 899d3f2b85e..7b885ead61c 100644 --- a/packages/rs-drive-abci/tests/strategy_tests/query.rs +++ b/packages/rs-drive-abci/tests/strategy_tests/query.rs @@ -386,7 +386,7 @@ mod tests { .with_config(config.clone()) .build_with_mock_rpc(); - let outcome = run_chain_for_strategy(&mut platform, 1000, strategy, config, 15); + let outcome = run_chain_for_strategy(&mut platform, 1000, strategy, config, 15, &mut None); assert_eq!(outcome.masternode_identity_balances.len(), 100); let all_have_balances = outcome .masternode_identity_balances @@ -484,7 +484,7 @@ mod tests { .with_config(config.clone()) .build_with_mock_rpc(); - let outcome = run_chain_for_strategy(&mut platform, 1000, strategy, config, 15); + let outcome = run_chain_for_strategy(&mut platform, 1000, strategy, config, 15, &mut None); assert_eq!(outcome.masternode_identity_balances.len(), 100); let all_have_balances = outcome .masternode_identity_balances @@ -583,7 +583,7 @@ mod tests { .with_config(config.clone()) .build_with_mock_rpc(); - let outcome = run_chain_for_strategy(&mut platform, 1000, strategy, config, 15); + let outcome = run_chain_for_strategy(&mut platform, 1000, strategy, config, 15, &mut None); assert_eq!(outcome.masternode_identity_balances.len(), 100); let all_have_balances = outcome .masternode_identity_balances diff --git a/packages/rs-drive-abci/tests/strategy_tests/strategy.rs b/packages/rs-drive-abci/tests/strategy_tests/strategy.rs index 2c7fb68f255..ed6ff161a11 100644 --- a/packages/rs-drive-abci/tests/strategy_tests/strategy.rs +++ b/packages/rs-drive-abci/tests/strategy_tests/strategy.rs @@ -45,9 +45,12 @@ use std::borrow::Cow; use std::collections::{BTreeMap, HashMap, HashSet}; use std::str::FromStr; use tenderdash_abci::proto::abci::{ExecTxResult, ValidatorSetUpdate}; +use dpp::dashcore::hashes::Hash; use dpp::data_contract::document_type::accessors::DocumentTypeV0Getters; use dpp::data_contract::document_type::v0::DocumentTypeV0; +use dpp::identifier::MasternodeIdentifiers; use dpp::identity::accessors::IdentityGettersV0; +use dpp::identity::identity_public_key::v0::IdentityPublicKeyV0; use dpp::platform_value::{BinaryData, Value}; use dpp::prelude::{Identifier, IdentityNonce}; use dpp::state_transition::documents_batch_transition::document_base_transition::v0::DocumentBaseTransitionV0; @@ -59,7 +62,14 @@ use dpp::state_transition::documents_batch_transition::document_transition::{Doc use drive::drive::document::query::QueryDocumentsOutcomeV0Methods; use dpp::state_transition::data_contract_create_transition::methods::v0::DataContractCreateTransitionMethodsV0; use dpp::state_transition::documents_batch_transition::document_transition::document_transfer_transition::DocumentTransferTransitionV0; +use dpp::state_transition::masternode_vote_transition::MasternodeVoteTransition; +use dpp::state_transition::masternode_vote_transition::methods::MasternodeVoteTransitionMethodsV0; +use dpp::voting::vote_polls::VotePoll; +use dpp::voting::votes::resource_vote::ResourceVote; +use dpp::voting::votes::resource_vote::v0::ResourceVoteV0; +use dpp::voting::votes::Vote; use drive_abci::abci::app::FullAbciApplication; +use drive_abci::platform_types::platform_state::v0::PlatformStateV0Methods; use drive_abci::platform_types::withdrawal::unsigned_withdrawal_txs::v0::UnsignedWithdrawalTxs; use crate::strategy::CoreHeightIncrease::NoCoreHeightIncrease; @@ -530,6 +540,7 @@ impl NetworkStrategy { rng: &mut StdRng, platform_version: &PlatformVersion, ) -> (Vec, Vec) { + let mut maybe_state = None; let mut operations = vec![]; let mut finalize_block_operations = vec![]; let mut replaced = vec![]; @@ -1261,6 +1272,56 @@ impl NetworkStrategy { operations.push(state_transition); } } + OperationType::ResourceVote(resource_vote_op) => { + let state = maybe_state.get_or_insert(platform.state.load()); + let full_masternode_list = state.full_masternode_list(); + + let rand_index = rng.gen_range(0..full_masternode_list.len()); + let (pro_tx_hash, masternode_list_item) = + full_masternode_list.iter().nth(rand_index).unwrap(); + + let pro_tx_hash_bytes: [u8; 32] = pro_tx_hash.to_raw_hash().into(); + let voting_address = masternode_list_item.state.voting_address; + let identity_public_key = IdentityPublicKey::V0(IdentityPublicKeyV0 { + id: 0, + purpose: Purpose::VOTING, + security_level: SecurityLevel::MEDIUM, + contract_bounds: None, + key_type: KeyType::ECDSA_HASH160, + read_only: false, + data: voting_address.to_vec().into(), + disabled_at: None, + }); + + let vote = Vote::ResourceVote(ResourceVote::V0(ResourceVoteV0 { + vote_poll: VotePoll::ContestedDocumentResourceVotePoll( + resource_vote_op.resolved_vote_poll.clone().into(), + ), + resource_vote_choice: Default::default(), + })); + + let voting_identifier = Identifier::create_voter_identifier( + pro_tx_hash.as_byte_array(), + &voting_address, + ); + + let identity_nonce = + identity_nonce_counter.entry(voting_identifier).or_default(); + *identity_nonce += 1; + + let state_transition = MasternodeVoteTransition::try_from_vote_with_signer( + vote, + signer, + Identifier::from(pro_tx_hash_bytes), + &identity_public_key, + *identity_nonce, + platform_version, + None, + ) + .expect("expected to make a masternode vote transition"); + + operations.push(state_transition); + } _ => {} } } diff --git a/packages/rs-drive-abci/tests/strategy_tests/upgrade_fork_tests.rs b/packages/rs-drive-abci/tests/strategy_tests/upgrade_fork_tests.rs index 2d4dac2e7e4..d19fb373d14 100644 --- a/packages/rs-drive-abci/tests/strategy_tests/upgrade_fork_tests.rs +++ b/packages/rs-drive-abci/tests/strategy_tests/upgrade_fork_tests.rs @@ -111,6 +111,7 @@ mod tests { strategy.clone(), config.clone(), 13, + &mut None, ); let platform = abci_app.platform; @@ -350,6 +351,7 @@ mod tests { strategy.clone(), config.clone(), 13, + &mut None, ); let platform = abci_app.platform; @@ -566,7 +568,14 @@ mod tests { current_quorum_hash, end_time_ms, .. - } = run_chain_for_strategy(&mut platform, 1, strategy.clone(), config.clone(), 13); + } = run_chain_for_strategy( + &mut platform, + 1, + strategy.clone(), + config.clone(), + 13, + &mut None, + ); let platform = abci_app.platform; @@ -749,6 +758,7 @@ mod tests { strategy.clone(), config.clone(), 16, + &mut None, ); let platform = abci_app.platform; let state = platform.state.load(); @@ -981,6 +991,7 @@ mod tests { strategy.clone(), config.clone(), 15, + &mut None, ); let platform = abci_app.platform; @@ -1303,7 +1314,14 @@ mod tests { identity_nonce_counter, identity_contract_nonce_counter, .. - } = run_chain_for_strategy(&mut platform, 1400, strategy, config.clone(), 15); + } = run_chain_for_strategy( + &mut platform, + 1400, + strategy, + config.clone(), + 15, + &mut None, + ); let state = abci_app.platform.state.load(); { let platform = abci_app.platform; diff --git a/packages/rs-drive-abci/tests/strategy_tests/voting_tests.rs b/packages/rs-drive-abci/tests/strategy_tests/voting_tests.rs index 80c40e66fd7..e58376b719f 100644 --- a/packages/rs-drive-abci/tests/strategy_tests/voting_tests.rs +++ b/packages/rs-drive-abci/tests/strategy_tests/voting_tests.rs @@ -1,7 +1,7 @@ #[cfg(test)] mod tests { - use crate::execution::run_chain_for_strategy; - use crate::strategy::NetworkStrategy; + use crate::execution::{continue_chain_for_strategy, run_chain_for_strategy}; + use crate::strategy::{ChainExecutionOutcome, ChainExecutionParameters, NetworkStrategy, StrategyRandomness}; use dpp::data_contract::accessors::v0::DataContractV0Getters; use dpp::data_contract::document_type::random_document::{ DocumentFieldFillSize, DocumentFieldFillType, @@ -20,9 +20,14 @@ mod tests { use dapi_grpc::platform::v0::get_contested_resource_vote_state_request::get_contested_resource_vote_state_request_v0::ResultType; use dapi_grpc::platform::v0::get_contested_resource_vote_state_request::GetContestedResourceVoteStateRequestV0; use dapi_grpc::platform::v0::get_contested_resource_vote_state_response::{get_contested_resource_vote_state_response_v0, GetContestedResourceVoteStateResponseV0}; + use dpp::block::extended_block_info::v0::ExtendedBlockInfoV0Getters; use dpp::data_contract::document_type::accessors::DocumentTypeV0Getters; + use dpp::voting::vote_choices::resource_vote_choice::ResourceVoteChoice; + use drive::drive::object_size_info::DataContractOwnedResolvedInfo; + use drive::drive::votes::resolved::vote_polls::contested_document_resource_vote_poll::ContestedDocumentResourceVotePollWithContractInfo; + use drive_abci::platform_types::platform_state::v0::PlatformStateV0Methods; use strategy_tests::frequency::Frequency; - use strategy_tests::operations::{DocumentAction, DocumentOp, Operation, OperationType}; + use strategy_tests::operations::{DocumentAction, DocumentOp, Operation, OperationType, ResourceVoteOp, VoteAction}; use strategy_tests::transitions::create_state_transitions_for_identities; use strategy_tests::{StartIdentities, Strategy}; @@ -182,8 +187,14 @@ mod tests { }; // On the first block we only have identities and contracts - let outcome = - run_chain_for_strategy(&mut platform, 2, strategy.clone(), config.clone(), 15); + let outcome = run_chain_for_strategy( + &mut platform, + 2, + strategy.clone(), + config.clone(), + 15, + &mut None, + ); let platform = outcome.abci_app.platform; @@ -314,4 +325,383 @@ mod tests { assert_eq!(second_contender.vote_count, Some(0)); } + + #[test] + fn run_chain_with_voting_on_conflicting_index() { + // In this test we try to insert two state transitions with the same unique index + // We use the DPNS contract, and we insert two documents both with the same "name" + // This is a common scenario we should see quite often + let config = PlatformConfig { + validator_set_quorum_size: 100, + validator_set_quorum_type: "llmq_100_67".to_string(), + chain_lock_quorum_type: "llmq_100_67".to_string(), + execution: ExecutionConfig { + //we disable document triggers because we are using dpns and dpns needs a preorder + use_document_triggers: false, + validator_set_rotation_block_count: 25, + ..Default::default() + }, + block_spacing_ms: 3000, + ..Default::default() + }; + let mut platform = TestPlatformBuilder::new() + .with_config(config.clone()) + .build_with_mock_rpc(); + + let platform_version = PlatformVersion::latest(); + + let mut rng = StdRng::seed_from_u64(567); + + let mut simple_signer = SimpleSigner::default(); + + let (identity1, keys1) = + Identity::random_identity_with_main_keys_with_private_key::>( + 2, + &mut rng, + platform_version, + ) + .unwrap(); + + simple_signer.add_keys(keys1); + + let (identity2, keys2) = + Identity::random_identity_with_main_keys_with_private_key::>( + 2, + &mut rng, + platform_version, + ) + .unwrap(); + + simple_signer.add_keys(keys2); + + let start_identities = create_state_transitions_for_identities( + vec![identity1, identity2], + &simple_signer, + &mut rng, + platform_version, + ); + + let dpns_contract = platform + .drive + .cache + .system_data_contracts + .load_dpns() + .as_ref() + .clone(); + + let document_type = dpns_contract + .document_type_for_name("domain") + .expect("expected a profile document type") + .to_owned_document_type(); + + let identity1_id = start_identities.first().unwrap().0.id(); + let identity2_id = start_identities.last().unwrap().0.id(); + let document_op_1 = DocumentOp { + contract: dpns_contract.clone(), + action: DocumentAction::DocumentActionInsertSpecific( + BTreeMap::from([ + ("label".into(), "quantum".into()), + ("normalizedLabel".into(), "quantum".into()), + ("normalizedParentDomainName".into(), "dash".into()), + ( + "records".into(), + BTreeMap::from([("dashUniqueIdentityId", Value::from(identity1_id))]) + .into(), + ), + ]), + Some(start_identities.first().unwrap().0.id()), + DocumentFieldFillType::FillIfNotRequired, + DocumentFieldFillSize::AnyDocumentFillSize, + ), + document_type: document_type.clone(), + }; + + let document_op_2 = DocumentOp { + contract: dpns_contract.clone(), + action: DocumentAction::DocumentActionInsertSpecific( + BTreeMap::from([ + ("label".into(), "quantum".into()), + ("normalizedLabel".into(), "quantum".into()), + ("normalizedParentDomainName".into(), "dash".into()), + ( + "records".into(), + BTreeMap::from([( + "dashUniqueIdentityId", + Value::from(start_identities.last().unwrap().0.id()), + )]) + .into(), + ), + ]), + Some(start_identities.last().unwrap().0.id()), + DocumentFieldFillType::FillIfNotRequired, + DocumentFieldFillSize::AnyDocumentFillSize, + ), + document_type: document_type.clone(), + }; + + let strategy = NetworkStrategy { + strategy: Strategy { + start_contracts: vec![], + operations: vec![ + Operation { + op_type: OperationType::Document(document_op_1), + frequency: Frequency { + times_per_block_range: 1..2, + chance_per_block: None, + }, + }, + Operation { + op_type: OperationType::Document(document_op_2), + frequency: Frequency { + times_per_block_range: 1..2, + chance_per_block: None, + }, + }, + ], + start_identities: StartIdentities { + hard_coded: start_identities, + ..Default::default() + }, + identity_inserts: Default::default(), + + identity_contract_nonce_gaps: None, + signer: Some(simple_signer), + }, + total_hpmns: 100, + extra_normal_mns: 0, + validator_quorum_count: 24, + chain_lock_quorum_count: 24, + upgrading_info: None, + + proposer_strategy: Default::default(), + rotate_quorums: false, + failure_testing: None, + query_testing: None, + verify_state_transition_results: true, + ..Default::default() + }; + + let mut voting_signer = Some(SimpleSigner::default()); + + // On the first block we only have identities and contracts + let ChainExecutionOutcome { + abci_app, + proposers, + quorums, + current_quorum_hash, + current_proposer_versions, + end_time_ms, + identity_nonce_counter, + identity_contract_nonce_counter, + state_transition_results_per_block, + .. + } = run_chain_for_strategy( + &mut platform, + 2, + strategy.clone(), + config.clone(), + 15, + &mut voting_signer, + ); + + let platform = abci_app.platform; + + let platform_state = platform.state.load(); + + let state_transitions_block_2 = state_transition_results_per_block + .get(&2) + .expect("expected to get block 2"); + + let first_document_insert_result = &state_transitions_block_2 + .first() + .as_ref() + .expect("expected a document insert") + .1; + assert_eq!(first_document_insert_result.code, 0); + + let second_document_insert_result = &state_transitions_block_2 + .get(1) + .as_ref() + .expect("expected a document insert") + .1; + + assert_eq!(second_document_insert_result.code, 0); // we expect the second to also be insertable as they are both contested + + let block_start = platform_state + .last_committed_block_info() + .as_ref() + .unwrap() + .basic_info() + .height + + 1; + let outcome = continue_chain_for_strategy( + abci_app, + ChainExecutionParameters { + block_start, + core_height_start: 1, + block_count: 30, + proposers, + quorums, + current_quorum_hash, + current_proposer_versions: Some(current_proposer_versions.clone()), + current_identity_nonce_counter: identity_nonce_counter, + current_identity_contract_nonce_counter: identity_contract_nonce_counter, + start_time_ms: 1681094380000, + current_time_ms: end_time_ms, + }, + NetworkStrategy { + strategy: Strategy { + start_contracts: vec![], + operations: vec![Operation { + op_type: OperationType::ResourceVote(ResourceVoteOp { + resolved_vote_poll: ContestedDocumentResourceVotePollWithContractInfo { + contract: DataContractOwnedResolvedInfo::OwnedDataContract( + dpns_contract.clone(), + ), + document_type_name: "domain".to_string(), + index_name: "parentNameAndLabel".to_string(), + index_values: vec!["dash".into(), "quantum".into()], + }, + action: VoteAction { + vote_choices_with_weights: vec![( + ResourceVoteChoice::TowardsIdentity(identity1_id), + 1, + )], + }, + }), + frequency: Frequency { + times_per_block_range: 1..3, + chance_per_block: None, + }, + }], + start_identities: StartIdentities::default(), + identity_inserts: Default::default(), + + identity_contract_nonce_gaps: None, + signer: voting_signer, + }, + total_hpmns: 100, + extra_normal_mns: 0, + validator_quorum_count: 24, + chain_lock_quorum_count: 24, + upgrading_info: None, + + proposer_strategy: Default::default(), + rotate_quorums: false, + failure_testing: None, + query_testing: None, + verify_state_transition_results: true, + ..Default::default() + }, + config.clone(), + StrategyRandomness::SeedEntropy(7), + ); + + let platform = outcome.abci_app.platform; + + // Now let's run a query for the vote totals + + let config = bincode::config::standard() + .with_big_endian() + .with_no_limit(); + + let dash_encoded = bincode::encode_to_vec(Value::Text("dash".to_string()), config) + .expect("expected to encode the word dash"); + + let quantum_encoded = bincode::encode_to_vec(Value::Text("quantum".to_string()), config) + .expect("expected to encode the word quantum"); + + let index_name = "parentNameAndLabel".to_string(); + + let query_validation_result = platform + .query_contested_resource_vote_state( + GetContestedResourceVoteStateRequest { + version: Some(get_contested_resource_vote_state_request::Version::V0( + GetContestedResourceVoteStateRequestV0 { + contract_id: dpns_contract.id().to_vec(), + document_type_name: document_type.name().clone(), + index_name: index_name.clone(), + index_values: vec![dash_encoded.clone(), quantum_encoded.clone()], + result_type: ResultType::DocumentsAndVoteTally as i32, + allow_include_locked_and_abstaining_vote_tally: true, + start_at_identifier_info: None, + count: None, + prove: false, + }, + )), + }, + &platform_state, + platform_version, + ) + .expect("expected to execute query") + .into_data() + .expect("expected query to be valid"); + + let get_contested_resource_vote_state_response::Version::V0( + GetContestedResourceVoteStateResponseV0 { + metadata: _, + result, + }, + ) = query_validation_result.version.expect("expected a version"); + + let Some( + get_contested_resource_vote_state_response_v0::Result::ContestedResourceContenders( + get_contested_resource_vote_state_response_v0::ContestedResourceContenders { + contenders, + abstain_vote_tally: _, + lock_vote_tally: _, + finished_vote_info: _, + }, + ), + ) = result + else { + panic!("expected contenders") + }; + + assert_eq!(contenders.len(), 2); + + let first_contender = contenders.first().unwrap(); + + let second_contender = contenders.last().unwrap(); + + assert_eq!( + first_contender.document, + Some(vec![ + 0, 24, 85, 248, 135, 55, 81, 210, 5, 93, 112, 104, 77, 97, 177, 49, 255, 108, 242, + 0, 83, 232, 168, 214, 145, 55, 49, 246, 246, 126, 99, 17, 108, 41, 18, 75, 231, + 232, 111, 151, 233, 89, 137, 74, 103, 169, 204, 7, 140, 62, 1, 6, 212, 191, 207, + 191, 52, 188, 64, 58, 79, 9, 153, 37, 180, 0, 0, 7, 113, 117, 97, 110, 116, 117, + 109, 7, 113, 117, 97, 110, 116, 117, 109, 1, 9, 112, 48, 81, 101, 48, 107, 49, 65, + 122, 4, 100, 97, 115, 104, 48, 165, 41, 91, 32, 215, 12, 4, 215, 10, 9, 207, 71, + 187, 248, 211, 105, 252, 147, 22, 127, 31, 203, 145, 6, 255, 132, 220, 231, 96, 76, + 195, 34, 1, 41, 18, 75, 231, 232, 111, 151, 233, 89, 137, 74, 103, 169, 204, 7, + 140, 62, 1, 6, 212, 191, 207, 191, 52, 188, 64, 58, 79, 9, 153, 37, 180, 0, 1, 0 + ]) + ); + + assert_eq!( + second_contender.document, + Some(vec![ + 0, 23, 193, 35, 24, 227, 101, 215, 103, 217, 98, 152, 114, 80, 94, 3, 27, 65, 246, + 202, 212, 59, 205, 101, 140, 243, 61, 26, 152, 167, 199, 96, 133, 139, 137, 72, + 166, 128, 21, 1, 187, 224, 67, 30, 61, 153, 77, 207, 113, 207, 90, 42, 9, 57, 254, + 81, 176, 230, 0, 7, 97, 153, 171, 164, 251, 0, 0, 7, 113, 117, 97, 110, 116, 117, + 109, 7, 113, 117, 97, 110, 116, 117, 109, 1, 36, 65, 50, 104, 52, 88, 69, 66, 112, + 116, 74, 101, 99, 48, 101, 98, 87, 53, 67, 52, 89, 106, 72, 119, 82, 81, 48, 51, + 88, 54, 83, 99, 75, 103, 89, 111, 97, 4, 100, 97, 115, 104, 110, 35, 254, 120, 68, + 194, 240, 23, 122, 207, 220, 40, 135, 147, 185, 9, 126, 239, 26, 0, 22, 196, 197, + 243, 182, 218, 58, 240, 230, 102, 185, 157, 34, 1, 139, 137, 72, 166, 128, 21, 1, + 187, 224, 67, 30, 61, 153, 77, 207, 113, 207, 90, 42, 9, 57, 254, 81, 176, 230, 0, + 7, 97, 153, 171, 164, 251, 0, 1, 0 + ]) + ); + + assert_eq!(first_contender.identifier, identity2_id.to_vec()); + + assert_eq!(second_contender.identifier, identity1_id.to_vec()); + + assert_eq!(first_contender.vote_count, Some(0)); + + assert_eq!(second_contender.vote_count, Some(0)); + } } diff --git a/packages/rs-drive/src/drive/object_size_info/contract_info.rs b/packages/rs-drive/src/drive/object_size_info/contract_info.rs index 70be1a8db2a..148706687dc 100644 --- a/packages/rs-drive/src/drive/object_size_info/contract_info.rs +++ b/packages/rs-drive/src/drive/object_size_info/contract_info.rs @@ -122,6 +122,19 @@ impl AsRef for DataContractOwnedResolvedInfo { } } +impl DataContractOwnedResolvedInfo { + /// Get the contract as owned + pub fn into_owned(self) -> DataContract { + match self { + #[cfg(feature = "server")] + DataContractOwnedResolvedInfo::DataContractFetchInfo(fetch_info) => { + fetch_info.contract.clone() + } + DataContractOwnedResolvedInfo::OwnedDataContract(owned) => owned, + } + } +} + /// Contains resolved data contract information, typically used after initial /// fetching or retrieval steps have been completed. This enum simplifies handling /// of data contract states post-retrieval. diff --git a/packages/strategy-tests/Cargo.toml b/packages/strategy-tests/Cargo.toml index 7487c04c8bc..f3e466a83b1 100644 --- a/packages/strategy-tests/Cargo.toml +++ b/packages/strategy-tests/Cargo.toml @@ -37,6 +37,8 @@ dpp = { path = "../rs-dpp", features = [ ] } simple-signer = { path = "../simple-signer" } platform-version = { path = "../rs-platform-version" } +platform-serialization = { path = "../rs-platform-serialization" } +platform-serialization-derive = { path = "../rs-platform-serialization-derive" } [dev-dependencies] platform-version = { path = "../rs-platform-version", features = [ diff --git a/packages/strategy-tests/src/operations.rs b/packages/strategy-tests/src/operations.rs index 18c7dd0f117..30c07ce3225 100644 --- a/packages/strategy-tests/src/operations.rs +++ b/packages/strategy-tests/src/operations.rs @@ -16,10 +16,13 @@ use dpp::serialization::{ PlatformDeserializableWithPotentialValidationFromVersionedStructure, PlatformSerializableWithPlatformVersion, }; +use dpp::voting::vote_choices::resource_vote_choice::ResourceVoteChoice; use dpp::ProtocolError; use dpp::ProtocolError::{PlatformDeserializationError, PlatformSerializationError}; +use drive::drive::object_size_info::DataContractOwnedResolvedInfo; +use drive::drive::votes::resolved::vote_polls::contested_document_resource_vote_poll::ContestedDocumentResourceVotePollWithContractInfo; use platform_version::version::PlatformVersion; -use platform_version::TryIntoPlatformVersioned; +use platform_version::{TryFromPlatformVersioned, TryIntoPlatformVersioned}; use std::collections::BTreeMap; use std::ops::Range; @@ -347,6 +350,128 @@ impl PlatformDeserializableWithPotentialValidationFromVersionedStructure for Dat } } +#[derive(Debug, PartialEq, Clone, Encode, Decode)] +pub struct ContestedDocumentResourceVotePollWithSerializableContract { + /// The contract information associated with the document. + pub contract: DataContractInSerializationFormat, + /// The name of the document type. + pub document_type_name: String, + /// The name of the index. + pub index_name: String, + /// The values used in the index for the poll. + pub index_values: Vec, +} + +impl TryFromPlatformVersioned + for ContestedDocumentResourceVotePollWithSerializableContract +{ + type Error = ProtocolError; + fn try_from_platform_versioned( + value: ContestedDocumentResourceVotePollWithContractInfo, + platform_version: &PlatformVersion, + ) -> Result { + let ContestedDocumentResourceVotePollWithContractInfo { + contract, + document_type_name, + index_name, + index_values, + } = value; + Ok(ContestedDocumentResourceVotePollWithSerializableContract { + contract: contract + .into_owned() + .try_into_platform_versioned(platform_version)?, + document_type_name, + index_name, + index_values, + }) + } +} + +impl TryFromPlatformVersioned + for ContestedDocumentResourceVotePollWithContractInfo +{ + type Error = ProtocolError; + fn try_from_platform_versioned( + value: ContestedDocumentResourceVotePollWithSerializableContract, + platform_version: &PlatformVersion, + ) -> Result { + let ContestedDocumentResourceVotePollWithSerializableContract { + contract, + document_type_name, + index_name, + index_values, + } = value; + Ok(ContestedDocumentResourceVotePollWithContractInfo { + contract: DataContractOwnedResolvedInfo::OwnedDataContract( + DataContract::try_from_platform_versioned( + contract, + false, + &mut vec![], + platform_version, + )?, + ), + document_type_name, + index_name, + index_values, + }) + } +} + +#[derive(Clone, Debug, PartialEq)] +pub struct ResourceVoteOp { + pub resolved_vote_poll: ContestedDocumentResourceVotePollWithContractInfo, + pub action: VoteAction, +} + +#[derive(Clone, Debug, PartialEq, Encode, Decode)] +pub struct ResourceVoteOpSerializable { + pub resolved_vote_poll: ContestedDocumentResourceVotePollWithSerializableContract, + pub action: VoteAction, +} + +impl TryFromPlatformVersioned for ResourceVoteOp { + type Error = ProtocolError; + + fn try_from_platform_versioned( + value: ResourceVoteOpSerializable, + platform_version: &PlatformVersion, + ) -> Result { + let ResourceVoteOpSerializable { + resolved_vote_poll, + action, + } = value; + + Ok(ResourceVoteOp { + resolved_vote_poll: resolved_vote_poll.try_into_platform_versioned(platform_version)?, + action, + }) + } +} + +impl TryFromPlatformVersioned for ResourceVoteOpSerializable { + type Error = ProtocolError; + + fn try_from_platform_versioned( + value: ResourceVoteOp, + platform_version: &PlatformVersion, + ) -> Result { + let ResourceVoteOp { + resolved_vote_poll, + action, + } = value; + + Ok(ResourceVoteOpSerializable { + resolved_vote_poll: resolved_vote_poll.try_into_platform_versioned(platform_version)?, + action, + }) + } +} + +#[derive(Clone, Debug, PartialEq, Encode, Decode)] +pub struct VoteAction { + pub vote_choices_with_weights: Vec<(ResourceVoteChoice, u8)>, +} + #[derive(Clone, Debug, PartialEq)] pub enum OperationType { Document(DocumentOp), @@ -356,6 +481,7 @@ pub enum OperationType { ContractCreate(RandomDocumentTypeParameters, DocumentTypeCount), ContractUpdate(DataContractUpdateOp), IdentityTransfer, + ResourceVote(ResourceVoteOp), } #[derive(Clone, Debug, Encode, Decode)] @@ -367,6 +493,7 @@ enum OperationTypeInSerializationFormat { ContractCreate(RandomDocumentTypeParameters, DocumentTypeCount), ContractUpdate(Vec), IdentityTransfer, + ResourceVote(ResourceVoteOpSerializable), } impl PlatformSerializableWithPlatformVersion for OperationType { @@ -410,6 +537,11 @@ impl PlatformSerializableWithPlatformVersion for OperationType { ) } OperationType::IdentityTransfer => OperationTypeInSerializationFormat::IdentityTransfer, + OperationType::ResourceVote(resource_vote_op) => { + let vote_op_in_serialization_format = + resource_vote_op.try_into_platform_versioned(platform_version)?; + OperationTypeInSerializationFormat::ResourceVote(vote_op_in_serialization_format) + } }; let config = bincode::config::standard() .with_big_endian() @@ -466,6 +598,10 @@ impl PlatformDeserializableWithPotentialValidationFromVersionedStructure for Ope OperationType::ContractUpdate(update_op) } OperationTypeInSerializationFormat::IdentityTransfer => OperationType::IdentityTransfer, + OperationTypeInSerializationFormat::ResourceVote(resource_vote_op) => { + let vote_op = resource_vote_op.try_into_platform_versioned(platform_version)?; + OperationType::ResourceVote(vote_op) + } }) } } From 00a11f18bb23a09b43c30167bc13ded21eb32337 Mon Sep 17 00:00:00 2001 From: Quantum Explorer Date: Wed, 26 Jun 2024 02:47:11 +0300 Subject: [PATCH 26/55] a lot of work on strategy tests for voting --- .../execute_event/v0/mod.rs | 24 ++ .../validate_fees_of_event/v0/mod.rs | 3 +- .../execution/types/execution_event/mod.rs | 16 +- .../state_transitions/masternode_vote/mod.rs | 4 +- .../transform_into_action/v0/mod.rs | 108 ++--- .../tests/strategy_tests/execution.rs | 3 + .../tests/strategy_tests/main.rs | 7 + .../tests/strategy_tests/strategy.rs | 115 +++-- .../strategy_tests/upgrade_fork_tests.rs | 11 + .../tests/strategy_tests/voting_tests.rs | 408 ++++++++++++++++-- packages/strategy-tests/src/operations.rs | 22 + 11 files changed, 585 insertions(+), 136 deletions(-) diff --git a/packages/rs-drive-abci/src/execution/platform_events/state_transition_processing/execute_event/v0/mod.rs b/packages/rs-drive-abci/src/execution/platform_events/state_transition_processing/execute_event/v0/mod.rs index e7f03575d9e..af1a185e840 100644 --- a/packages/rs-drive-abci/src/execution/platform_events/state_transition_processing/execute_event/v0/mod.rs +++ b/packages/rs-drive-abci/src/execution/platform_events/state_transition_processing/execute_event/v0/mod.rs @@ -59,6 +59,7 @@ where )?) } ExecutionEvent::PaidFromAssetLockWithoutIdentity { .. } + | ExecutionEvent::PaidFixedCost { .. } | ExecutionEvent::Free { .. } => None, }; @@ -154,6 +155,29 @@ where )) } } + ExecutionEvent::PaidFixedCost { + operations, + fees_to_add_to_pool, + } => { + if consensus_errors.is_empty() { + self.drive + .apply_drive_operations( + operations, + true, + block_info, + Some(transaction), + platform_version, + ) + .map_err(Error::Drive)?; + + Ok(SuccessfulPaidExecution( + None, + FeeResult::default_with_fees(0, fees_to_add_to_pool), + )) + } else { + Ok(UnpaidConsensusExecutionError(consensus_errors)) + } + } ExecutionEvent::Free { operations } => { self.drive .apply_drive_operations( diff --git a/packages/rs-drive-abci/src/execution/platform_events/state_transition_processing/validate_fees_of_event/v0/mod.rs b/packages/rs-drive-abci/src/execution/platform_events/state_transition_processing/validate_fees_of_event/v0/mod.rs index 27e56dd02f1..5f9000326f1 100644 --- a/packages/rs-drive-abci/src/execution/platform_events/state_transition_processing/validate_fees_of_event/v0/mod.rs +++ b/packages/rs-drive-abci/src/execution/platform_events/state_transition_processing/validate_fees_of_event/v0/mod.rs @@ -146,7 +146,8 @@ where )) } } - ExecutionEvent::Free { .. } + ExecutionEvent::PaidFixedCost { .. } + | ExecutionEvent::Free { .. } | ExecutionEvent::PaidFromAssetLockWithoutIdentity { .. } => Ok( ConsensusValidationResult::new_with_data(FeeResult::default()), ), diff --git a/packages/rs-drive-abci/src/execution/types/execution_event/mod.rs b/packages/rs-drive-abci/src/execution/types/execution_event/mod.rs index 133aafb3a5e..f3d3da8aaa2 100644 --- a/packages/rs-drive-abci/src/execution/types/execution_event/mod.rs +++ b/packages/rs-drive-abci/src/execution/types/execution_event/mod.rs @@ -36,6 +36,13 @@ pub(in crate::execution) enum ExecutionEvent<'a> { /// the fee multiplier that the user agreed to, 0 means 100% of the base fee, 1 means 101% user_fee_increase: UserFeeIncrease, }, + /// A drive event that has a fixed cost that will be taken out in the operations + PaidFixedCost { + /// the operations that should be performed + operations: Vec>, + /// fees to add + fees_to_add_to_pool: Credits, + }, /// A drive event that is paid from an asset lock PaidFromAssetLock { /// The identity requesting the event @@ -177,7 +184,14 @@ impl<'a> ExecutionEvent<'a> { StateTransitionAction::MasternodeVoteAction(_) => { let operations = action.into_high_level_drive_operations(epoch, platform_version)?; - Ok(ExecutionEvent::Free { operations }) + + Ok(ExecutionEvent::PaidFixedCost { + operations, + fees_to_add_to_pool: platform_version + .fee_version + .vote_resolution_fund_fees + .contested_document_single_vote_cost, + }) } _ => { let user_fee_increase = action.user_fee_increase(); diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/masternode_vote/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/masternode_vote/mod.rs index 3e7d74f39e5..25f6f026def 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/masternode_vote/mod.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/masternode_vote/mod.rs @@ -30,7 +30,7 @@ impl StateTransitionActionTransformerV0 for MasternodeVoteTransition { &self, platform: &PlatformRef, _block_info: &BlockInfo, - _validation_mode: ValidationMode, + validation_mode: ValidationMode, _execution_context: &mut StateTransitionExecutionContext, tx: TransactionArg, ) -> Result, Error> { @@ -44,7 +44,7 @@ impl StateTransitionActionTransformerV0 for MasternodeVoteTransition { .transform_into_action { 0 => self - .transform_into_action_v0(platform, tx, platform_version) + .transform_into_action_v0(platform, validation_mode, tx, platform_version) .map(|result| result.map(|action| action.into())), version => Err(Error::Execution(ExecutionError::UnknownVersionMismatch { method: "masternode votes state transition: transform_into_action".to_string(), diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/masternode_vote/transform_into_action/v0/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/masternode_vote/transform_into_action/v0/mod.rs index 6e17495d3c4..b49fbe56eaa 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/masternode_vote/transform_into_action/v0/mod.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/masternode_vote/transform_into_action/v0/mod.rs @@ -14,6 +14,7 @@ use dpp::state_transition::masternode_vote_transition::accessors::MasternodeVote use dpp::state_transition::masternode_vote_transition::MasternodeVoteTransition; use drive::state_transition_action::identity::masternode_vote::MasternodeVoteTransitionAction; +use crate::execution::validation::state_transition::ValidationMode; use crate::platform_types::platform_state::v0::PlatformStateV0Methods; use dpp::version::PlatformVersion; use dpp::voting::vote_polls::VotePoll; @@ -26,6 +27,7 @@ pub(in crate::execution::validation::state_transition::state_transitions::master fn transform_into_action_v0( &self, platform: &PlatformRef, + validation_mode: ValidationMode, tx: TransactionArg, platform_version: &PlatformVersion, ) -> Result, Error>; @@ -35,66 +37,70 @@ impl MasternodeVoteStateTransitionTransformIntoActionValidationV0 for Masternode fn transform_into_action_v0( &self, platform: &PlatformRef, + validation_mode: ValidationMode, tx: TransactionArg, platform_version: &PlatformVersion, ) -> Result, Error> { let mut previous_resource_vote_choice_to_remove = None; - // Before we transform into action we want to make sure that we have not yet voted - match self.vote() { - Vote::ResourceVote(resource_vote) => { - match resource_vote.vote_poll() { - VotePoll::ContestedDocumentResourceVotePoll(vote_poll) => { - let vote_id = vote_poll.unique_id()?; - let maybe_existing_resource_vote_choice = - platform.drive.fetch_identity_contested_resource_vote( - self.pro_tx_hash(), - vote_id, - tx, - &mut vec![], - platform_version, - )?; - if let Some((existing_resource_vote_choice, previous_vote_count)) = - maybe_existing_resource_vote_choice - { - if existing_resource_vote_choice == resource_vote.resource_vote_choice() + if validation_mode != ValidationMode::NoValidation { + // Before we transform into action we want to make sure that we have not yet voted + match self.vote() { + Vote::ResourceVote(resource_vote) => { + match resource_vote.vote_poll() { + VotePoll::ContestedDocumentResourceVotePoll(vote_poll) => { + let vote_id = vote_poll.unique_id()?; + let maybe_existing_resource_vote_choice = + platform.drive.fetch_identity_contested_resource_vote( + self.pro_tx_hash(), + vote_id, + tx, + &mut vec![], + platform_version, + )?; + if let Some((existing_resource_vote_choice, previous_vote_count)) = + maybe_existing_resource_vote_choice { - // We are submitting a vote for something we already have - return Ok(ConsensusValidationResult::new_with_error( - ConsensusError::StateError( - StateError::MasternodeVoteAlreadyPresentError( - MasternodeVoteAlreadyPresentError::new( - self.pro_tx_hash(), - resource_vote.vote_poll().clone(), + if existing_resource_vote_choice + == resource_vote.resource_vote_choice() + { + // We are submitting a vote for something we already have + return Ok(ConsensusValidationResult::new_with_error( + ConsensusError::StateError( + StateError::MasternodeVoteAlreadyPresentError( + MasternodeVoteAlreadyPresentError::new( + self.pro_tx_hash(), + resource_vote.vote_poll().clone(), + ), ), ), - ), - )); - } else if previous_vote_count - >= platform_version - .dpp - .validation - .voting - .votes_allowed_per_masternode - { - // We are submitting a vote for something we already have - return Ok(ConsensusValidationResult::new_with_error( - ConsensusError::StateError( - StateError::MasternodeVotedTooManyTimesError( - MasternodeVotedTooManyTimesError::new( - self.pro_tx_hash(), - previous_vote_count, - platform_version - .dpp - .validation - .voting - .votes_allowed_per_masternode, + )); + } else if previous_vote_count + >= platform_version + .dpp + .validation + .voting + .votes_allowed_per_masternode + { + // We are submitting a vote for something we already have + return Ok(ConsensusValidationResult::new_with_error( + ConsensusError::StateError( + StateError::MasternodeVotedTooManyTimesError( + MasternodeVotedTooManyTimesError::new( + self.pro_tx_hash(), + previous_vote_count, + platform_version + .dpp + .validation + .voting + .votes_allowed_per_masternode, + ), ), ), - ), - )); - } else { - previous_resource_vote_choice_to_remove = - Some((existing_resource_vote_choice, previous_vote_count)); + )); + } else { + previous_resource_vote_choice_to_remove = + Some((existing_resource_vote_choice, previous_vote_count)); + } } } } diff --git a/packages/rs-drive-abci/tests/strategy_tests/execution.rs b/packages/rs-drive-abci/tests/strategy_tests/execution.rs index 618e2546921..427703b02d3 100644 --- a/packages/rs-drive-abci/tests/strategy_tests/execution.rs +++ b/packages/rs-drive-abci/tests/strategy_tests/execution.rs @@ -777,6 +777,7 @@ pub(crate) fn start_chain_for_strategy( current_proposer_versions: None, current_identity_nonce_counter: Default::default(), current_identity_contract_nonce_counter: Default::default(), + current_votes: Default::default(), start_time_ms: GENESIS_TIME_MS, current_time_ms: GENESIS_TIME_MS, }, @@ -804,6 +805,7 @@ pub(crate) fn continue_chain_for_strategy( current_proposer_versions, mut current_identity_nonce_counter, mut current_identity_contract_nonce_counter, + mut current_votes, start_time_ms, mut current_time_ms, } = chain_execution_parameters; @@ -880,6 +882,7 @@ pub(crate) fn continue_chain_for_strategy( &mut current_identities, &mut current_identity_nonce_counter, &mut current_identity_contract_nonce_counter, + &mut current_votes, &mut signer, &mut rng, ); diff --git a/packages/rs-drive-abci/tests/strategy_tests/main.rs b/packages/rs-drive-abci/tests/strategy_tests/main.rs index 5c0f979f94d..80d6999b352 100644 --- a/packages/rs-drive-abci/tests/strategy_tests/main.rs +++ b/packages/rs-drive-abci/tests/strategy_tests/main.rs @@ -302,6 +302,7 @@ mod tests { current_proposer_versions: Some(current_proposer_versions), current_identity_nonce_counter: identity_nonce_counter, current_identity_contract_nonce_counter: identity_contract_nonce_counter, + current_votes: BTreeMap::default(), start_time_ms: 1681094380000, current_time_ms: end_time_ms, }, @@ -441,6 +442,7 @@ mod tests { current_proposer_versions: Some(current_proposer_versions), current_identity_nonce_counter: identity_nonce_counter, current_identity_contract_nonce_counter: identity_contract_nonce_counter, + current_votes: BTreeMap::default(), start_time_ms: 1681094380000, current_time_ms: end_time_ms, }, @@ -2991,6 +2993,7 @@ mod tests { current_proposer_versions: Some(current_proposer_versions), current_identity_nonce_counter: identity_nonce_counter, current_identity_contract_nonce_counter: identity_contract_nonce_counter, + current_votes: BTreeMap::default(), start_time_ms: GENESIS_TIME_MS, current_time_ms: end_time_ms, }, @@ -3072,6 +3075,7 @@ mod tests { current_proposer_versions: Some(current_proposer_versions), current_identity_nonce_counter: identity_nonce_counter, current_identity_contract_nonce_counter: identity_contract_nonce_counter, + current_votes: BTreeMap::default(), start_time_ms: GENESIS_TIME_MS, current_time_ms: end_time_ms + 1000, }, @@ -3184,6 +3188,7 @@ mod tests { current_proposer_versions: Some(current_proposer_versions), current_identity_nonce_counter: identity_nonce_counter, current_identity_contract_nonce_counter: identity_contract_nonce_counter, + current_votes: BTreeMap::default(), start_time_ms: GENESIS_TIME_MS, current_time_ms: end_time_ms + 1000, }, @@ -3291,6 +3296,7 @@ mod tests { current_proposer_versions: Some(current_proposer_versions), current_identity_nonce_counter: identity_nonce_counter, current_identity_contract_nonce_counter: identity_contract_nonce_counter, + current_votes: BTreeMap::default(), start_time_ms: GENESIS_TIME_MS, current_time_ms: end_time_ms + 1000, }, @@ -3955,6 +3961,7 @@ mod tests { current_proposer_versions: Some(current_proposer_versions), current_identity_nonce_counter: identity_nonce_counter, current_identity_contract_nonce_counter: identity_contract_nonce_counter, + current_votes: BTreeMap::default(), start_time_ms: 1681094380000, current_time_ms: end_time_ms, }, diff --git a/packages/rs-drive-abci/tests/strategy_tests/strategy.rs b/packages/rs-drive-abci/tests/strategy_tests/strategy.rs index ed6ff161a11..94159aec1e2 100644 --- a/packages/rs-drive-abci/tests/strategy_tests/strategy.rs +++ b/packages/rs-drive-abci/tests/strategy_tests/strategy.rs @@ -64,6 +64,7 @@ use dpp::state_transition::data_contract_create_transition::methods::v0::DataCon use dpp::state_transition::documents_batch_transition::document_transition::document_transfer_transition::DocumentTransferTransitionV0; use dpp::state_transition::masternode_vote_transition::MasternodeVoteTransition; use dpp::state_transition::masternode_vote_transition::methods::MasternodeVoteTransitionMethodsV0; +use dpp::voting::vote_choices::resource_vote_choice::ResourceVoteChoice; use dpp::voting::vote_polls::VotePoll; use dpp::voting::votes::resource_vote::ResourceVote; use dpp::voting::votes::resource_vote::v0::ResourceVoteV0; @@ -537,6 +538,9 @@ impl NetworkStrategy { signer: &mut SimpleSigner, identity_nonce_counter: &mut BTreeMap, contract_nonce_counter: &mut BTreeMap<(Identifier, Identifier), u64>, + // first identifier is the vote poll id + // second identifier is the identifier + current_votes: &mut BTreeMap>, rng: &mut StdRng, platform_version: &PlatformVersion, ) -> (Vec, Vec) { @@ -1275,52 +1279,72 @@ impl NetworkStrategy { OperationType::ResourceVote(resource_vote_op) => { let state = maybe_state.get_or_insert(platform.state.load()); let full_masternode_list = state.full_masternode_list(); + let vote_poll_id = resource_vote_op + .resolved_vote_poll + .unique_id() + .expect("expected a vote poll unique id"); + let vote_poll_votes = current_votes.entry(vote_poll_id).or_default(); + for _ in 0..count { + let rand_index = rng.gen_range(0..full_masternode_list.len()); + let (pro_tx_hash, masternode_list_item) = + full_masternode_list.iter().nth(rand_index).unwrap(); - let rand_index = rng.gen_range(0..full_masternode_list.len()); - let (pro_tx_hash, masternode_list_item) = - full_masternode_list.iter().nth(rand_index).unwrap(); - - let pro_tx_hash_bytes: [u8; 32] = pro_tx_hash.to_raw_hash().into(); - let voting_address = masternode_list_item.state.voting_address; - let identity_public_key = IdentityPublicKey::V0(IdentityPublicKeyV0 { - id: 0, - purpose: Purpose::VOTING, - security_level: SecurityLevel::MEDIUM, - contract_bounds: None, - key_type: KeyType::ECDSA_HASH160, - read_only: false, - data: voting_address.to_vec().into(), - disabled_at: None, - }); - - let vote = Vote::ResourceVote(ResourceVote::V0(ResourceVoteV0 { - vote_poll: VotePoll::ContestedDocumentResourceVotePoll( - resource_vote_op.resolved_vote_poll.clone().into(), - ), - resource_vote_choice: Default::default(), - })); - - let voting_identifier = Identifier::create_voter_identifier( - pro_tx_hash.as_byte_array(), - &voting_address, - ); - - let identity_nonce = - identity_nonce_counter.entry(voting_identifier).or_default(); - *identity_nonce += 1; - - let state_transition = MasternodeVoteTransition::try_from_vote_with_signer( - vote, - signer, - Identifier::from(pro_tx_hash_bytes), - &identity_public_key, - *identity_nonce, - platform_version, - None, - ) - .expect("expected to make a masternode vote transition"); + let pro_tx_hash_bytes: [u8; 32] = pro_tx_hash.to_raw_hash().into(); + let voting_address = masternode_list_item.state.voting_address; - operations.push(state_transition); + let voting_identifier = Identifier::create_voter_identifier( + pro_tx_hash.as_byte_array(), + &voting_address, + ); + + // Choose the resource vote choice based on weights + let resource_vote_choice = + resource_vote_op.action.choose_weighted_choice(rng); + + if vote_poll_votes.get(&voting_identifier) + == Some(&resource_vote_choice) + { + continue; + } + + let identity_public_key = IdentityPublicKey::V0(IdentityPublicKeyV0 { + id: 0, + purpose: Purpose::VOTING, + security_level: SecurityLevel::MEDIUM, + contract_bounds: None, + key_type: KeyType::ECDSA_HASH160, + read_only: false, + data: voting_address.to_vec().into(), + disabled_at: None, + }); + + let vote = Vote::ResourceVote(ResourceVote::V0(ResourceVoteV0 { + vote_poll: VotePoll::ContestedDocumentResourceVotePoll( + resource_vote_op.resolved_vote_poll.clone().into(), + ), + resource_vote_choice, + })); + + let identity_nonce = + identity_nonce_counter.entry(voting_identifier).or_default(); + *identity_nonce += 1; + + let state_transition = + MasternodeVoteTransition::try_from_vote_with_signer( + vote, + signer, + Identifier::from(pro_tx_hash_bytes), + &identity_public_key, + *identity_nonce, + platform_version, + None, + ) + .expect("expected to make a masternode vote transition"); + + vote_poll_votes.insert(voting_identifier, resource_vote_choice); + + operations.push(state_transition); + } } _ => {} } @@ -1336,6 +1360,7 @@ impl NetworkStrategy { current_identities: &mut Vec, identity_nonce_counter: &mut BTreeMap, contract_nonce_counter: &mut BTreeMap<(Identifier, Identifier), u64>, + current_votes: &mut BTreeMap>, signer: &mut SimpleSigner, rng: &mut StdRng, ) -> (Vec, Vec) { @@ -1379,6 +1404,7 @@ impl NetworkStrategy { signer, identity_nonce_counter, contract_nonce_counter, + current_votes, rng, platform_version, ); @@ -1521,6 +1547,7 @@ pub struct ChainExecutionParameters { pub current_proposer_versions: Option>>, pub current_identity_nonce_counter: BTreeMap, pub current_identity_contract_nonce_counter: BTreeMap<(Identifier, Identifier), IdentityNonce>, + pub current_votes: BTreeMap>, pub start_time_ms: u64, pub current_time_ms: u64, } diff --git a/packages/rs-drive-abci/tests/strategy_tests/upgrade_fork_tests.rs b/packages/rs-drive-abci/tests/strategy_tests/upgrade_fork_tests.rs index d19fb373d14..5822bceb1db 100644 --- a/packages/rs-drive-abci/tests/strategy_tests/upgrade_fork_tests.rs +++ b/packages/rs-drive-abci/tests/strategy_tests/upgrade_fork_tests.rs @@ -7,6 +7,7 @@ mod tests { use dpp::dashcore::{BlockHash, ChainLock}; use dpp::version::PlatformVersion; use drive::drive::config::DriveConfig; + use std::collections::BTreeMap; use crate::execution::{continue_chain_for_strategy, run_chain_for_strategy}; use crate::strategy::{ @@ -181,6 +182,7 @@ mod tests { current_proposer_versions: Some(current_proposer_versions.clone()), current_identity_nonce_counter: identity_nonce_counter, current_identity_contract_nonce_counter: identity_contract_nonce_counter, + current_votes: BTreeMap::default(), start_time_ms: 1681094380000, current_time_ms: end_time_ms, }, @@ -231,6 +233,7 @@ mod tests { current_proposer_versions: Some(current_proposer_versions), current_identity_nonce_counter: identity_nonce_counter, current_identity_contract_nonce_counter: identity_contract_nonce_counter, + current_votes: BTreeMap::default(), start_time_ms: 1681094380000, current_time_ms: end_time_ms, }, @@ -418,6 +421,7 @@ mod tests { current_proposer_versions: Some(current_proposer_versions.clone()), current_identity_nonce_counter: identity_nonce_counter, current_identity_contract_nonce_counter: identity_contract_nonce_counter, + current_votes: BTreeMap::default(), start_time_ms: 1681094380000, current_time_ms: end_time_ms, }, @@ -468,6 +472,7 @@ mod tests { current_proposer_versions: Some(current_proposer_versions), current_identity_nonce_counter: identity_nonce_counter, current_identity_contract_nonce_counter: identity_contract_nonce_counter, + current_votes: BTreeMap::default(), start_time_ms: 1681094380000, current_time_ms: end_time_ms, }, @@ -818,6 +823,7 @@ mod tests { current_proposer_versions: Some(current_proposer_versions.clone()), current_identity_nonce_counter: identity_nonce_counter, current_identity_contract_nonce_counter: identity_contract_nonce_counter, + current_votes: BTreeMap::default(), start_time_ms: 1681094380000, current_time_ms: end_time_ms, }, @@ -871,6 +877,7 @@ mod tests { current_proposer_versions: Some(current_proposer_versions), current_identity_nonce_counter: identity_nonce_counter, current_identity_contract_nonce_counter: identity_contract_nonce_counter, + current_votes: BTreeMap::default(), start_time_ms: 1681094380000, current_time_ms: end_time_ms, }, @@ -1043,6 +1050,7 @@ mod tests { current_proposer_versions: Some(current_proposer_versions), current_identity_nonce_counter: identity_nonce_counter, current_identity_contract_nonce_counter: identity_contract_nonce_counter, + current_votes: BTreeMap::default(), start_time_ms: 1681094380000, current_time_ms: end_time_ms, }, @@ -1139,6 +1147,7 @@ mod tests { current_proposer_versions: None, //restart the proposer versions current_identity_nonce_counter: identity_nonce_counter, current_identity_contract_nonce_counter: identity_contract_nonce_counter, + current_votes: BTreeMap::default(), start_time_ms: 1681094380000, current_time_ms: end_time_ms, }, @@ -1194,6 +1203,7 @@ mod tests { current_proposer_versions: Some(current_proposer_versions), current_identity_nonce_counter: identity_nonce_counter, current_identity_contract_nonce_counter: identity_contract_nonce_counter, + current_votes: BTreeMap::default(), start_time_ms: 1681094380000, current_time_ms: end_time_ms, }, @@ -1418,6 +1428,7 @@ mod tests { current_proposer_versions: None, current_identity_nonce_counter: identity_nonce_counter, current_identity_contract_nonce_counter: identity_contract_nonce_counter, + current_votes: BTreeMap::default(), start_time_ms: 1681094380000, current_time_ms: end_time_ms, }, diff --git a/packages/rs-drive-abci/tests/strategy_tests/voting_tests.rs b/packages/rs-drive-abci/tests/strategy_tests/voting_tests.rs index e58376b719f..52e34820f0c 100644 --- a/packages/rs-drive-abci/tests/strategy_tests/voting_tests.rs +++ b/packages/rs-drive-abci/tests/strategy_tests/voting_tests.rs @@ -327,7 +327,7 @@ mod tests { } #[test] - fn run_chain_with_voting_on_conflicting_index() { + fn run_chain_with_voting_on_conflicting_index_just_abstain_votes() { // In this test we try to insert two state transitions with the same unique index // We use the DPNS contract, and we insert two documents both with the same "name" // This is a common scenario we should see quite often @@ -546,6 +546,7 @@ mod tests { current_proposer_versions: Some(current_proposer_versions.clone()), current_identity_nonce_counter: identity_nonce_counter, current_identity_contract_nonce_counter: identity_contract_nonce_counter, + current_votes: BTreeMap::default(), start_time_ms: 1681094380000, current_time_ms: end_time_ms, }, @@ -563,10 +564,7 @@ mod tests { index_values: vec!["dash".into(), "quantum".into()], }, action: VoteAction { - vote_choices_with_weights: vec![( - ResourceVoteChoice::TowardsIdentity(identity1_id), - 1, - )], + vote_choices_with_weights: vec![(ResourceVoteChoice::Abstain, 1)], }, }), frequency: Frequency { @@ -590,7 +588,7 @@ mod tests { rotate_quorums: false, failure_testing: None, query_testing: None, - verify_state_transition_results: true, + verify_state_transition_results: false, ..Default::default() }, config.clone(), @@ -648,7 +646,7 @@ mod tests { get_contested_resource_vote_state_response_v0::Result::ContestedResourceContenders( get_contested_resource_vote_state_response_v0::ContestedResourceContenders { contenders, - abstain_vote_tally: _, + abstain_vote_tally, lock_vote_tally: _, finished_vote_info: _, }, @@ -664,37 +662,9 @@ mod tests { let second_contender = contenders.last().unwrap(); - assert_eq!( - first_contender.document, - Some(vec![ - 0, 24, 85, 248, 135, 55, 81, 210, 5, 93, 112, 104, 77, 97, 177, 49, 255, 108, 242, - 0, 83, 232, 168, 214, 145, 55, 49, 246, 246, 126, 99, 17, 108, 41, 18, 75, 231, - 232, 111, 151, 233, 89, 137, 74, 103, 169, 204, 7, 140, 62, 1, 6, 212, 191, 207, - 191, 52, 188, 64, 58, 79, 9, 153, 37, 180, 0, 0, 7, 113, 117, 97, 110, 116, 117, - 109, 7, 113, 117, 97, 110, 116, 117, 109, 1, 9, 112, 48, 81, 101, 48, 107, 49, 65, - 122, 4, 100, 97, 115, 104, 48, 165, 41, 91, 32, 215, 12, 4, 215, 10, 9, 207, 71, - 187, 248, 211, 105, 252, 147, 22, 127, 31, 203, 145, 6, 255, 132, 220, 231, 96, 76, - 195, 34, 1, 41, 18, 75, 231, 232, 111, 151, 233, 89, 137, 74, 103, 169, 204, 7, - 140, 62, 1, 6, 212, 191, 207, 191, 52, 188, 64, 58, 79, 9, 153, 37, 180, 0, 1, 0 - ]) - ); + assert!(first_contender.document.is_some()); - assert_eq!( - second_contender.document, - Some(vec![ - 0, 23, 193, 35, 24, 227, 101, 215, 103, 217, 98, 152, 114, 80, 94, 3, 27, 65, 246, - 202, 212, 59, 205, 101, 140, 243, 61, 26, 152, 167, 199, 96, 133, 139, 137, 72, - 166, 128, 21, 1, 187, 224, 67, 30, 61, 153, 77, 207, 113, 207, 90, 42, 9, 57, 254, - 81, 176, 230, 0, 7, 97, 153, 171, 164, 251, 0, 0, 7, 113, 117, 97, 110, 116, 117, - 109, 7, 113, 117, 97, 110, 116, 117, 109, 1, 36, 65, 50, 104, 52, 88, 69, 66, 112, - 116, 74, 101, 99, 48, 101, 98, 87, 53, 67, 52, 89, 106, 72, 119, 82, 81, 48, 51, - 88, 54, 83, 99, 75, 103, 89, 111, 97, 4, 100, 97, 115, 104, 110, 35, 254, 120, 68, - 194, 240, 23, 122, 207, 220, 40, 135, 147, 185, 9, 126, 239, 26, 0, 22, 196, 197, - 243, 182, 218, 58, 240, 230, 102, 185, 157, 34, 1, 139, 137, 72, 166, 128, 21, 1, - 187, 224, 67, 30, 61, 153, 77, 207, 113, 207, 90, 42, 9, 57, 254, 81, 176, 230, 0, - 7, 97, 153, 171, 164, 251, 0, 1, 0 - ]) - ); + assert!(second_contender.document.is_some()); assert_eq!(first_contender.identifier, identity2_id.to_vec()); @@ -703,5 +673,369 @@ mod tests { assert_eq!(first_contender.vote_count, Some(0)); assert_eq!(second_contender.vote_count, Some(0)); + + assert_eq!(abstain_vote_tally, Some(124)); + } + + #[test] + fn run_chain_with_voting_on_conflicting_index_various_votes() { + // In this test we try to insert two state transitions with the same unique index + // We use the DPNS contract, and we insert two documents both with the same "name" + // This is a common scenario we should see quite often + let config = PlatformConfig { + validator_set_quorum_size: 100, + validator_set_quorum_type: "llmq_100_67".to_string(), + chain_lock_quorum_type: "llmq_100_67".to_string(), + execution: ExecutionConfig { + //we disable document triggers because we are using dpns and dpns needs a preorder + use_document_triggers: false, + validator_set_rotation_block_count: 25, + ..Default::default() + }, + block_spacing_ms: 3000, + ..Default::default() + }; + let mut platform = TestPlatformBuilder::new() + .with_config(config.clone()) + .build_with_mock_rpc(); + + let platform_version = PlatformVersion::latest(); + + let mut rng = StdRng::seed_from_u64(567); + + let mut simple_signer = SimpleSigner::default(); + + let (identity1, keys1) = + Identity::random_identity_with_main_keys_with_private_key::>( + 2, + &mut rng, + platform_version, + ) + .unwrap(); + + simple_signer.add_keys(keys1); + + let (identity2, keys2) = + Identity::random_identity_with_main_keys_with_private_key::>( + 2, + &mut rng, + platform_version, + ) + .unwrap(); + + simple_signer.add_keys(keys2); + + let start_identities = create_state_transitions_for_identities( + vec![identity1, identity2], + &simple_signer, + &mut rng, + platform_version, + ); + + let dpns_contract = platform + .drive + .cache + .system_data_contracts + .load_dpns() + .as_ref() + .clone(); + + let document_type = dpns_contract + .document_type_for_name("domain") + .expect("expected a profile document type") + .to_owned_document_type(); + + let identity1_id = start_identities.first().unwrap().0.id(); + let identity2_id = start_identities.last().unwrap().0.id(); + let document_op_1 = DocumentOp { + contract: dpns_contract.clone(), + action: DocumentAction::DocumentActionInsertSpecific( + BTreeMap::from([ + ("label".into(), "quantum".into()), + ("normalizedLabel".into(), "quantum".into()), + ("normalizedParentDomainName".into(), "dash".into()), + ( + "records".into(), + BTreeMap::from([("dashUniqueIdentityId", Value::from(identity1_id))]) + .into(), + ), + ]), + Some(start_identities.first().unwrap().0.id()), + DocumentFieldFillType::FillIfNotRequired, + DocumentFieldFillSize::AnyDocumentFillSize, + ), + document_type: document_type.clone(), + }; + + let document_op_2 = DocumentOp { + contract: dpns_contract.clone(), + action: DocumentAction::DocumentActionInsertSpecific( + BTreeMap::from([ + ("label".into(), "quantum".into()), + ("normalizedLabel".into(), "quantum".into()), + ("normalizedParentDomainName".into(), "dash".into()), + ( + "records".into(), + BTreeMap::from([( + "dashUniqueIdentityId", + Value::from(start_identities.last().unwrap().0.id()), + )]) + .into(), + ), + ]), + Some(start_identities.last().unwrap().0.id()), + DocumentFieldFillType::FillIfNotRequired, + DocumentFieldFillSize::AnyDocumentFillSize, + ), + document_type: document_type.clone(), + }; + + let strategy = NetworkStrategy { + strategy: Strategy { + start_contracts: vec![], + operations: vec![ + Operation { + op_type: OperationType::Document(document_op_1), + frequency: Frequency { + times_per_block_range: 1..2, + chance_per_block: None, + }, + }, + Operation { + op_type: OperationType::Document(document_op_2), + frequency: Frequency { + times_per_block_range: 1..2, + chance_per_block: None, + }, + }, + ], + start_identities: StartIdentities { + hard_coded: start_identities, + ..Default::default() + }, + identity_inserts: Default::default(), + + identity_contract_nonce_gaps: None, + signer: Some(simple_signer), + }, + total_hpmns: 100, + extra_normal_mns: 0, + validator_quorum_count: 24, + chain_lock_quorum_count: 24, + upgrading_info: None, + + proposer_strategy: Default::default(), + rotate_quorums: false, + failure_testing: None, + query_testing: None, + verify_state_transition_results: true, + ..Default::default() + }; + + let mut voting_signer = Some(SimpleSigner::default()); + + // On the first block we only have identities and contracts + let ChainExecutionOutcome { + abci_app, + proposers, + quorums, + current_quorum_hash, + current_proposer_versions, + end_time_ms, + identity_nonce_counter, + identity_contract_nonce_counter, + state_transition_results_per_block, + .. + } = run_chain_for_strategy( + &mut platform, + 2, + strategy.clone(), + config.clone(), + 15, + &mut voting_signer, + ); + + let platform = abci_app.platform; + + let platform_state = platform.state.load(); + + let state_transitions_block_2 = state_transition_results_per_block + .get(&2) + .expect("expected to get block 2"); + + let first_document_insert_result = &state_transitions_block_2 + .first() + .as_ref() + .expect("expected a document insert") + .1; + assert_eq!(first_document_insert_result.code, 0); + + let second_document_insert_result = &state_transitions_block_2 + .get(1) + .as_ref() + .expect("expected a document insert") + .1; + + assert_eq!(second_document_insert_result.code, 0); // we expect the second to also be insertable as they are both contested + + let block_start = platform_state + .last_committed_block_info() + .as_ref() + .unwrap() + .basic_info() + .height + + 1; + let outcome = continue_chain_for_strategy( + abci_app, + ChainExecutionParameters { + block_start, + core_height_start: 1, + block_count: 30, + proposers, + quorums, + current_quorum_hash, + current_proposer_versions: Some(current_proposer_versions.clone()), + current_identity_nonce_counter: identity_nonce_counter, + current_identity_contract_nonce_counter: identity_contract_nonce_counter, + current_votes: BTreeMap::default(), + start_time_ms: 1681094380000, + current_time_ms: end_time_ms, + }, + NetworkStrategy { + strategy: Strategy { + start_contracts: vec![], + operations: vec![Operation { + op_type: OperationType::ResourceVote(ResourceVoteOp { + resolved_vote_poll: ContestedDocumentResourceVotePollWithContractInfo { + contract: DataContractOwnedResolvedInfo::OwnedDataContract( + dpns_contract.clone(), + ), + document_type_name: "domain".to_string(), + index_name: "parentNameAndLabel".to_string(), + index_values: vec!["dash".into(), "quantum".into()], + }, + action: VoteAction { + vote_choices_with_weights: vec![ + (ResourceVoteChoice::Abstain, 1), + (ResourceVoteChoice::Lock, 1), + (ResourceVoteChoice::TowardsIdentity(identity1_id), 5), + (ResourceVoteChoice::TowardsIdentity(identity2_id), 10), + ], + }, + }), + frequency: Frequency { + times_per_block_range: 1..3, + chance_per_block: None, + }, + }], + start_identities: StartIdentities::default(), + identity_inserts: Default::default(), + + identity_contract_nonce_gaps: None, + signer: voting_signer, + }, + total_hpmns: 100, + extra_normal_mns: 0, + validator_quorum_count: 24, + chain_lock_quorum_count: 24, + upgrading_info: None, + + proposer_strategy: Default::default(), + rotate_quorums: false, + failure_testing: None, + query_testing: None, + verify_state_transition_results: false, + ..Default::default() + }, + config.clone(), + StrategyRandomness::SeedEntropy(7), + ); + + let platform = outcome.abci_app.platform; + + // Now let's run a query for the vote totals + + let config = bincode::config::standard() + .with_big_endian() + .with_no_limit(); + + let dash_encoded = bincode::encode_to_vec(Value::Text("dash".to_string()), config) + .expect("expected to encode the word dash"); + + let quantum_encoded = bincode::encode_to_vec(Value::Text("quantum".to_string()), config) + .expect("expected to encode the word quantum"); + + let index_name = "parentNameAndLabel".to_string(); + + let query_validation_result = platform + .query_contested_resource_vote_state( + GetContestedResourceVoteStateRequest { + version: Some(get_contested_resource_vote_state_request::Version::V0( + GetContestedResourceVoteStateRequestV0 { + contract_id: dpns_contract.id().to_vec(), + document_type_name: document_type.name().clone(), + index_name: index_name.clone(), + index_values: vec![dash_encoded.clone(), quantum_encoded.clone()], + result_type: ResultType::DocumentsAndVoteTally as i32, + allow_include_locked_and_abstaining_vote_tally: true, + start_at_identifier_info: None, + count: None, + prove: false, + }, + )), + }, + &platform_state, + platform_version, + ) + .expect("expected to execute query") + .into_data() + .expect("expected query to be valid"); + + let get_contested_resource_vote_state_response::Version::V0( + GetContestedResourceVoteStateResponseV0 { + metadata: _, + result, + }, + ) = query_validation_result.version.expect("expected a version"); + + let Some( + get_contested_resource_vote_state_response_v0::Result::ContestedResourceContenders( + get_contested_resource_vote_state_response_v0::ContestedResourceContenders { + contenders, + abstain_vote_tally, + lock_vote_tally, + finished_vote_info, + }, + ), + ) = result + else { + panic!("expected contenders") + }; + + assert_eq!(contenders.len(), 2); + + let first_contender = contenders.first().unwrap(); + + let second_contender = contenders.last().unwrap(); + + assert!(first_contender.document.is_some()); + + assert!(second_contender.document.is_some()); + + assert_eq!(first_contender.identifier, identity2_id.to_vec()); + + assert_eq!(second_contender.identifier, identity1_id.to_vec()); + + // All vote counts are weighted, so for evonodes, these are in multiples of 4 + + assert_eq!(first_contender.vote_count, Some(52)); + + assert_eq!(second_contender.vote_count, Some(56)); + + assert_eq!(lock_vote_tally, Some(16)); + + assert_eq!(abstain_vote_tally, Some(8)); + + assert_eq!(finished_vote_info, None); } } diff --git a/packages/strategy-tests/src/operations.rs b/packages/strategy-tests/src/operations.rs index 30c07ce3225..3a02424ebe0 100644 --- a/packages/strategy-tests/src/operations.rs +++ b/packages/strategy-tests/src/operations.rs @@ -23,6 +23,8 @@ use drive::drive::object_size_info::DataContractOwnedResolvedInfo; use drive::drive::votes::resolved::vote_polls::contested_document_resource_vote_poll::ContestedDocumentResourceVotePollWithContractInfo; use platform_version::version::PlatformVersion; use platform_version::{TryFromPlatformVersioned, TryIntoPlatformVersioned}; +use rand::distributions::{Distribution, WeightedIndex}; +use rand::prelude::StdRng; use std::collections::BTreeMap; use std::ops::Range; @@ -472,6 +474,26 @@ pub struct VoteAction { pub vote_choices_with_weights: Vec<(ResourceVoteChoice, u8)>, } +impl VoteAction { + // Function to choose a ResourceVoteChoice based on weights + pub fn choose_weighted_choice(&self, rng: &mut StdRng) -> ResourceVoteChoice { + if self.vote_choices_with_weights.is_empty() { + ResourceVoteChoice::Abstain + } else if self.vote_choices_with_weights.len() == 1 { + self.vote_choices_with_weights[0].0 + } else { + let weights: Vec = self + .vote_choices_with_weights + .iter() + .map(|(_, weight)| *weight) + .collect(); + let dist = WeightedIndex::new(weights).unwrap(); + let index = dist.sample(rng); + self.vote_choices_with_weights[index].0 + } + } +} + #[derive(Clone, Debug, PartialEq)] pub enum OperationType { Document(DocumentOp), From a0d08509853113251338d2d7116deab5683bf4e8 Mon Sep 17 00:00:00 2001 From: pauldelucia Date: Wed, 26 Jun 2024 18:28:27 +0900 Subject: [PATCH 27/55] fix: PutVote was using wrong identity for nonce --- Cargo.lock | 2 + packages/rs-sdk/Cargo.toml | 2 + .../rs-sdk/src/platform/transition/vote.rs | 43 ++++++++++++++++++- 3 files changed, 45 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5f303b64b50..a7a6b5c517b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1348,6 +1348,7 @@ dependencies = [ "async-trait", "base64 0.22.1", "bip37-bloom-filter", + "bs58 0.5.1", "chrono", "ciborium", "clap 4.5.7", @@ -1370,6 +1371,7 @@ dependencies = [ "sanitize-filename", "serde", "serde_json", + "sha2", "thiserror", "tokio", "tokio-test", diff --git a/packages/rs-sdk/Cargo.toml b/packages/rs-sdk/Cargo.toml index fd1a5498a6e..90b0d3de508 100644 --- a/packages/rs-sdk/Cargo.toml +++ b/packages/rs-sdk/Cargo.toml @@ -36,6 +36,8 @@ dashcore-rpc = { git = "https://github.com/dashpay/rust-dashcore-rpc", tag = "v0 lru = { version = "0.12.3", optional = true } bip37-bloom-filter = { git = "https://github.com/dashpay/rs-bip37-bloom-filter", branch = "develop" } pollster = { version = "0.3.0" } +sha2 = "0.10.8" +bs58 = "0.5.0" [dev-dependencies] tokio = { version = "1.36.0", features = ["macros", "rt-multi-thread"] } diff --git a/packages/rs-sdk/src/platform/transition/vote.rs b/packages/rs-sdk/src/platform/transition/vote.rs index 505109f4fc4..d1b9161e8e1 100644 --- a/packages/rs-sdk/src/platform/transition/vote.rs +++ b/packages/rs-sdk/src/platform/transition/vote.rs @@ -5,8 +5,10 @@ use crate::platform::transition::put_settings::PutSettings; use crate::platform::Fetch; use crate::{Error, Sdk}; use dapi_grpc::platform::VersionedGrpcResponse; +use dpp::identity::hash::IdentityPublicKeyHashMethodsV0; use dpp::identity::signer::Signer; use dpp::identity::IdentityPublicKey; +use dpp::platform_value::string_encoding::Encoding; use dpp::prelude::Identifier; use dpp::state_transition::masternode_vote_transition::methods::MasternodeVoteTransitionMethodsV0; use dpp::state_transition::masternode_vote_transition::MasternodeVoteTransition; @@ -15,6 +17,7 @@ use dpp::voting::votes::resource_vote::accessors::v0::ResourceVoteGettersV0; use dpp::voting::votes::Vote; use drive::drive::Drive; use rs_dapi_client::DapiRequest; +use sha2::{Digest, Sha256}; #[async_trait::async_trait] /// A trait for putting a vote on platform @@ -49,8 +52,26 @@ impl PutVote for Vote { signer: &S, settings: Option, ) -> Result<(), Error> { + let pub_key_hash = voting_public_key.public_key_hash()?; + + let mut hasher = Sha256::new(); + hasher.update(voter_pro_tx_hash.as_bytes()); + hasher.update(pub_key_hash); + let voting_identity_id_hashed = hasher.finalize(); + let voting_identity_id_bs58 = bs58::encode(voting_identity_id_hashed).into_string(); + let voting_identity_id = + match Identifier::from_string(&voting_identity_id_bs58, Encoding::Base58) { + Ok(id) => id, + Err(e) => { + return Err(Error::Generic(format!( + "Couldn't convert id string to Identifier: {}", + e + ))) + } + }; + let new_masternode_voting_nonce = sdk - .get_identity_nonce(voter_pro_tx_hash, true, settings) + .get_identity_nonce(voting_identity_id, true, settings) .await?; let settings = settings.unwrap_or_default(); @@ -79,8 +100,26 @@ impl PutVote for Vote { signer: &S, settings: Option, ) -> Result { + let pub_key_hash = voting_public_key.public_key_hash()?; + + let mut hasher = Sha256::new(); + hasher.update(voter_pro_tx_hash.as_bytes()); + hasher.update(pub_key_hash); + let voting_identity_id_hashed = hasher.finalize(); + let voting_identity_id_bs58 = bs58::encode(voting_identity_id_hashed).into_string(); + let voting_identity_id = + match Identifier::from_string(&voting_identity_id_bs58, Encoding::Base58) { + Ok(id) => id, + Err(e) => { + return Err(Error::Generic(format!( + "Couldn't convert id string to Identifier: {}", + e + ))) + } + }; + let new_masternode_voting_nonce = sdk - .get_identity_nonce(voter_pro_tx_hash, true, settings) + .get_identity_nonce(voting_identity_id, true, settings) .await?; let settings = settings.unwrap_or_default(); From c4ff2a81ec5d743d1bc2087f6f90505074e0bddf Mon Sep 17 00:00:00 2001 From: pauldelucia Date: Thu, 27 Jun 2024 16:19:56 +0900 Subject: [PATCH 28/55] remove bs58 dependency --- Cargo.lock | 1 - packages/rs-sdk/Cargo.toml | 1 - .../rs-sdk/src/platform/transition/vote.rs | 41 ++++++++----------- 3 files changed, 18 insertions(+), 25 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a7a6b5c517b..4e62dd62e5e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1348,7 +1348,6 @@ dependencies = [ "async-trait", "base64 0.22.1", "bip37-bloom-filter", - "bs58 0.5.1", "chrono", "ciborium", "clap 4.5.7", diff --git a/packages/rs-sdk/Cargo.toml b/packages/rs-sdk/Cargo.toml index 90b0d3de508..87550d31a3c 100644 --- a/packages/rs-sdk/Cargo.toml +++ b/packages/rs-sdk/Cargo.toml @@ -37,7 +37,6 @@ lru = { version = "0.12.3", optional = true } bip37-bloom-filter = { git = "https://github.com/dashpay/rs-bip37-bloom-filter", branch = "develop" } pollster = { version = "0.3.0" } sha2 = "0.10.8" -bs58 = "0.5.0" [dev-dependencies] tokio = { version = "1.36.0", features = ["macros", "rt-multi-thread"] } diff --git a/packages/rs-sdk/src/platform/transition/vote.rs b/packages/rs-sdk/src/platform/transition/vote.rs index d1b9161e8e1..8066e5cde6a 100644 --- a/packages/rs-sdk/src/platform/transition/vote.rs +++ b/packages/rs-sdk/src/platform/transition/vote.rs @@ -8,7 +8,6 @@ use dapi_grpc::platform::VersionedGrpcResponse; use dpp::identity::hash::IdentityPublicKeyHashMethodsV0; use dpp::identity::signer::Signer; use dpp::identity::IdentityPublicKey; -use dpp::platform_value::string_encoding::Encoding; use dpp::prelude::Identifier; use dpp::state_transition::masternode_vote_transition::methods::MasternodeVoteTransitionMethodsV0; use dpp::state_transition::masternode_vote_transition::MasternodeVoteTransition; @@ -58,17 +57,15 @@ impl PutVote for Vote { hasher.update(voter_pro_tx_hash.as_bytes()); hasher.update(pub_key_hash); let voting_identity_id_hashed = hasher.finalize(); - let voting_identity_id_bs58 = bs58::encode(voting_identity_id_hashed).into_string(); - let voting_identity_id = - match Identifier::from_string(&voting_identity_id_bs58, Encoding::Base58) { - Ok(id) => id, - Err(e) => { - return Err(Error::Generic(format!( - "Couldn't convert id string to Identifier: {}", - e - ))) - } - }; + let voting_identity_id = match Identifier::from_bytes(&voting_identity_id_hashed) { + Ok(id) => id, + Err(e) => { + return Err(Error::Generic(format!( + "Couldn't convert id string to Identifier: {}", + e + ))) + } + }; let new_masternode_voting_nonce = sdk .get_identity_nonce(voting_identity_id, true, settings) @@ -106,17 +103,15 @@ impl PutVote for Vote { hasher.update(voter_pro_tx_hash.as_bytes()); hasher.update(pub_key_hash); let voting_identity_id_hashed = hasher.finalize(); - let voting_identity_id_bs58 = bs58::encode(voting_identity_id_hashed).into_string(); - let voting_identity_id = - match Identifier::from_string(&voting_identity_id_bs58, Encoding::Base58) { - Ok(id) => id, - Err(e) => { - return Err(Error::Generic(format!( - "Couldn't convert id string to Identifier: {}", - e - ))) - } - }; + let voting_identity_id = match Identifier::from_bytes(&voting_identity_id_hashed) { + Ok(id) => id, + Err(e) => { + return Err(Error::Generic(format!( + "Couldn't convert id string to Identifier: {}", + e + ))) + } + }; let new_masternode_voting_nonce = sdk .get_identity_nonce(voting_identity_id, true, settings) From 02fb3a08a8c2da185555101760a6c95c70c96066 Mon Sep 17 00:00:00 2001 From: pauldelucia Date: Thu, 27 Jun 2024 16:49:34 +0900 Subject: [PATCH 29/55] extract copied code to function --- .../rs-sdk/src/platform/transition/vote.rs | 47 +++++++------------ 1 file changed, 17 insertions(+), 30 deletions(-) diff --git a/packages/rs-sdk/src/platform/transition/vote.rs b/packages/rs-sdk/src/platform/transition/vote.rs index 8066e5cde6a..b21a16c281b 100644 --- a/packages/rs-sdk/src/platform/transition/vote.rs +++ b/packages/rs-sdk/src/platform/transition/vote.rs @@ -51,21 +51,7 @@ impl PutVote for Vote { signer: &S, settings: Option, ) -> Result<(), Error> { - let pub_key_hash = voting_public_key.public_key_hash()?; - - let mut hasher = Sha256::new(); - hasher.update(voter_pro_tx_hash.as_bytes()); - hasher.update(pub_key_hash); - let voting_identity_id_hashed = hasher.finalize(); - let voting_identity_id = match Identifier::from_bytes(&voting_identity_id_hashed) { - Ok(id) => id, - Err(e) => { - return Err(Error::Generic(format!( - "Couldn't convert id string to Identifier: {}", - e - ))) - } - }; + let voting_identity_id = get_voting_identity_id(voter_pro_tx_hash, voting_public_key)?; let new_masternode_voting_nonce = sdk .get_identity_nonce(voting_identity_id, true, settings) @@ -97,21 +83,7 @@ impl PutVote for Vote { signer: &S, settings: Option, ) -> Result { - let pub_key_hash = voting_public_key.public_key_hash()?; - - let mut hasher = Sha256::new(); - hasher.update(voter_pro_tx_hash.as_bytes()); - hasher.update(pub_key_hash); - let voting_identity_id_hashed = hasher.finalize(); - let voting_identity_id = match Identifier::from_bytes(&voting_identity_id_hashed) { - Ok(id) => id, - Err(e) => { - return Err(Error::Generic(format!( - "Couldn't convert id string to Identifier: {}", - e - ))) - } - }; + let voting_identity_id = get_voting_identity_id(voter_pro_tx_hash, voting_public_key)?; let new_masternode_voting_nonce = sdk .get_identity_nonce(voting_identity_id, true, settings) @@ -175,3 +147,18 @@ impl PutVote for Vote { } } } + +fn get_voting_identity_id( + voter_pro_tx_hash: Identifier, + voting_public_key: &IdentityPublicKey, +) -> Result { + let pub_key_hash = voting_public_key.public_key_hash()?; + + let mut hasher = Sha256::new(); + hasher.update(voter_pro_tx_hash.as_bytes()); + hasher.update(pub_key_hash); + let voting_identity_id_hashed = hasher.finalize(); + + Identifier::from_bytes(&voting_identity_id_hashed) + .map_err(|e| Error::Generic(format!("Couldn't convert id string to Identifier: {}", e))) +} From 9116c8c37bbafad2f738c108db59e60c9c08b217 Mon Sep 17 00:00:00 2001 From: Quantum Explorer Date: Thu, 27 Jun 2024 18:40:08 +0700 Subject: [PATCH 30/55] many more fixes --- Cargo.lock | 588 +++++++----------- packages/dapi-grpc/Cargo.toml | 2 +- .../src/voting/contender_structs/mod.rs | 7 +- .../mod.rs | 4 +- .../v0/mod.rs | 33 +- packages/rs-drive-abci/Cargo.toml | 2 +- .../engine/run_block_proposal/v0/mod.rs | 21 +- .../voting/check_for_ended_vote_polls/mod.rs | 9 +- .../check_for_ended_vote_polls/v0/mod.rs | 23 +- .../voting/keep_record_of_vote_poll/mod.rs | 3 + .../voting/keep_record_of_vote_poll/v0/mod.rs | 38 +- .../voting/run_dao_platform_events/v0/mod.rs | 7 +- .../state_transitions/documents_batch/mod.rs | 3 + .../state_transitions/masternode_vote/mod.rs | 415 +++++++++++- .../rs-drive-abci/src/query/proofs/v0/mod.rs | 58 +- .../verify_state_transitions.rs | 10 +- .../tests/strategy_tests/voting_tests.rs | 390 +++++++++++- packages/rs-drive-proof-verifier/Cargo.toml | 2 +- .../v0/mod.rs | 1 + .../voting/verify_masternode_vote/v0/mod.rs | 1 + .../mod.rs | 4 +- .../v0/mod.rs | 25 +- 22 files changed, 1216 insertions(+), 430 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3b570a56d88..453b23d7c3f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,6 +17,17 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +[[package]] +name = "aes" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" +dependencies = [ + "cfg-if", + "cipher", + "cpufeatures", +] + [[package]] name = "ahash" version = "0.7.8" @@ -211,7 +222,7 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -222,7 +233,7 @@ checksum = "c6fa2087f2753a7da8cc1c0dbfcf89579dd57458e36769de5ac750b4671737ca" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -397,7 +408,7 @@ dependencies = [ "regex", "rustc-hash", "shlex", - "syn 2.0.66", + "syn 2.0.68", "which", ] @@ -407,7 +418,7 @@ version = "0.69.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a00dc851838a2120612785d195287475a3ac45514741da670b735818822129a0" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "cexpr", "clang-sys", "itertools 0.12.1", @@ -418,7 +429,7 @@ dependencies = [ "regex", "rustc-hash", "shlex", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -469,9 +480,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" [[package]] name = "bitvec" @@ -495,7 +506,7 @@ dependencies = [ "arrayvec", "cc", "cfg-if", - "constant_time_eq", + "constant_time_eq 0.3.0", ] [[package]] @@ -548,7 +559,7 @@ dependencies = [ "proc-macro-crate 3.1.0", "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", "syn_derive", ] @@ -616,6 +627,16 @@ dependencies = [ "serde", ] +[[package]] +name = "bzip2" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bdb116a6ef3f6c3698828873ad02c3014b3c85cadb88496095628e3ef1e347f8" +dependencies = [ + "bzip2-sys", + "libc", +] + [[package]] name = "bzip2-sys" version = "0.1.11+1.0.8" @@ -731,9 +752,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.0.99" +version = "1.0.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96c51067fd44124faa7f870b4b1c969379ad32b2ba805aa959430ceaa384f695" +checksum = "ac367972e516d45567c7eafc73d24e1c193dcf200a8d94e9db7b3d38b349572d" dependencies = [ "jobserver", "libc", @@ -807,6 +828,16 @@ dependencies = [ "half", ] +[[package]] +name = "cipher" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" +dependencies = [ + "crypto-common", + "inout", +] + [[package]] name = "clang-sys" version = "1.8.1" @@ -860,7 +891,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -937,6 +968,12 @@ version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" +[[package]] +name = "constant_time_eq" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" + [[package]] name = "constant_time_eq" version = "0.3.0" @@ -1217,16 +1254,15 @@ dependencies = [ [[package]] name = "curve25519-dalek" -version = "4.1.2" +version = "4.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a677b8922c94e01bdbb12126b0bc852f00447528dee1782229af9c720c3f348" +checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be" dependencies = [ "cfg-if", "cpufeatures", "curve25519-dalek-derive", "digest", "fiat-crypto", - "platforms", "rustc_version", "subtle", "zeroize", @@ -1240,7 +1276,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -1266,7 +1302,7 @@ dependencies = [ "dapi-grpc", "heck 0.5.0", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -1290,7 +1326,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -1301,7 +1337,7 @@ checksum = "733cabb43482b1a1b53eee8583c2b9e8684d592215ea83efd305dd31bc2f0178" dependencies = [ "darling_core", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -1469,7 +1505,7 @@ dependencies = [ "proc-macro2", "quote", "rustc_version", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -1492,6 +1528,7 @@ checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ "block-buffer", "crypto-common", + "subtle", ] [[package]] @@ -1525,17 +1562,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "displaydoc" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.66", -] - [[package]] name = "dotenvy" version = "0.15.7" @@ -1770,9 +1796,9 @@ dependencies = [ [[package]] name = "either" -version = "1.12.0" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3dca9240753cf90908d7e4aac30f630662b02aebaa1b58a3cadabdb23385b58b" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" [[package]] name = "enum-map" @@ -1791,7 +1817,7 @@ checksum = "f282cfdfe92516eb26c2af8589c274c7c17681f5ecc03c18255fe741c6aa64eb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -1879,7 +1905,7 @@ dependencies = [ "proc-macro2", "quote", "syn 1.0.109", - "synstructure 0.12.6", + "synstructure", ] [[package]] @@ -2125,7 +2151,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -2207,7 +2233,7 @@ checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" [[package]] name = "grovedb" version = "1.0.0-rc.2" -source = "git+https://github.com/dashpay/grovedb?branch=feat/QuerySumTree#0b32606fd4983899ca2b5865299f04b1a0accc98" +source = "git+https://github.com/dashpay/grovedb?branch=feat/QuerySumTree#1696c2ef47a674be5ec213b9ff723afe4c45fb90" dependencies = [ "bincode 2.0.0-rc.3", "bitvec", @@ -2225,12 +2251,13 @@ dependencies = [ "nohash-hasher", "tempfile", "thiserror", + "zip-extensions", ] [[package]] name = "grovedb-costs" version = "1.0.0-rc.2" -source = "git+https://github.com/dashpay/grovedb?branch=feat/QuerySumTree#0b32606fd4983899ca2b5865299f04b1a0accc98" +source = "git+https://github.com/dashpay/grovedb?branch=feat/QuerySumTree#1696c2ef47a674be5ec213b9ff723afe4c45fb90" dependencies = [ "integer-encoding", "intmap", @@ -2240,7 +2267,7 @@ dependencies = [ [[package]] name = "grovedb-merk" version = "1.0.0-rc.2" -source = "git+https://github.com/dashpay/grovedb?branch=feat/QuerySumTree#0b32606fd4983899ca2b5865299f04b1a0accc98" +source = "git+https://github.com/dashpay/grovedb?branch=feat/QuerySumTree#1696c2ef47a674be5ec213b9ff723afe4c45fb90" dependencies = [ "blake3", "byteorder", @@ -2263,12 +2290,12 @@ dependencies = [ [[package]] name = "grovedb-path" version = "1.0.0-rc.2" -source = "git+https://github.com/dashpay/grovedb?branch=feat/QuerySumTree#0b32606fd4983899ca2b5865299f04b1a0accc98" +source = "git+https://github.com/dashpay/grovedb?branch=feat/QuerySumTree#1696c2ef47a674be5ec213b9ff723afe4c45fb90" [[package]] name = "grovedb-storage" version = "1.0.0-rc.2" -source = "git+https://github.com/dashpay/grovedb?branch=feat/QuerySumTree#0b32606fd4983899ca2b5865299f04b1a0accc98" +source = "git+https://github.com/dashpay/grovedb?branch=feat/QuerySumTree#1696c2ef47a674be5ec213b9ff723afe4c45fb90" dependencies = [ "blake3", "grovedb-costs", @@ -2279,7 +2306,7 @@ dependencies = [ "lazy_static", "num_cpus", "rocksdb", - "strum 0.26.2", + "strum 0.26.3", "tempfile", "thiserror", ] @@ -2287,7 +2314,7 @@ dependencies = [ [[package]] name = "grovedb-visualize" version = "1.0.0-rc.2" -source = "git+https://github.com/dashpay/grovedb?branch=feat/QuerySumTree#0b32606fd4983899ca2b5865299f04b1a0accc98" +source = "git+https://github.com/dashpay/grovedb?branch=feat/QuerySumTree#1696c2ef47a674be5ec213b9ff723afe4c45fb90" dependencies = [ "hex", "itertools 0.12.1", @@ -2420,6 +2447,15 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3011d1213f159867b13cfd6ac92d2cd5f1345762c63be3554e84092d85a50bbd" +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest", +] + [[package]] name = "home" version = "0.5.9" @@ -2619,124 +2655,6 @@ dependencies = [ "cc", ] -[[package]] -name = "icu_collections" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" -dependencies = [ - "displaydoc", - "yoke", - "zerofrom", - "zerovec", -] - -[[package]] -name = "icu_locid" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" -dependencies = [ - "displaydoc", - "litemap", - "tinystr", - "writeable", - "zerovec", -] - -[[package]] -name = "icu_locid_transform" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" -dependencies = [ - "displaydoc", - "icu_locid", - "icu_locid_transform_data", - "icu_provider", - "tinystr", - "zerovec", -] - -[[package]] -name = "icu_locid_transform_data" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e" - -[[package]] -name = "icu_normalizer" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" -dependencies = [ - "displaydoc", - "icu_collections", - "icu_normalizer_data", - "icu_properties", - "icu_provider", - "smallvec", - "utf16_iter", - "utf8_iter", - "write16", - "zerovec", -] - -[[package]] -name = "icu_normalizer_data" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516" - -[[package]] -name = "icu_properties" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f8ac670d7422d7f76b32e17a5db556510825b29ec9154f235977c9caba61036" -dependencies = [ - "displaydoc", - "icu_collections", - "icu_locid_transform", - "icu_properties_data", - "icu_provider", - "tinystr", - "zerovec", -] - -[[package]] -name = "icu_properties_data" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569" - -[[package]] -name = "icu_provider" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" -dependencies = [ - "displaydoc", - "icu_locid", - "icu_provider_macros", - "stable_deref_trait", - "tinystr", - "writeable", - "yoke", - "zerofrom", - "zerovec", -] - -[[package]] -name = "icu_provider_macros" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.66", -] - [[package]] name = "ident_case" version = "1.0.1" @@ -2745,14 +2663,12 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" [[package]] name = "idna" -version = "1.0.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4716a3a0933a1d01c2f72450e89596eb51dd34ef3c211ccd875acdf1f8fe47ed" +checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" dependencies = [ - "icu_normalizer", - "icu_properties", - "smallvec", - "utf8_iter", + "unicode-bidi", + "unicode-normalization", ] [[package]] @@ -2777,6 +2693,15 @@ dependencies = [ "serde", ] +[[package]] +name = "inout" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" +dependencies = [ + "generic-array", +] + [[package]] name = "instant" version = "0.1.13" @@ -2995,9 +2920,9 @@ dependencies = [ [[package]] name = "lazy_static" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "lazycell" @@ -3025,9 +2950,9 @@ checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" [[package]] name = "libloading" -version = "0.8.3" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19" +checksum = "e310b3a6b5907f99202fcdb4960ff45b93735d7c7d96b760fcff8db2dc0e103d" dependencies = [ "cfg-if", "windows-targets 0.52.5", @@ -3039,7 +2964,7 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "libc", ] @@ -3082,12 +3007,6 @@ version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" -[[package]] -name = "litemap" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "643cb0b8d4fcc284004d5fd0d67ccf61dfffadb7f75e1e71bc420f4688a3a704" - [[package]] name = "lock_api" version = "0.4.12" @@ -3446,7 +3365,7 @@ checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -3559,7 +3478,7 @@ version = "0.10.64" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95a0481286a310808298130d22dd1fef0fa571e05a8f44ec801801e84b216b1f" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "cfg-if", "foreign-types", "libc", @@ -3576,7 +3495,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -3632,12 +3551,35 @@ dependencies = [ "windows-targets 0.52.5", ] +[[package]] +name = "password-hash" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7676374caaee8a325c9e7a2ae557f216c5563a171d6997b0ef8a65af35147700" +dependencies = [ + "base64ct", + "rand_core", + "subtle", +] + [[package]] name = "paste" version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" +[[package]] +name = "pbkdf2" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917" +dependencies = [ + "digest", + "hmac", + "password-hash", + "sha2", +] + [[package]] name = "peeking_take_while" version = "0.1.2" @@ -3677,7 +3619,7 @@ checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -3722,7 +3664,7 @@ version = "1.0.0-dev.15" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", "virtue 0.0.14", ] @@ -3752,7 +3694,7 @@ name = "platform-value-convertible" version = "1.0.0-dev.15" dependencies = [ "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -3768,15 +3710,9 @@ version = "1.0.0-dev.15" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] -[[package]] -name = "platforms" -version = "3.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db23d408679286588f4d4644f965003d056e3dd5abcaaa938116871d7ce2fee7" - [[package]] name = "plotters" version = "0.3.6" @@ -3902,7 +3838,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f12335488a2f3b0a83b14edad48dca9879ce89b2edd10e80237e4e852dd645e" dependencies = [ "proc-macro2", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -3950,9 +3886,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.85" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22244ce15aa966053a896d1accb3a6e68469b97c7f33f284b99f0d576879fc23" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" dependencies = [ "unicode-ident", ] @@ -4016,7 +3952,7 @@ dependencies = [ "prost 0.12.6", "prost-types 0.12.6", "regex", - "syn 2.0.66", + "syn 2.0.68", "tempfile", ] @@ -4043,7 +3979,7 @@ dependencies = [ "itertools 0.12.1", "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -4099,7 +4035,7 @@ version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57206b407293d2bcd3af849ce869d52068623f19e1b5ff8e8778e3309439682b" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "memchr", "unicase", ] @@ -4195,7 +4131,7 @@ version = "11.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e29830cbb1290e404f24c73af91c5d8d631ce7e128691e9477556b540cd01ecd" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", ] [[package]] @@ -4224,7 +4160,7 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c82cf8cff14456045f55ec4241383baeff27af886adb72ffb2162f99911de0fd" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", ] [[package]] @@ -4462,7 +4398,7 @@ version = "0.38.34" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "errno", "itoa", "libc", @@ -4613,7 +4549,7 @@ version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c627723fd09706bacdb5cf41499e95098555af3c3c29d014dc3c458ef6be11c0" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "core-foundation", "core-foundation-sys", "libc", @@ -4660,9 +4596,9 @@ dependencies = [ [[package]] name = "serde_bytes" -version = "0.11.14" +version = "0.11.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b8497c313fd43ab992087548117643f6fcd935cbf36f176ffda0aacf9591734" +checksum = "387cc504cb06bb40a96c8e04e951fe01854cf6bc921053c954e4a606d9675c6a" dependencies = [ "serde", ] @@ -4685,14 +4621,14 @@ checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] name = "serde_json" -version = "1.0.117" +version = "1.0.118" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "455182ea6142b14f93f4bc5320a2b31c1f266b66a4a5c858b013302a5d8cbfc3" +checksum = "d947f6b3163d8857ea16c4fa0dd4840d52f3041039a85decd46867eb1abef2e4" dependencies = [ "indexmap 2.2.6", "itoa", @@ -4708,7 +4644,7 @@ checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -4761,7 +4697,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -4773,7 +4709,18 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", +] + +[[package]] +name = "sha1" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", ] [[package]] @@ -4980,9 +4927,9 @@ dependencies = [ [[package]] name = "strum" -version = "0.26.2" +version = "0.26.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d8cec3501a5194c432b2b7976db6b7d10ec95c253208b45f83f7136aa985e29" +checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" dependencies = [ "strum_macros 0.26.4", ] @@ -4997,7 +4944,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -5010,14 +4957,14 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] name = "subtle" -version = "2.5.0" +version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "subtle-encoding" @@ -5041,9 +4988,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.66" +version = "2.0.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c42f3f41a2de00b01c0aaad383c5a45241efc8b2d1eda5661812fda5f3cdcff5" +checksum = "901fa70d88b9d6c98022e23b4136f9f3e54e4662c3bc1bd1d84a42a9a0f0c1e9" dependencies = [ "proc-macro2", "quote", @@ -5059,7 +5006,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -5080,24 +5027,13 @@ dependencies = [ "unicode-xid", ] -[[package]] -name = "synstructure" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.66", -] - [[package]] name = "system-interface" version = "0.26.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0682e006dd35771e392a6623ac180999a9a854b1d4a6c12fb2e804941c2b1f58" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "cap-fs-ext", "cap-std", "fd-lock", @@ -5139,8 +5075,8 @@ dependencies = [ [[package]] name = "tenderdash-abci" -version = "0.14.0-dev.12" -source = "git+https://github.com/dashpay/rs-tenderdash-abci#3048c2ecdf7a2bd023634082a85635c76db22bf0" +version = "1.0.0-dev.1" +source = "git+https://github.com/dashpay/rs-tenderdash-abci#cfb6ae41b4100c4b0af88ad1a201c5266a2ddc8c" dependencies = [ "bytes", "futures", @@ -5161,8 +5097,8 @@ dependencies = [ [[package]] name = "tenderdash-proto" -version = "0.14.0-dev.12" -source = "git+https://github.com/dashpay/rs-tenderdash-abci#3048c2ecdf7a2bd023634082a85635c76db22bf0" +version = "1.0.0-dev.1" +source = "git+https://github.com/dashpay/rs-tenderdash-abci#cfb6ae41b4100c4b0af88ad1a201c5266a2ddc8c" dependencies = [ "bytes", "chrono", @@ -5181,8 +5117,8 @@ dependencies = [ [[package]] name = "tenderdash-proto-compiler" -version = "0.14.0-dev.12" -source = "git+https://github.com/dashpay/rs-tenderdash-abci#3048c2ecdf7a2bd023634082a85635c76db22bf0" +version = "1.0.0-dev.1" +source = "git+https://github.com/dashpay/rs-tenderdash-abci#cfb6ae41b4100c4b0af88ad1a201c5266a2ddc8c" dependencies = [ "fs_extra", "prost-build 0.12.6", @@ -5257,7 +5193,7 @@ checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -5301,16 +5237,6 @@ dependencies = [ "time-core", ] -[[package]] -name = "tinystr" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" -dependencies = [ - "displaydoc", - "zerovec", -] - [[package]] name = "tinytemplate" version = "1.2.1" @@ -5323,9 +5249,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.6.0" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +checksum = "c55115c6fbe2d2bef26eb09ad74bde02d8255476fc0c7b515ef09fbb35742d82" dependencies = [ "tinyvec_macros", ] @@ -5374,7 +5300,7 @@ checksum = "5f5ae998a069d4b5aba8ee9dad856af7d520c3699e6159b185c2acd48155d39a" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -5573,7 +5499,7 @@ dependencies = [ "proc-macro2", "prost-build 0.12.6", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -5625,7 +5551,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -5713,12 +5639,27 @@ dependencies = [ "version_check", ] +[[package]] +name = "unicode-bidi" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" + [[package]] name = "unicode-ident" version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +[[package]] +name = "unicode-normalization" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" +dependencies = [ + "tinyvec", +] + [[package]] name = "unicode-width" version = "0.1.13" @@ -5756,27 +5697,15 @@ dependencies = [ [[package]] name = "url" -version = "2.5.1" +version = "2.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7c25da092f0a868cdf09e8674cd3b7ef3a7d92a24253e663a2fb85e2496de56" +checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" dependencies = [ "form_urlencoded", "idna", "percent-encoding", ] -[[package]] -name = "utf16_iter" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" - -[[package]] -name = "utf8_iter" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" - [[package]] name = "utf8parse" version = "0.2.2" @@ -5785,9 +5714,9 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" -version = "1.8.0" +version = "1.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a183cf7feeba97b4dd1c0d46788634f6221d87fa961b305bed08c851829efcc0" +checksum = "5de17fd2f7da591098415cff336e12965a28061ddace43b59cb3c430179c9439" dependencies = [ "getrandom", "rand", @@ -5884,7 +5813,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d888b611fee7d273dd057dc009d2dd3132736f36710ffd65657ac83628d1e3b" dependencies = [ "anyhow", - "bitflags 2.5.0", + "bitflags 2.6.0", "cap-rand", "cap-std", "io-extras", @@ -5918,7 +5847,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", "wasm-bindgen-shared", ] @@ -5952,7 +5881,7 @@ checksum = "e128beba882dd1eb6200e1dc92ae6c5dbaa4311aa7bb211ca035779e5efc39f8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -6195,7 +6124,7 @@ checksum = "f55c5565959287c21dd0f4277ae3518dd2ae62679f655ee2dbc4396e19d210db" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -6272,7 +6201,7 @@ checksum = "0afb26cd3269289bb314a361ff0a6685e5ce793b62181a9fe3f81ace15051697" dependencies = [ "anyhow", "async-trait", - "bitflags 2.5.0", + "bitflags 2.6.0", "thiserror", "tracing", "wasmtime", @@ -6290,7 +6219,7 @@ dependencies = [ "proc-macro2", "quote", "shellexpand", - "syn 2.0.66", + "syn 2.0.68", "witx", ] @@ -6302,7 +6231,7 @@ checksum = "31ae1ec11a17ea481539ee9a5719a278c9790d974060fbf71db4b2c05378780b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", "wiggle-generate", ] @@ -6509,7 +6438,7 @@ version = "0.36.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f9643b83820c0cd246ecabe5fa454dd04ba4fa67996369466d0747472d337346" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "windows-sys 0.52.0", ] @@ -6538,18 +6467,6 @@ dependencies = [ "wast", ] -[[package]] -name = "write16" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" - -[[package]] -name = "writeable" -version = "0.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" - [[package]] name = "wyz" version = "0.5.1" @@ -6565,30 +6482,6 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec" -[[package]] -name = "yoke" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c5b1314b079b0930c31e3af543d8ee1757b1951ae1e1565ec704403a7240ca5" -dependencies = [ - "serde", - "stable_deref_trait", - "yoke-derive", - "zerofrom", -] - -[[package]] -name = "yoke-derive" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28cc31741b18cb6f1d5ff12f5b7523e3d6eb0852bbbad19d73905511d9849b95" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.66", - "synstructure 0.13.1", -] - [[package]] name = "zerocopy" version = "0.7.34" @@ -6606,68 +6499,61 @@ checksum = "15e934569e47891f7d9411f1a451d947a60e000ab3bd24fbb970f000387d1b3b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] -name = "zerofrom" -version = "0.1.4" +name = "zeroize" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91ec111ce797d0e0784a1116d0ddcdbea84322cd79e5d5ad173daeba4f93ab55" -dependencies = [ - "zerofrom-derive", -] +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" [[package]] -name = "zerofrom-derive" -version = "0.1.4" +name = "zip" +version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ea7b4a3637ea8669cedf0f1fd5c286a17f3de97b8dd5a70a6c167a1730e63a5" +checksum = "760394e246e4c28189f19d488c058bf16f564016aefac5d32bb1f3b51d5e9261" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.66", - "synstructure 0.13.1", + "aes", + "byteorder", + "bzip2", + "constant_time_eq 0.1.5", + "crc32fast", + "crossbeam-utils", + "flate2", + "hmac", + "pbkdf2", + "sha1", + "time", + "zstd", ] [[package]] -name = "zeroize" -version = "1.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" - -[[package]] -name = "zerovec" -version = "0.10.2" +name = "zip-extensions" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb2cc8827d6c0994478a15c53f374f46fbd41bea663d809b14744bc42e6b109c" +checksum = "cecf62554c4ff96bce01a7ef123d160c3ffe9180638820f8b4d545c65b221b8c" dependencies = [ - "yoke", - "zerofrom", - "zerovec-derive", + "zip", ] [[package]] -name = "zerovec-derive" -version = "0.10.2" +name = "zstd" +version = "0.11.2+zstd.1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97cf56601ee5052b4417d90c8755c6683473c926039908196cf35d99f893ebe7" +checksum = "20cc960326ece64f010d2d2107537f26dc589a6573a316bd5b1dba685fa5fde4" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.66", + "zstd-safe", ] [[package]] -name = "zip" -version = "0.6.6" +name = "zstd-safe" +version = "5.0.2+zstd.1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "760394e246e4c28189f19d488c058bf16f564016aefac5d32bb1f3b51d5e9261" +checksum = "1d2a5585e04f9eea4b2a3d1eca508c4dee9592a89ef6f450c11719da0726f4db" dependencies = [ - "byteorder", - "crc32fast", - "crossbeam-utils", - "flate2", + "libc", + "zstd-sys", ] [[package]] diff --git a/packages/dapi-grpc/Cargo.toml b/packages/dapi-grpc/Cargo.toml index 21e63ea3e3e..085300789d1 100644 --- a/packages/dapi-grpc/Cargo.toml +++ b/packages/dapi-grpc/Cargo.toml @@ -42,7 +42,7 @@ tonic = { version = "0.11", features = [ serde = { version = "1.0.197", optional = true, features = ["derive"] } serde_bytes = { version = "0.11.12", optional = true } serde_json = { version = "1.0", optional = true } -tenderdash-proto = { git = "https://github.com/dashpay/rs-tenderdash-abci", version = "0.14.0-dev.12", default-features = false } +tenderdash-proto = { git = "https://github.com/dashpay/rs-tenderdash-abci", version = "1.0.0-dev.1", default-features = false } dapi-grpc-macros = { path = "../rs-dapi-grpc-macros" } platform-version = { path = "../rs-platform-version" } diff --git a/packages/rs-dpp/src/voting/contender_structs/mod.rs b/packages/rs-dpp/src/voting/contender_structs/mod.rs index 61e5ed2d58f..3d7756a5ad7 100644 --- a/packages/rs-dpp/src/voting/contender_structs/mod.rs +++ b/packages/rs-dpp/src/voting/contender_structs/mod.rs @@ -10,6 +10,7 @@ use platform_value::string_encoding::Encoding; use platform_value::Identifier; use platform_version::version::PlatformVersion; use std::fmt; +use std::fmt::format; pub use contender::v0::{ContenderV0, ContenderWithSerializedDocumentV0}; pub use contender::{Contender, ContenderWithSerializedDocument}; @@ -38,15 +39,15 @@ pub struct FinalizedContenderWithSerializedDocument { pub struct FinalizedResourceVoteChoicesWithVoterInfo { /// The resource vote choice. pub resource_vote_choice: ResourceVoteChoice, - /// The pro_tx_hashes of the voters for this contender. - pub voters: Vec, + /// The pro_tx_hashes of the voters for this contender along with their strength + pub voters: Vec<(Identifier, u8)>, } impl fmt::Display for FinalizedResourceVoteChoicesWithVoterInfo { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let voters_str: Vec = self .voters .iter() - .map(|v| v.to_string(Encoding::Base58)) + .map(|(id, strength)| format!("{}:{}", id, strength)) .collect(); write!( f, diff --git a/packages/rs-dpp/src/voting/vote_info_storage/contested_document_vote_poll_stored_info/mod.rs b/packages/rs-dpp/src/voting/vote_info_storage/contested_document_vote_poll_stored_info/mod.rs index e50b5c54774..12eb2b400cc 100644 --- a/packages/rs-dpp/src/voting/vote_info_storage/contested_document_vote_poll_stored_info/mod.rs +++ b/packages/rs-dpp/src/voting/vote_info_storage/contested_document_vote_poll_stored_info/mod.rs @@ -166,7 +166,7 @@ impl ContestedDocumentVotePollStoredInfoV0Getters for ContestedDocumentVotePollS } } - fn last_locked_voters(&self) -> Option> { + fn last_locked_voters(&self) -> Option> { match self { ContestedDocumentVotePollStoredInfo::V0(v0) => v0.last_locked_voters(), } @@ -178,7 +178,7 @@ impl ContestedDocumentVotePollStoredInfoV0Getters for ContestedDocumentVotePollS } } - fn last_abstain_voters(&self) -> Option> { + fn last_abstain_voters(&self) -> Option> { match self { ContestedDocumentVotePollStoredInfo::V0(v0) => v0.last_abstain_voters(), } diff --git a/packages/rs-dpp/src/voting/vote_info_storage/contested_document_vote_poll_stored_info/v0/mod.rs b/packages/rs-dpp/src/voting/vote_info_storage/contested_document_vote_poll_stored_info/v0/mod.rs index dc1d425daa9..b7fe690994a 100644 --- a/packages/rs-dpp/src/voting/vote_info_storage/contested_document_vote_poll_stored_info/v0/mod.rs +++ b/packages/rs-dpp/src/voting/vote_info_storage/contested_document_vote_poll_stored_info/v0/mod.rs @@ -147,11 +147,11 @@ pub trait ContestedDocumentVotePollStoredInfoV0Getters { fn last_locked_votes(&self) -> Option; - fn last_locked_voters(&self) -> Option>; + fn last_locked_voters(&self) -> Option>; fn last_abstain_votes(&self) -> Option; - fn last_abstain_voters(&self) -> Option>; + fn last_abstain_voters(&self) -> Option>; fn contender_votes_in_vec_of_contender_with_serialized_document( &self, ) -> Option>; @@ -218,12 +218,19 @@ impl ContestedDocumentVotePollStoredInfoV0Getters for ContestedDocumentVotePollS .filter(|choice| { matches!(choice.resource_vote_choice, ResourceVoteChoice::Lock) }) - .map(|choice| choice.voters.len() as u32) + .map(|choice| { + let sum: u32 = choice + .voters + .iter() + .map(|(_, strength)| *strength as u32) + .sum(); + sum + }) .sum() }) } - fn last_locked_voters(&self) -> Option> { + fn last_locked_voters(&self) -> Option> { self.last_resource_vote_choices() .map(|resource_vote_choices| { resource_vote_choices @@ -244,12 +251,19 @@ impl ContestedDocumentVotePollStoredInfoV0Getters for ContestedDocumentVotePollS .filter(|choice| { matches!(choice.resource_vote_choice, ResourceVoteChoice::Abstain) }) - .map(|choice| choice.voters.len() as u32) + .map(|choice| { + let sum: u32 = choice + .voters + .iter() + .map(|(_, strength)| *strength as u32) + .sum(); + sum + }) .sum() }) } - fn last_abstain_voters(&self) -> Option> { + fn last_abstain_voters(&self) -> Option> { self.last_resource_vote_choices() .map(|resource_vote_choices| { resource_vote_choices @@ -273,11 +287,16 @@ impl ContestedDocumentVotePollStoredInfoV0Getters for ContestedDocumentVotePollS if let ResourceVoteChoice::TowardsIdentity(identity_id) = &choice.resource_vote_choice { + let vote_tally: u32 = choice + .voters + .iter() + .map(|(_, strength)| *strength as u32) + .sum(); Some( ContenderWithSerializedDocumentV0 { identity_id: *identity_id, serialized_document: None, - vote_tally: Some(choice.voters.len() as u32), + vote_tally: Some(vote_tally), } .into(), ) diff --git a/packages/rs-drive-abci/Cargo.toml b/packages/rs-drive-abci/Cargo.toml index 40b131f2124..5d759599614 100644 --- a/packages/rs-drive-abci/Cargo.toml +++ b/packages/rs-drive-abci/Cargo.toml @@ -55,7 +55,7 @@ tracing-subscriber = { version = "0.3.16", default-features = false, features = "tracing-log", ], optional = false } atty = { version = "0.2.14", optional = false } -tenderdash-abci = { git = "https://github.com/dashpay/rs-tenderdash-abci", version = "0.14.0-dev.12", features = [ +tenderdash-abci = { git = "https://github.com/dashpay/rs-tenderdash-abci", version = "1.0.0-dev.1", features = [ "grpc", ] } lazy_static = "1.4.0" diff --git a/packages/rs-drive-abci/src/execution/engine/run_block_proposal/v0/mod.rs b/packages/rs-drive-abci/src/execution/engine/run_block_proposal/v0/mod.rs index 4b6d62ef4a6..f77c5ea16ad 100644 --- a/packages/rs-drive-abci/src/execution/engine/run_block_proposal/v0/mod.rs +++ b/packages/rs-drive-abci/src/execution/engine/run_block_proposal/v0/mod.rs @@ -294,6 +294,17 @@ where platform_version, )?; + // Run all dao platform events, such as vote tallying and distribution of contested documents + // This must be done before state transition processing + // Otherwise we would expect a proof after a successful vote that has since been cleaned up. + self.run_dao_platform_events( + &block_info, + last_committed_platform_state, + &block_platform_state, + Some(transaction), + platform_version, + )?; + // Process transactions let state_transitions_result = self.process_raw_state_transitions( raw_state_transitions, @@ -313,16 +324,6 @@ where platform_version, )?; - // Run all dao platform events, such as vote tallying and distribution of contested documents - - self.run_dao_platform_events( - &block_info, - last_committed_platform_state, - &block_platform_state, - Some(transaction), - platform_version, - )?; - // Create a new block execution context let mut block_execution_context: BlockExecutionContext = diff --git a/packages/rs-drive-abci/src/execution/platform_events/voting/check_for_ended_vote_polls/mod.rs b/packages/rs-drive-abci/src/execution/platform_events/voting/check_for_ended_vote_polls/mod.rs index 2b27616301c..6bb08f7facb 100644 --- a/packages/rs-drive-abci/src/execution/platform_events/voting/check_for_ended_vote_polls/mod.rs +++ b/packages/rs-drive-abci/src/execution/platform_events/voting/check_for_ended_vote_polls/mod.rs @@ -1,6 +1,7 @@ use crate::error::execution::ExecutionError; use crate::error::Error; use crate::platform_types::platform::Platform; +use crate::platform_types::platform_state::PlatformState; use crate::rpc::core::CoreRPCLike; use dpp::block::block_info::BlockInfo; use dpp::version::PlatformVersion; @@ -15,6 +16,7 @@ where /// Checks for ended vote polls pub(in crate::execution) fn check_for_ended_vote_polls( &self, + block_platform_state: &PlatformState, block_info: &BlockInfo, transaction: TransactionArg, platform_version: &PlatformVersion, @@ -25,7 +27,12 @@ where .voting .check_for_ended_vote_polls { - 0 => self.check_for_ended_vote_polls_v0(block_info, transaction, platform_version), + 0 => self.check_for_ended_vote_polls_v0( + block_platform_state, + block_info, + transaction, + platform_version, + ), version => Err(Error::Execution(ExecutionError::UnknownVersionMismatch { method: "check_for_ended_vote_polls".to_string(), known_versions: vec![0], diff --git a/packages/rs-drive-abci/src/execution/platform_events/voting/check_for_ended_vote_polls/v0/mod.rs b/packages/rs-drive-abci/src/execution/platform_events/voting/check_for_ended_vote_polls/v0/mod.rs index 761d113fba1..ca84b637298 100644 --- a/packages/rs-drive-abci/src/execution/platform_events/voting/check_for_ended_vote_polls/v0/mod.rs +++ b/packages/rs-drive-abci/src/execution/platform_events/voting/check_for_ended_vote_polls/v0/mod.rs @@ -1,5 +1,6 @@ use crate::error::Error; use crate::platform_types::platform::Platform; +use crate::platform_types::platform_state::PlatformState; use crate::rpc::core::CoreRPCLike; use dpp::block::block_info::BlockInfo; use dpp::document::DocumentV0Getters; @@ -23,6 +24,7 @@ where #[inline(always)] pub(super) fn check_for_ended_vote_polls_v0( &self, + block_platform_state: &PlatformState, block_info: &BlockInfo, transaction: TransactionArg, platform_version: &PlatformVersion, @@ -69,27 +71,23 @@ where let (contenders_with_votes, contenders_with_no_votes) : (Vec<_>, Vec<_>) = sorted_contenders.iter().partition(|a| a.final_vote_tally > 0); - let (restrict_to_only_fetch_contenders, mut other_contenders) = if contenders_with_no_votes.is_empty() + let fetch_contenders = contenders_with_votes + .iter() + .map(|contender| contender.identity_id) + .collect::>(); + let mut other_contenders = if contenders_with_no_votes.is_empty() { - (None, BTreeMap::new()) + BTreeMap::new() } else { - // Collect all identity_ids from contenders_with_votes - let restrict_to_only_fetch_contenders = Some( - contenders_with_votes - .iter() - .map(|contender| contender.identity_id) - .collect::>(), - ); - // Other contenders are only those with no votes - (restrict_to_only_fetch_contenders, contenders_with_no_votes.into_iter().map(|contender| (TowardsIdentity(contender.identity_id), vec![])).collect()) + contenders_with_no_votes.into_iter().map(|contender| (TowardsIdentity(contender.identity_id), vec![])).collect() }; // We need to get the votes of the sorted contenders let mut identifiers_voting_for_contenders = self.drive.fetch_identities_voting_for_contenders( &resolved_contested_document_resource_vote_poll, - restrict_to_only_fetch_contenders, + fetch_contenders, true, transaction, platform_version, @@ -156,6 +154,7 @@ where }; // We want to keep a record of how everyone voted self.keep_record_of_finished_contested_resource_vote_poll( + block_platform_state, block_info, &resolved_contested_document_resource_vote_poll, &identifiers_voting_for_contenders, diff --git a/packages/rs-drive-abci/src/execution/platform_events/voting/keep_record_of_vote_poll/mod.rs b/packages/rs-drive-abci/src/execution/platform_events/voting/keep_record_of_vote_poll/mod.rs index 9e8bb69e0ec..b5743cbf504 100644 --- a/packages/rs-drive-abci/src/execution/platform_events/voting/keep_record_of_vote_poll/mod.rs +++ b/packages/rs-drive-abci/src/execution/platform_events/voting/keep_record_of_vote_poll/mod.rs @@ -1,6 +1,7 @@ use crate::error::execution::ExecutionError; use crate::error::Error; use crate::platform_types::platform::Platform; +use crate::platform_types::platform_state::PlatformState; use crate::rpc::core::CoreRPCLike; use dpp::block::block_info::BlockInfo; use dpp::identifier::Identifier; @@ -20,6 +21,7 @@ where /// Keeps a record of the vote poll after it has finished pub(in crate::execution) fn keep_record_of_finished_contested_resource_vote_poll( &self, + block_platform_state: &PlatformState, block_info: &BlockInfo, vote_poll: &ContestedDocumentResourceVotePollWithContractInfo, contender_votes: &BTreeMap>, @@ -34,6 +36,7 @@ where .keep_record_of_finished_contested_resource_vote_poll { 0 => self.keep_record_of_finished_contested_resource_vote_poll_v0( + block_platform_state, block_info, vote_poll, contender_votes, diff --git a/packages/rs-drive-abci/src/execution/platform_events/voting/keep_record_of_vote_poll/v0/mod.rs b/packages/rs-drive-abci/src/execution/platform_events/voting/keep_record_of_vote_poll/v0/mod.rs index 2e1cbd0eb92..1b3214a5fe1 100644 --- a/packages/rs-drive-abci/src/execution/platform_events/voting/keep_record_of_vote_poll/v0/mod.rs +++ b/packages/rs-drive-abci/src/execution/platform_events/voting/keep_record_of_vote_poll/v0/mod.rs @@ -1,8 +1,15 @@ use crate::error::Error; use crate::platform_types::platform::Platform; +use crate::platform_types::platform_state::v0::PlatformStateV0Methods; +use crate::platform_types::platform_state::PlatformState; use crate::rpc::core::CoreRPCLike; +use dashcore_rpc::dashcore_rpc_json::MasternodeType; use dpp::block::block_info::BlockInfo; +use dpp::consensus::state::voting::masternode_not_found_error::MasternodeNotFoundError; +use dpp::dashcore::hashes::Hash; +use dpp::dashcore::ProTxHash; use dpp::identifier::Identifier; +use dpp::prelude::ConsensusValidationResult; use dpp::version::PlatformVersion; use dpp::voting::contender_structs::FinalizedResourceVoteChoicesWithVoterInfo; use dpp::voting::vote_choices::resource_vote_choice::ResourceVoteChoice; @@ -20,6 +27,7 @@ where #[inline(always)] pub(super) fn keep_record_of_finished_contested_resource_vote_poll_v0( &self, + block_platform_state: &PlatformState, block_info: &BlockInfo, vote_poll: &ContestedDocumentResourceVotePollWithContractInfo, contender_votes: &BTreeMap>, @@ -29,12 +37,30 @@ where ) -> Result<(), Error> { let finalized_resource_vote_choices_with_voter_infos = contender_votes .iter() - .map( - |(resource_vote_choice, voters)| FinalizedResourceVoteChoicesWithVoterInfo { - resource_vote_choice: resource_vote_choice.clone(), - voters: voters.clone(), - }, - ) + .map(|(resource_vote_choice, voters)| { + let full_masternode_list = block_platform_state.full_masternode_list(); + let voters = voters + .iter() + .map(|pro_tx_hash_identifier| { + let strength = if let Some(masternode) = full_masternode_list.get( + &ProTxHash::from_byte_array(pro_tx_hash_identifier.to_buffer()), + ) { + match masternode.node_type { + MasternodeType::Regular => 1, + MasternodeType::Evo => 4, + } + } else { + 0 + }; + (*pro_tx_hash_identifier, strength) + }) + .collect(); + + FinalizedResourceVoteChoicesWithVoterInfo { + resource_vote_choice: *resource_vote_choice, + voters, + } + }) .collect(); let stored_info_from_disk = self .drive diff --git a/packages/rs-drive-abci/src/execution/platform_events/voting/run_dao_platform_events/v0/mod.rs b/packages/rs-drive-abci/src/execution/platform_events/voting/run_dao_platform_events/v0/mod.rs index e8375654df1..817067f58c0 100644 --- a/packages/rs-drive-abci/src/execution/platform_events/voting/run_dao_platform_events/v0/mod.rs +++ b/packages/rs-drive-abci/src/execution/platform_events/voting/run_dao_platform_events/v0/mod.rs @@ -29,7 +29,12 @@ where // Check for any vote polls that might have ended - self.check_for_ended_vote_polls(block_info, transaction, platform_version)?; + self.check_for_ended_vote_polls( + block_platform_state, + block_info, + transaction, + platform_version, + )?; Ok(()) } diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/documents_batch/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/documents_batch/mod.rs index 7db6b4eadb8..abc066b643d 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/documents_batch/mod.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/documents_batch/mod.rs @@ -929,10 +929,13 @@ mod tests { fast_forward_to_block(&platform, 2_000_000_000, 900); //more than two weeks + let platform_state = platform.state.load(); + let transaction = platform.drive.grove.start_transaction(); platform .check_for_ended_vote_polls( + &platform_state, &BlockInfo { time_ms: 2_000_000_000, height: 900, diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/masternode_vote/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/masternode_vote/mod.rs index 25f6f026def..77173b24cf9 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/masternode_vote/mod.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/masternode_vote/mod.rs @@ -5431,7 +5431,12 @@ mod tests { let transaction = platform.drive.grove.start_transaction(); platform - .check_for_ended_vote_polls(&block_info, Some(&transaction), platform_version) + .check_for_ended_vote_polls( + &platform_state, + &block_info, + Some(&transaction), + platform_version, + ) .expect("expected to check for ended vote polls"); platform @@ -5633,7 +5638,12 @@ mod tests { let transaction = platform.drive.grove.start_transaction(); platform - .check_for_ended_vote_polls(&block_info, Some(&transaction), platform_version) + .check_for_ended_vote_polls( + &platform_state, + &block_info, + Some(&transaction), + platform_version, + ) .expect("expected to check for ended vote polls"); platform @@ -5835,7 +5845,12 @@ mod tests { let transaction = platform.drive.grove.start_transaction(); platform - .check_for_ended_vote_polls(&block_info, Some(&transaction), platform_version) + .check_for_ended_vote_polls( + &platform_state, + &block_info, + Some(&transaction), + platform_version, + ) .expect("expected to check for ended vote polls"); platform @@ -6032,7 +6047,12 @@ mod tests { let transaction = platform.drive.grove.start_transaction(); platform - .check_for_ended_vote_polls(&block_info, Some(&transaction), platform_version) + .check_for_ended_vote_polls( + &platform_state, + &block_info, + Some(&transaction), + platform_version, + ) .expect("expected to check for ended vote polls"); platform @@ -6220,7 +6240,12 @@ mod tests { let transaction = platform.drive.grove.start_transaction(); platform - .check_for_ended_vote_polls(&block_info, Some(&transaction), platform_version) + .check_for_ended_vote_polls( + &platform_state, + &block_info, + Some(&transaction), + platform_version, + ) .expect("expected to check for ended vote polls"); platform @@ -6422,7 +6447,12 @@ mod tests { let transaction = platform.drive.grove.start_transaction(); platform - .check_for_ended_vote_polls(&block_info, Some(&transaction), platform_version) + .check_for_ended_vote_polls( + &platform_state, + &block_info, + Some(&transaction), + platform_version, + ) .expect("expected to check for ended vote polls"); platform @@ -6524,6 +6554,372 @@ mod tests { assert_eq!(locking, Some(60)); } } + + #[test] + fn test_new_vote_after_document_distribution() { + let platform_version = PlatformVersion::latest(); + let mut platform = TestPlatformBuilder::new() + .build_with_mock_rpc() + .set_genesis_state(); + + let platform_state = platform.state.load(); + + let (contender_1, contender_2, dpns_contract) = create_dpns_name_contest( + &mut platform, + &platform_state, + 7, + "quantum", + platform_version, + ); + + perform_votes_multi( + &mut platform, + dpns_contract.as_ref(), + vec![ + (TowardsIdentity(contender_1.id()), 50), + (TowardsIdentity(contender_2.id()), 5), + (ResourceVoteChoice::Abstain, 10), + (ResourceVoteChoice::Lock, 3), + ], + "quantum", + 10, + platform_version, + ); + + let platform_state = platform.state.load(); + + let (contenders, abstaining, locking, finished_vote_info) = get_vote_states( + &platform, + &platform_state, + &dpns_contract, + "quantum", + None, + true, + None, + ResultType::DocumentsAndVoteTally, + platform_version, + ); + + assert_eq!(finished_vote_info, None); + + assert_eq!(contenders.len(), 2); + + let first_contender = contenders.first().unwrap(); + + let second_contender = contenders.last().unwrap(); + + assert_ne!(first_contender.document(), second_contender.document()); + + assert_eq!(first_contender.identity_id(), contender_1.id()); + + assert_eq!(second_contender.identity_id(), contender_2.id()); + + assert_eq!(first_contender.vote_tally(), Some(50)); + + assert_eq!(second_contender.vote_tally(), Some(5)); + + assert_eq!(abstaining, Some(10)); + + assert_eq!(locking, Some(3)); + + let mut platform_state = (**platform_state).clone(); + + let block_info = BlockInfo { + time_ms: 1_209_900_000, //2 weeks and 300s + height: 10000, + core_height: 42, + epoch: Default::default(), + }; + + platform_state.set_last_committed_block_info(Some( + ExtendedBlockInfoV0 { + basic_info: block_info, + app_hash: platform.drive.grove.root_hash(None).unwrap().unwrap(), + quorum_hash: [0u8; 32], + block_id_hash: [0u8; 32], + signature: [0u8; 96], + round: 0, + } + .into(), + )); + + platform.state.store(Arc::new(platform_state)); + + let platform_state = platform.state.load(); + + let transaction = platform.drive.grove.start_transaction(); + + platform + .check_for_ended_vote_polls( + &platform_state, + &block_info, + Some(&transaction), + platform_version, + ) + .expect("expected to check for ended vote polls"); + + platform + .drive + .grove + .commit_transaction(transaction) + .unwrap() + .expect("expected to commit transaction"); + + // At this point the document should have been awarded to contender 1. + + // now let's try to do another vote + + let (pro_tx_hash, _masternode, signer, voting_key) = + setup_masternode_identity(&mut platform, 5000, platform_version); + + let platform_state = platform.state.load(); + + perform_vote( + &mut platform, + &platform_state, + dpns_contract.as_ref(), + TowardsIdentity(contender_1.id()), + "quantum", + &signer, + pro_tx_hash, + &voting_key, + 2, + Some("VotePoll ContestedDocumentResourceVotePoll(ContestedDocumentResourceVotePoll { contract_id: GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec, document_type_name: domain, index_name: parentNameAndLabel, index_values: [string dash, string quantum] }) not available for voting: Awarded(BjNejy4r9QAvLHpQ9Yq6yRMgNymeGZ46d48fJxJbMrfW)"), + platform_version, + ); + + { + let (contenders, abstaining, locking, finished_vote_info) = get_vote_states( + &platform, + &platform_state, + &dpns_contract, + "quantum", + None, + true, + None, + ResultType::DocumentsAndVoteTally, + platform_version, + ); + + assert_eq!( + finished_vote_info, + Some(FinishedVoteInfo { + finished_vote_outcome: + finished_vote_info::FinishedVoteOutcome::TowardsIdentity as i32, + won_by_identity_id: Some(contender_1.id().to_vec()), + finished_at_block_height: 10000, + finished_at_core_block_height: 42, + finished_at_block_time_ms: 1209900000, + finished_at_epoch: 0 + }) + ); + + assert_eq!(contenders.len(), 2); + + let first_contender = contenders.first().unwrap(); + + let second_contender = contenders.last().unwrap(); + + assert_eq!(first_contender.document(), &None); + + assert_eq!(second_contender.document(), &None); + + assert_eq!(first_contender.identity_id(), contender_1.id()); + + assert_eq!(second_contender.identity_id(), contender_2.id()); + + assert_eq!(first_contender.vote_tally(), Some(50)); + + assert_eq!(second_contender.vote_tally(), Some(5)); + + assert_eq!(abstaining, Some(10)); + + assert_eq!(locking, Some(3)); + } + } + + #[test] + fn test_new_vote_after_lock() { + let platform_version = PlatformVersion::latest(); + let mut platform = TestPlatformBuilder::new() + .build_with_mock_rpc() + .set_genesis_state(); + + let platform_state = platform.state.load(); + + let (contender_1, contender_2, dpns_contract) = create_dpns_name_contest( + &mut platform, + &platform_state, + 7, + "quantum", + platform_version, + ); + + perform_votes_multi( + &mut platform, + dpns_contract.as_ref(), + vec![ + (TowardsIdentity(contender_1.id()), 2), + (TowardsIdentity(contender_2.id()), 5), + (ResourceVoteChoice::Abstain, 10), + (ResourceVoteChoice::Lock, 50), + ], + "quantum", + 10, + platform_version, + ); + + let platform_state = platform.state.load(); + + let (contenders, abstaining, locking, finished_vote_info) = get_vote_states( + &platform, + &platform_state, + &dpns_contract, + "quantum", + None, + true, + None, + ResultType::DocumentsAndVoteTally, + platform_version, + ); + + assert_eq!(finished_vote_info, None); + + assert_eq!(contenders.len(), 2); + + let first_contender = contenders.first().unwrap(); + + let second_contender = contenders.last().unwrap(); + + assert_ne!(first_contender.document(), second_contender.document()); + + assert_eq!(first_contender.identity_id(), contender_1.id()); + + assert_eq!(second_contender.identity_id(), contender_2.id()); + + assert_eq!(first_contender.vote_tally(), Some(2)); + + assert_eq!(second_contender.vote_tally(), Some(5)); + + assert_eq!(abstaining, Some(10)); + + assert_eq!(locking, Some(50)); + + let mut platform_state = (**platform_state).clone(); + + let block_info = BlockInfo { + time_ms: 1_209_900_000, //2 weeks and 300s + height: 10000, + core_height: 42, + epoch: Default::default(), + }; + + platform_state.set_last_committed_block_info(Some( + ExtendedBlockInfoV0 { + basic_info: block_info, + app_hash: platform.drive.grove.root_hash(None).unwrap().unwrap(), + quorum_hash: [0u8; 32], + block_id_hash: [0u8; 32], + signature: [0u8; 96], + round: 0, + } + .into(), + )); + + platform.state.store(Arc::new(platform_state)); + + let platform_state = platform.state.load(); + + let transaction = platform.drive.grove.start_transaction(); + + platform + .check_for_ended_vote_polls( + &platform_state, + &block_info, + Some(&transaction), + platform_version, + ) + .expect("expected to check for ended vote polls"); + + platform + .drive + .grove + .commit_transaction(transaction) + .unwrap() + .expect("expected to commit transaction"); + + // At this point the document should have been awarded to contender 1. + + // now let's try to do another vote + + let (pro_tx_hash, _masternode, signer, voting_key) = + setup_masternode_identity(&mut platform, 5000, platform_version); + + let platform_state = platform.state.load(); + + perform_vote( + &mut platform, + &platform_state, + dpns_contract.as_ref(), + TowardsIdentity(contender_1.id()), + "quantum", + &signer, + pro_tx_hash, + &voting_key, + 2, + Some("VotePoll ContestedDocumentResourceVotePoll(ContestedDocumentResourceVotePoll { contract_id: GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec, document_type_name: domain, index_name: parentNameAndLabel, index_values: [string dash, string quantum] }) not available for voting: Locked"), + platform_version, + ); + + { + let (contenders, abstaining, locking, finished_vote_info) = get_vote_states( + &platform, + &platform_state, + &dpns_contract, + "quantum", + None, + true, + None, + ResultType::DocumentsAndVoteTally, + platform_version, + ); + + assert_eq!( + finished_vote_info, + Some(FinishedVoteInfo { + finished_vote_outcome: finished_vote_info::FinishedVoteOutcome::Locked + as i32, + won_by_identity_id: None, + finished_at_block_height: 10000, + finished_at_core_block_height: 42, + finished_at_block_time_ms: 1209900000, + finished_at_epoch: 0 + }) + ); + + assert_eq!(contenders.len(), 2); + + let first_contender = contenders.first().unwrap(); + + let second_contender = contenders.last().unwrap(); + + assert_eq!(first_contender.document(), &None); + + assert_eq!(second_contender.document(), &None); + + assert_eq!(first_contender.identity_id(), contender_1.id()); + + assert_eq!(second_contender.identity_id(), contender_2.id()); + + assert_eq!(first_contender.vote_tally(), Some(2)); + + assert_eq!(second_contender.vote_tally(), Some(5)); + + assert_eq!(abstaining, Some(10)); + + assert_eq!(locking, Some(50)); + } + } } mod changing_vote { use super::*; @@ -6903,7 +7299,12 @@ mod tests { let transaction = platform.drive.grove.start_transaction(); platform - .check_for_ended_vote_polls(&block_info, Some(&transaction), platform_version) + .check_for_ended_vote_polls( + &platform_state, + &block_info, + Some(&transaction), + platform_version, + ) .expect("expected to check for ended vote polls"); platform diff --git a/packages/rs-drive-abci/src/query/proofs/v0/mod.rs b/packages/rs-drive-abci/src/query/proofs/v0/mod.rs index 161461e96aa..e82980bdf34 100644 --- a/packages/rs-drive-abci/src/query/proofs/v0/mod.rs +++ b/packages/rs-drive-abci/src/query/proofs/v0/mod.rs @@ -169,9 +169,13 @@ impl Platform { mod tests { use super::*; use crate::query::tests::{assert_invalid_identifier, setup_platform}; + use dapi_grpc::platform::v0::get_proofs_request::get_proofs_request_v0::vote_status_request::ContestedResourceVoteStatusRequest; use dapi_grpc::platform::v0::get_proofs_request::get_proofs_request_v0::{ - ContractRequest, DocumentRequest, IdentityRequest, + ContractRequest, DocumentRequest, IdentityRequest, VoteStatusRequest, }; + use dpp::data_contract::accessors::v0::DataContractV0Getters; + use dpp::platform_value::Value; + use dpp::util::strings::convert_to_homograph_safe_chars; #[test] fn test_invalid_identity_ids() { @@ -318,6 +322,58 @@ mod tests { }) if !proof.grovedb_proof.is_empty())); } + #[test] + fn test_proof_of_absence_of_vote() { + let (platform, state, version) = setup_platform(false); + + let dpns_contract = platform + .drive + .cache + .system_data_contracts + .load_dpns() + .as_ref() + .clone(); + + let config = bincode::config::standard() + .with_big_endian() + .with_no_limit(); + let serialized_index_values = [ + Value::Text("dash".to_string()), + Value::Text(convert_to_homograph_safe_chars("quantum")), + ] + .iter() + .map(|value| { + bincode::encode_to_vec(value, config).expect("expected to encode value in path") + }) + .collect(); + + let request = GetProofsRequestV0 { + identities: vec![], + contracts: vec![], + documents: vec![], + votes: vec![VoteStatusRequest { + request_type: Some(RequestType::ContestedResourceVoteStatusRequest( + ContestedResourceVoteStatusRequest { + contract_id: dpns_contract.id().to_vec(), + document_type_name: "domain".to_string(), + index_name: "parentNameAndLabel".to_string(), + index_values: serialized_index_values, + voter_identifier: [0u8; 32].to_vec(), + }, + )), + }], + }; + + let validation_result = platform + .query_proofs_v0(request, &state, version) + .expect("expected query to succeed"); + + assert!(matches!(validation_result.data, Some(GetProofsResponseV0 { + result: Some(get_proofs_response_v0::Result::Proof(proof)), + metadata: Some(_), + }) if !proof.grovedb_proof.is_empty())); + } + #[test] fn test_prove_all() { let (platform, state, version) = setup_platform(false); diff --git a/packages/rs-drive-abci/tests/strategy_tests/verify_state_transitions.rs b/packages/rs-drive-abci/tests/strategy_tests/verify_state_transitions.rs index f97721c4633..a2ed5728daf 100644 --- a/packages/rs-drive-abci/tests/strategy_tests/verify_state_transitions.rs +++ b/packages/rs-drive-abci/tests/strategy_tests/verify_state_transitions.rs @@ -23,7 +23,9 @@ use drive_abci::rpc::core::MockCoreRPCLike; use tenderdash_abci::proto::abci::ExecTxResult; use dpp::state_transition::documents_batch_transition::accessors::DocumentsBatchTransitionAccessorsV0; +use dpp::voting::votes::resource_vote::accessors::v0::ResourceVoteGettersV0; use dpp::voting::votes::Vote; +use drive::drive::verify::RootHash; use drive::drive::votes::resolved::vote_polls::ResolvedVotePoll; use drive::drive::votes::resolved::votes::resolved_resource_vote::accessors::v0::ResolvedResourceVoteGettersV0; use drive::drive::votes::resolved::votes::ResolvedVote; @@ -554,7 +556,7 @@ pub(crate) fn verify_state_transitions_were_or_were_not_executed( false, platform_version, ) - .expect("expected to verify balance identity"); + .expect("expected to verify balance identity for top up"); let balance = balance.expect("expected a balance"); assert_eq!( &root_hash, @@ -616,7 +618,7 @@ pub(crate) fn verify_state_transitions_were_or_were_not_executed( false, platform_version, ) - .expect("expected to verify balance identity"); + .expect("expected to verify balance identity for withdrawal"); let _balance = balance.expect("expected a balance"); assert_eq!( &root_hash, @@ -717,7 +719,7 @@ pub(crate) fn verify_state_transitions_were_or_were_not_executed( true, platform_version, ) - .expect("expected to verify balance identity"); + .expect("expected to verify balance identity for credit transfer"); assert_eq!( &root_hash_identity, @@ -806,7 +808,7 @@ pub(crate) fn verify_state_transitions_were_or_were_not_executed( masternode_vote_action.pro_tx_hash().into_buffer(), &vote, data_contract, - true, + false, // we are not in a subset, we have just one vote platform_version, ) .expect("expected to verify balance identity"); diff --git a/packages/rs-drive-abci/tests/strategy_tests/voting_tests.rs b/packages/rs-drive-abci/tests/strategy_tests/voting_tests.rs index 52e34820f0c..83eddeea27c 100644 --- a/packages/rs-drive-abci/tests/strategy_tests/voting_tests.rs +++ b/packages/rs-drive-abci/tests/strategy_tests/voting_tests.rs @@ -20,9 +20,12 @@ mod tests { use dapi_grpc::platform::v0::get_contested_resource_vote_state_request::get_contested_resource_vote_state_request_v0::ResultType; use dapi_grpc::platform::v0::get_contested_resource_vote_state_request::GetContestedResourceVoteStateRequestV0; use dapi_grpc::platform::v0::get_contested_resource_vote_state_response::{get_contested_resource_vote_state_response_v0, GetContestedResourceVoteStateResponseV0}; + use dapi_grpc::platform::v0::get_contested_resource_vote_state_response::get_contested_resource_vote_state_response_v0::{finished_vote_info, FinishedVoteInfo}; + use dapi_grpc::platform::v0::get_contested_resource_vote_state_response::get_contested_resource_vote_state_response_v0::finished_vote_info::FinishedVoteOutcome; use dpp::block::extended_block_info::v0::ExtendedBlockInfoV0Getters; use dpp::data_contract::document_type::accessors::DocumentTypeV0Getters; use dpp::voting::vote_choices::resource_vote_choice::ResourceVoteChoice; + use drive::drive::config::DriveConfig; use drive::drive::object_size_info::DataContractOwnedResolvedInfo; use drive::drive::votes::resolved::vote_polls::contested_document_resource_vote_poll::ContestedDocumentResourceVotePollWithContractInfo; use drive_abci::platform_types::platform_state::v0::PlatformStateV0Methods; @@ -588,7 +591,7 @@ mod tests { rotate_quorums: false, failure_testing: None, query_testing: None, - verify_state_transition_results: false, + verify_state_transition_results: true, ..Default::default() }, config.clone(), @@ -944,7 +947,7 @@ mod tests { rotate_quorums: false, failure_testing: None, query_testing: None, - verify_state_transition_results: false, + verify_state_transition_results: true, ..Default::default() }, config.clone(), @@ -1038,4 +1041,387 @@ mod tests { assert_eq!(finished_vote_info, None); } + + #[test] + fn run_chain_with_voting_on_conflicting_index_distribution_after_won_by_identity() { + // In this test we try to insert two state transitions with the same unique index + // We use the DPNS contract, and we insert two documents both with the same "name" + // This is a common scenario we should see quite often + let config = PlatformConfig { + validator_set_quorum_size: 100, + validator_set_quorum_type: "llmq_100_67".to_string(), + chain_lock_quorum_type: "llmq_100_67".to_string(), + execution: ExecutionConfig { + //we disable document triggers because we are using dpns and dpns needs a preorder + use_document_triggers: false, + validator_set_rotation_block_count: 25, + ..Default::default() + }, + block_spacing_ms: 3000, + ..Default::default() + }; + let mut platform = TestPlatformBuilder::new() + .with_config(config.clone()) + .build_with_mock_rpc(); + + let platform_version = PlatformVersion::latest(); + + let mut rng = StdRng::seed_from_u64(567); + + let mut simple_signer = SimpleSigner::default(); + + let (identity1, keys1) = + Identity::random_identity_with_main_keys_with_private_key::>( + 2, + &mut rng, + platform_version, + ) + .unwrap(); + + simple_signer.add_keys(keys1); + + let (identity2, keys2) = + Identity::random_identity_with_main_keys_with_private_key::>( + 2, + &mut rng, + platform_version, + ) + .unwrap(); + + simple_signer.add_keys(keys2); + + let start_identities = create_state_transitions_for_identities( + vec![identity1, identity2], + &simple_signer, + &mut rng, + platform_version, + ); + + let dpns_contract = platform + .drive + .cache + .system_data_contracts + .load_dpns() + .as_ref() + .clone(); + + let document_type = dpns_contract + .document_type_for_name("domain") + .expect("expected a profile document type") + .to_owned_document_type(); + + let identity1_id = start_identities.first().unwrap().0.id(); + let identity2_id = start_identities.last().unwrap().0.id(); + let document_op_1 = DocumentOp { + contract: dpns_contract.clone(), + action: DocumentAction::DocumentActionInsertSpecific( + BTreeMap::from([ + ("label".into(), "quantum".into()), + ("normalizedLabel".into(), "quantum".into()), + ("normalizedParentDomainName".into(), "dash".into()), + ( + "records".into(), + BTreeMap::from([("dashUniqueIdentityId", Value::from(identity1_id))]) + .into(), + ), + ]), + Some(start_identities.first().unwrap().0.id()), + DocumentFieldFillType::FillIfNotRequired, + DocumentFieldFillSize::AnyDocumentFillSize, + ), + document_type: document_type.clone(), + }; + + let document_op_2 = DocumentOp { + contract: dpns_contract.clone(), + action: DocumentAction::DocumentActionInsertSpecific( + BTreeMap::from([ + ("label".into(), "quantum".into()), + ("normalizedLabel".into(), "quantum".into()), + ("normalizedParentDomainName".into(), "dash".into()), + ( + "records".into(), + BTreeMap::from([( + "dashUniqueIdentityId", + Value::from(start_identities.last().unwrap().0.id()), + )]) + .into(), + ), + ]), + Some(start_identities.last().unwrap().0.id()), + DocumentFieldFillType::FillIfNotRequired, + DocumentFieldFillSize::AnyDocumentFillSize, + ), + document_type: document_type.clone(), + }; + + let strategy = NetworkStrategy { + strategy: Strategy { + start_contracts: vec![], + operations: vec![ + Operation { + op_type: OperationType::Document(document_op_1), + frequency: Frequency { + times_per_block_range: 1..2, + chance_per_block: None, + }, + }, + Operation { + op_type: OperationType::Document(document_op_2), + frequency: Frequency { + times_per_block_range: 1..2, + chance_per_block: None, + }, + }, + ], + start_identities: StartIdentities { + hard_coded: start_identities, + ..Default::default() + }, + identity_inserts: Default::default(), + + identity_contract_nonce_gaps: None, + signer: Some(simple_signer), + }, + total_hpmns: 100, + extra_normal_mns: 0, + validator_quorum_count: 24, + chain_lock_quorum_count: 24, + upgrading_info: None, + + proposer_strategy: Default::default(), + rotate_quorums: false, + failure_testing: None, + query_testing: None, + verify_state_transition_results: true, + ..Default::default() + }; + + let mut voting_signer = Some(SimpleSigner::default()); + + // On the first block we only have identities and contracts + let ChainExecutionOutcome { + abci_app, + proposers, + quorums, + current_quorum_hash, + current_proposer_versions, + end_time_ms, + identity_nonce_counter, + identity_contract_nonce_counter, + state_transition_results_per_block, + .. + } = run_chain_for_strategy( + &mut platform, + 2, + strategy.clone(), + config.clone(), + 15, + &mut voting_signer, + ); + + let platform = abci_app.platform; + + let platform_state = platform.state.load(); + + let state_transitions_block_2 = state_transition_results_per_block + .get(&2) + .expect("expected to get block 2"); + + let first_document_insert_result = &state_transitions_block_2 + .first() + .as_ref() + .expect("expected a document insert") + .1; + assert_eq!(first_document_insert_result.code, 0); + + let second_document_insert_result = &state_transitions_block_2 + .get(1) + .as_ref() + .expect("expected a document insert") + .1; + + assert_eq!(second_document_insert_result.code, 0); // we expect the second to also be insertable as they are both contested + + let block_start = platform_state + .last_committed_block_info() + .as_ref() + .unwrap() + .basic_info() + .height + + 1; + let day_in_ms = 1000 * 60 * 60 * 24; + let config = PlatformConfig { + validator_set_quorum_size: 100, + validator_set_quorum_type: "llmq_100_67".to_string(), + chain_lock_quorum_type: "llmq_100_67".to_string(), + execution: ExecutionConfig { + //we disable document triggers because we are using dpns and dpns needs a preorder + use_document_triggers: false, + validator_set_rotation_block_count: 25, + ..Default::default() + }, + block_spacing_ms: day_in_ms, + ..Default::default() + }; + + let outcome = continue_chain_for_strategy( + abci_app, + ChainExecutionParameters { + block_start, + core_height_start: 1, + block_count: 16, + proposers, + quorums, + current_quorum_hash, + current_proposer_versions: Some(current_proposer_versions.clone()), + current_identity_nonce_counter: identity_nonce_counter, + current_identity_contract_nonce_counter: identity_contract_nonce_counter, + current_votes: BTreeMap::default(), + start_time_ms: 1681094380000, + current_time_ms: end_time_ms, + }, + NetworkStrategy { + strategy: Strategy { + start_contracts: vec![], + operations: vec![Operation { + op_type: OperationType::ResourceVote(ResourceVoteOp { + resolved_vote_poll: ContestedDocumentResourceVotePollWithContractInfo { + contract: DataContractOwnedResolvedInfo::OwnedDataContract( + dpns_contract.clone(), + ), + document_type_name: "domain".to_string(), + index_name: "parentNameAndLabel".to_string(), + index_values: vec!["dash".into(), "quantum".into()], + }, + action: VoteAction { + vote_choices_with_weights: vec![ + (ResourceVoteChoice::Abstain, 1), + (ResourceVoteChoice::Lock, 1), + (ResourceVoteChoice::TowardsIdentity(identity1_id), 2), + (ResourceVoteChoice::TowardsIdentity(identity2_id), 10), + ], + }, + }), + frequency: Frequency { + times_per_block_range: 1..3, + chance_per_block: None, + }, + }], + start_identities: StartIdentities::default(), + identity_inserts: Default::default(), + + identity_contract_nonce_gaps: None, + signer: voting_signer, + }, + total_hpmns: 100, + extra_normal_mns: 0, + validator_quorum_count: 24, + chain_lock_quorum_count: 24, + upgrading_info: None, + + proposer_strategy: Default::default(), + rotate_quorums: false, + failure_testing: None, + query_testing: None, + verify_state_transition_results: true, + ..Default::default() + }, + config.clone(), + StrategyRandomness::SeedEntropy(9), + ); + + let platform = outcome.abci_app.platform; + + // Now let's run a query for the vote totals + + let config = bincode::config::standard() + .with_big_endian() + .with_no_limit(); + + let dash_encoded = bincode::encode_to_vec(Value::Text("dash".to_string()), config) + .expect("expected to encode the word dash"); + + let quantum_encoded = bincode::encode_to_vec(Value::Text("quantum".to_string()), config) + .expect("expected to encode the word quantum"); + + let index_name = "parentNameAndLabel".to_string(); + + let query_validation_result = platform + .query_contested_resource_vote_state( + GetContestedResourceVoteStateRequest { + version: Some(get_contested_resource_vote_state_request::Version::V0( + GetContestedResourceVoteStateRequestV0 { + contract_id: dpns_contract.id().to_vec(), + document_type_name: document_type.name().clone(), + index_name: index_name.clone(), + index_values: vec![dash_encoded.clone(), quantum_encoded.clone()], + result_type: ResultType::DocumentsAndVoteTally as i32, + allow_include_locked_and_abstaining_vote_tally: true, + start_at_identifier_info: None, + count: None, + prove: false, + }, + )), + }, + &platform_state, + platform_version, + ) + .expect("expected to execute query") + .into_data() + .expect("expected query to be valid"); + + let get_contested_resource_vote_state_response::Version::V0( + GetContestedResourceVoteStateResponseV0 { + metadata: _, + result, + }, + ) = query_validation_result.version.expect("expected a version"); + + let Some( + get_contested_resource_vote_state_response_v0::Result::ContestedResourceContenders( + get_contested_resource_vote_state_response_v0::ContestedResourceContenders { + contenders, + abstain_vote_tally, + lock_vote_tally, + finished_vote_info, + }, + ), + ) = result + else { + panic!("expected contenders") + }; + + assert_eq!(contenders.len(), 2); + + let first_contender = contenders.first().unwrap(); + + let second_contender = contenders.last().unwrap(); + + assert_eq!(first_contender.identifier, identity2_id.to_vec()); + + assert_eq!(second_contender.identifier, identity1_id.to_vec()); + + // All vote counts are weighted, so for evonodes, these are in multiples of 4 + + assert_eq!(first_contender.vote_count, Some(60)); + + assert_eq!(second_contender.vote_count, Some(4)); + + assert_eq!(lock_vote_tally, Some(4)); + + assert_eq!(abstain_vote_tally, Some(8)); + + assert_eq!( + finished_vote_info, + Some(FinishedVoteInfo { + finished_vote_outcome: FinishedVoteOutcome::TowardsIdentity.into(), + won_by_identity_id: Some(identity2_id.to_vec()), + finished_at_block_height: 17, + finished_at_core_block_height: 1, + finished_at_block_time_ms: 1682303986000, + finished_at_epoch: 1 + }) + ); + } } diff --git a/packages/rs-drive-proof-verifier/Cargo.toml b/packages/rs-drive-proof-verifier/Cargo.toml index 9ff302579f9..d8647821b8c 100644 --- a/packages/rs-drive-proof-verifier/Cargo.toml +++ b/packages/rs-drive-proof-verifier/Cargo.toml @@ -32,7 +32,7 @@ dpp = { path = "../rs-dpp", features = [ bincode = { version = "2.0.0-rc.3", features = ["serde"], optional = true } platform-serialization-derive = { path = "../rs-platform-serialization-derive", optional = true } platform-serialization = { path = "../rs-platform-serialization", optional = true } -tenderdash-abci = { git = "https://github.com/dashpay/rs-tenderdash-abci", version = "0.14.0-dev.12", features = [ +tenderdash-abci = { git = "https://github.com/dashpay/rs-tenderdash-abci", version = "1.0.0-dev.1", features = [ "crypto", ], default-features = false } tracing = { version = "0.1.37" } diff --git a/packages/rs-drive/src/drive/prove/prove_multiple_state_transition_results/v0/mod.rs b/packages/rs-drive/src/drive/prove/prove_multiple_state_transition_results/v0/mod.rs index 24972183258..05ec3e2c679 100644 --- a/packages/rs-drive/src/drive/prove/prove_multiple_state_transition_results/v0/mod.rs +++ b/packages/rs-drive/src/drive/prove/prove_multiple_state_transition_results/v0/mod.rs @@ -120,6 +120,7 @@ impl Drive { _ => true, }; let path_query = PathQuery::merge(path_queries.iter().collect()).map_err(Error::GroveDB)?; + self.grove_get_proved_path_query( &path_query, verbose, diff --git a/packages/rs-drive/src/drive/verify/voting/verify_masternode_vote/v0/mod.rs b/packages/rs-drive/src/drive/verify/voting/verify_masternode_vote/v0/mod.rs index d98691171b6..54034508d57 100644 --- a/packages/rs-drive/src/drive/verify/voting/verify_masternode_vote/v0/mod.rs +++ b/packages/rs-drive/src/drive/verify/voting/verify_masternode_vote/v0/mod.rs @@ -1,6 +1,7 @@ use crate::drive::Drive; use dpp::data_contract::DataContract; use grovedb::{GroveDb, PathQuery, SizedQuery}; +use tracing::debug; use crate::error::Error; diff --git a/packages/rs-drive/src/drive/votes/fetch/fetch_identities_voting_for_contenders/mod.rs b/packages/rs-drive/src/drive/votes/fetch/fetch_identities_voting_for_contenders/mod.rs index 734a66c8fa2..6337f21cf82 100644 --- a/packages/rs-drive/src/drive/votes/fetch/fetch_identities_voting_for_contenders/mod.rs +++ b/packages/rs-drive/src/drive/votes/fetch/fetch_identities_voting_for_contenders/mod.rs @@ -17,7 +17,7 @@ impl Drive { pub fn fetch_identities_voting_for_contenders( &self, contested_document_resource_vote_poll_with_contract_info: &ContestedDocumentResourceVotePollWithContractInfo, - restrict_to_only_fetch_contenders: Option>, + fetch_contenders: Vec, also_fetch_abstaining_and_locked_votes: bool, transaction: TransactionArg, platform_version: &PlatformVersion, @@ -31,7 +31,7 @@ impl Drive { { 0 => self.fetch_identities_voting_for_contenders_v0( contested_document_resource_vote_poll_with_contract_info, - restrict_to_only_fetch_contenders, + fetch_contenders, also_fetch_abstaining_and_locked_votes, transaction, platform_version, diff --git a/packages/rs-drive/src/drive/votes/fetch/fetch_identities_voting_for_contenders/v0/mod.rs b/packages/rs-drive/src/drive/votes/fetch/fetch_identities_voting_for_contenders/v0/mod.rs index cfccd890c11..4dcb5a98f10 100644 --- a/packages/rs-drive/src/drive/votes/fetch/fetch_identities_voting_for_contenders/v0/mod.rs +++ b/packages/rs-drive/src/drive/votes/fetch/fetch_identities_voting_for_contenders/v0/mod.rs @@ -18,7 +18,7 @@ impl Drive { pub fn fetch_identities_voting_for_contenders_v0( &self, contested_document_resource_vote_poll_with_contract_info: &ContestedDocumentResourceVotePollWithContractInfo, - restrict_to_only_fetch_contenders: Option>, + fetch_contenders: Vec, also_fetch_abstaining_and_locked_votes: bool, transaction: TransactionArg, platform_version: &PlatformVersion, @@ -28,23 +28,12 @@ impl Drive { let mut query = Query::new_with_direction(true); - if let Some(restrict_to_only_fetch_contenders) = restrict_to_only_fetch_contenders { - query.insert_keys( - restrict_to_only_fetch_contenders - .into_iter() - .map(|id| id.to_vec()) - .collect(), - ); - if also_fetch_abstaining_and_locked_votes { - query.insert_keys(vec![ - vec![RESOURCE_ABSTAIN_VOTE_TREE_KEY_U8], - vec![RESOURCE_LOCK_VOTE_TREE_KEY_U8], - ]); - } - } else if also_fetch_abstaining_and_locked_votes { - query.insert_range_after(vec![RESOURCE_STORED_INFO_KEY_U8]..) - } else { - query.insert_range_after(vec![RESOURCE_LOCK_VOTE_TREE_KEY_U8]..) + query.insert_keys(fetch_contenders.into_iter().map(|id| id.to_vec()).collect()); + if also_fetch_abstaining_and_locked_votes { + query.insert_keys(vec![ + vec![RESOURCE_ABSTAIN_VOTE_TREE_KEY_U8], + vec![RESOURCE_LOCK_VOTE_TREE_KEY_U8], + ]); } query.set_subquery_path(vec![vec![VOTING_STORAGE_TREE_KEY]]); From f546e537a649e72035ce193619a8400058fd20e0 Mon Sep 17 00:00:00 2001 From: Lukasz Klimek <842586+lklimek@users.noreply.github.com> Date: Thu, 27 Jun 2024 14:57:54 +0200 Subject: [PATCH 31/55] build: revert rs-tenderdash-abci to v0.14.0-dev.12 --- Cargo.lock | 34 +++++++++------------ packages/dapi-grpc/Cargo.toml | 2 +- packages/rs-drive-abci/Cargo.toml | 2 +- packages/rs-drive-proof-verifier/Cargo.toml | 2 +- 4 files changed, 17 insertions(+), 23 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 458b3b2e06c..da113745281 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -421,7 +421,7 @@ dependencies = [ "bitflags 2.6.0", "cexpr", "clang-sys", - "itertools 0.12.1", + "itertools 0.10.5", "lazy_static", "lazycell", "proc-macro2", @@ -2890,7 +2890,7 @@ source = "git+https://github.com/fominok/jsonschema-rs?branch=feat-unevaluated-p dependencies = [ "ahash 0.8.11", "anyhow", - "base64 0.22.1", + "base64 0.13.1", "bytecount", "fancy-regex", "fraction", @@ -2956,7 +2956,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e310b3a6b5907f99202fcdb4960ff45b93735d7c7d96b760fcff8db2dc0e103d" dependencies = [ "cfg-if", - "windows-targets 0.52.5", + "windows-targets 0.48.5", ] [[package]] @@ -3252,12 +3252,6 @@ version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a" -[[package]] -name = "multimap" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "defc4c55412d89136f966bbb339008b474350e5e6e78d2714439c386b3137a03" - [[package]] name = "murmur3" version = "0.5.2" @@ -3925,7 +3919,7 @@ dependencies = [ "itertools 0.10.5", "lazy_static", "log", - "multimap 0.8.3", + "multimap", "petgraph", "prettyplease 0.1.25", "prost 0.11.9", @@ -3943,10 +3937,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "22505a5c94da8e3b7c2996394d1c933236c4d743e81a410bcca4e6989fc066a4" dependencies = [ "bytes", - "heck 0.5.0", - "itertools 0.12.1", + "heck 0.4.1", + "itertools 0.10.5", "log", - "multimap 0.10.0", + "multimap", "once_cell", "petgraph", "prettyplease 0.2.20", @@ -3977,7 +3971,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "81bddcdb20abf9501610992b6759a4c888aef7d1a7247ef75e2404275ac24af1" dependencies = [ "anyhow", - "itertools 0.12.1", + "itertools 0.10.5", "proc-macro2", "quote", "syn 2.0.68", @@ -5076,8 +5070,8 @@ dependencies = [ [[package]] name = "tenderdash-abci" -version = "1.0.0-dev.1" -source = "git+https://github.com/dashpay/rs-tenderdash-abci#cfb6ae41b4100c4b0af88ad1a201c5266a2ddc8c" +version = "0.14.0-dev.12" +source = "git+https://github.com/dashpay/rs-tenderdash-abci?tag=v0.14.0-dev.12#17e57f509c2bb7015042d69976bd1f056fef923d" dependencies = [ "bytes", "futures", @@ -5098,8 +5092,8 @@ dependencies = [ [[package]] name = "tenderdash-proto" -version = "1.0.0-dev.1" -source = "git+https://github.com/dashpay/rs-tenderdash-abci#cfb6ae41b4100c4b0af88ad1a201c5266a2ddc8c" +version = "0.14.0-dev.12" +source = "git+https://github.com/dashpay/rs-tenderdash-abci?tag=v0.14.0-dev.12#17e57f509c2bb7015042d69976bd1f056fef923d" dependencies = [ "bytes", "chrono", @@ -5118,8 +5112,8 @@ dependencies = [ [[package]] name = "tenderdash-proto-compiler" -version = "1.0.0-dev.1" -source = "git+https://github.com/dashpay/rs-tenderdash-abci#cfb6ae41b4100c4b0af88ad1a201c5266a2ddc8c" +version = "0.14.0-dev.12" +source = "git+https://github.com/dashpay/rs-tenderdash-abci?tag=v0.14.0-dev.12#17e57f509c2bb7015042d69976bd1f056fef923d" dependencies = [ "fs_extra", "prost-build 0.12.6", diff --git a/packages/dapi-grpc/Cargo.toml b/packages/dapi-grpc/Cargo.toml index 085300789d1..dc80fcf6ab3 100644 --- a/packages/dapi-grpc/Cargo.toml +++ b/packages/dapi-grpc/Cargo.toml @@ -42,7 +42,7 @@ tonic = { version = "0.11", features = [ serde = { version = "1.0.197", optional = true, features = ["derive"] } serde_bytes = { version = "0.11.12", optional = true } serde_json = { version = "1.0", optional = true } -tenderdash-proto = { git = "https://github.com/dashpay/rs-tenderdash-abci", version = "1.0.0-dev.1", default-features = false } +tenderdash-proto = { git = "https://github.com/dashpay/rs-tenderdash-abci", version = "0.14.0-dev.12", tag = "v0.14.0-dev.12", default-features = false } dapi-grpc-macros = { path = "../rs-dapi-grpc-macros" } platform-version = { path = "../rs-platform-version" } diff --git a/packages/rs-drive-abci/Cargo.toml b/packages/rs-drive-abci/Cargo.toml index 5d759599614..5b95221b011 100644 --- a/packages/rs-drive-abci/Cargo.toml +++ b/packages/rs-drive-abci/Cargo.toml @@ -55,7 +55,7 @@ tracing-subscriber = { version = "0.3.16", default-features = false, features = "tracing-log", ], optional = false } atty = { version = "0.2.14", optional = false } -tenderdash-abci = { git = "https://github.com/dashpay/rs-tenderdash-abci", version = "1.0.0-dev.1", features = [ +tenderdash-abci = { git = "https://github.com/dashpay/rs-tenderdash-abci", version = "0.14.0-dev.12", tag = "v0.14.0-dev.12", features = [ "grpc", ] } lazy_static = "1.4.0" diff --git a/packages/rs-drive-proof-verifier/Cargo.toml b/packages/rs-drive-proof-verifier/Cargo.toml index d8647821b8c..5b29db2a529 100644 --- a/packages/rs-drive-proof-verifier/Cargo.toml +++ b/packages/rs-drive-proof-verifier/Cargo.toml @@ -32,7 +32,7 @@ dpp = { path = "../rs-dpp", features = [ bincode = { version = "2.0.0-rc.3", features = ["serde"], optional = true } platform-serialization-derive = { path = "../rs-platform-serialization-derive", optional = true } platform-serialization = { path = "../rs-platform-serialization", optional = true } -tenderdash-abci = { git = "https://github.com/dashpay/rs-tenderdash-abci", version = "1.0.0-dev.1", features = [ +tenderdash-abci = { git = "https://github.com/dashpay/rs-tenderdash-abci", version = "0.14.0-dev.12", tag = "v0.14.0-dev.12", features = [ "crypto", ], default-features = false } tracing = { version = "0.1.37" } From 522e3a1efb08d0faf7379ef3f2046b610f12fc1d Mon Sep 17 00:00:00 2001 From: Ivan Shumkov Date: Thu, 27 Jun 2024 23:05:10 +0700 Subject: [PATCH 32/55] fix: empty proofs are returned for masternode vote state transition --- Cargo.lock | 1 + .../platform/v0/nodejs/platform_pbjs.js | 27 ++-- .../platform/v0/nodejs/platform_protoc.js | 7 +- .../platform/v0/objective-c/Platform.pbobjc.h | 7 +- .../platform/v0/objective-c/Platform.pbobjc.m | 6 +- .../platform/v0/python/platform_pb2.py | 143 +++++++++--------- .../clients/platform/v0/web/platform_pb.d.ts | 7 +- .../clients/platform/v0/web/platform_pb.js | 7 +- .../fetchProofForStateTransitionFactory.js | 24 +++ ...etchProofForStateTransitionFactory.spec.js | 28 ++++ packages/wasm-dpp/Cargo.toml | 1 + .../masternode_vote_transition/mod.rs | 43 +++++- 12 files changed, 189 insertions(+), 112 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 453b23d7c3f..fd9441a0128 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5898,6 +5898,7 @@ version = "1.0.0-dev.15" dependencies = [ "anyhow", "async-trait", + "bincode 2.0.0-rc.3", "dpp", "hex", "itertools 0.10.5", diff --git a/packages/dapi-grpc/clients/platform/v0/nodejs/platform_pbjs.js b/packages/dapi-grpc/clients/platform/v0/nodejs/platform_pbjs.js index 73e77dccf6a..ad5b5842dd6 100644 --- a/packages/dapi-grpc/clients/platform/v0/nodejs/platform_pbjs.js +++ b/packages/dapi-grpc/clients/platform/v0/nodejs/platform_pbjs.js @@ -29722,7 +29722,6 @@ $root.org = (function() { case 0: case 1: case 2: - case 3: break; } if (message.allowIncludeLockedAndAbstainingVoteTally != null && message.hasOwnProperty("allowIncludeLockedAndAbstainingVoteTally")) @@ -29774,22 +29773,18 @@ $root.org = (function() { message.indexValues[i] = object.indexValues[i]; } switch (object.resultType) { - case "IDENTITY_IDS_ONLY": + case "DOCUMENTS": case 0: message.resultType = 0; break; - case "DOCUMENTS": + case "VOTE_TALLY": case 1: message.resultType = 1; break; - case "VOTE_TALLY": + case "DOCUMENTS_AND_VOTE_TALLY": case 2: message.resultType = 2; break; - case "DOCUMENTS_AND_VOTE_TALLY": - case 3: - message.resultType = 3; - break; } if (object.allowIncludeLockedAndAbstainingVoteTally != null) message.allowIncludeLockedAndAbstainingVoteTally = Boolean(object.allowIncludeLockedAndAbstainingVoteTally); @@ -29830,7 +29825,7 @@ $root.org = (function() { } object.documentTypeName = ""; object.indexName = ""; - object.resultType = options.enums === String ? "IDENTITY_IDS_ONLY" : 0; + object.resultType = options.enums === String ? "DOCUMENTS" : 0; object.allowIncludeLockedAndAbstainingVoteTally = false; object.startAtIdentifierInfo = null; object.count = 0; @@ -30094,17 +30089,15 @@ $root.org = (function() { * ResultType enum. * @name org.dash.platform.dapi.v0.GetContestedResourceVoteStateRequest.GetContestedResourceVoteStateRequestV0.ResultType * @enum {number} - * @property {number} IDENTITY_IDS_ONLY=0 IDENTITY_IDS_ONLY value - * @property {number} DOCUMENTS=1 DOCUMENTS value - * @property {number} VOTE_TALLY=2 VOTE_TALLY value - * @property {number} DOCUMENTS_AND_VOTE_TALLY=3 DOCUMENTS_AND_VOTE_TALLY value + * @property {number} DOCUMENTS=0 DOCUMENTS value + * @property {number} VOTE_TALLY=1 VOTE_TALLY value + * @property {number} DOCUMENTS_AND_VOTE_TALLY=2 DOCUMENTS_AND_VOTE_TALLY value */ GetContestedResourceVoteStateRequestV0.ResultType = (function() { var valuesById = {}, values = Object.create(valuesById); - values[valuesById[0] = "IDENTITY_IDS_ONLY"] = 0; - values[valuesById[1] = "DOCUMENTS"] = 1; - values[valuesById[2] = "VOTE_TALLY"] = 2; - values[valuesById[3] = "DOCUMENTS_AND_VOTE_TALLY"] = 3; + values[valuesById[0] = "DOCUMENTS"] = 0; + values[valuesById[1] = "VOTE_TALLY"] = 1; + values[valuesById[2] = "DOCUMENTS_AND_VOTE_TALLY"] = 2; return values; })(); diff --git a/packages/dapi-grpc/clients/platform/v0/nodejs/platform_protoc.js b/packages/dapi-grpc/clients/platform/v0/nodejs/platform_protoc.js index 62d8ac471c0..8d995602b92 100644 --- a/packages/dapi-grpc/clients/platform/v0/nodejs/platform_protoc.js +++ b/packages/dapi-grpc/clients/platform/v0/nodejs/platform_protoc.js @@ -29030,10 +29030,9 @@ proto.org.dash.platform.dapi.v0.GetContestedResourceVoteStateRequest.GetConteste * @enum {number} */ proto.org.dash.platform.dapi.v0.GetContestedResourceVoteStateRequest.GetContestedResourceVoteStateRequestV0.ResultType = { - IDENTITY_IDS_ONLY: 0, - DOCUMENTS: 1, - VOTE_TALLY: 2, - DOCUMENTS_AND_VOTE_TALLY: 3 + DOCUMENTS: 0, + VOTE_TALLY: 1, + DOCUMENTS_AND_VOTE_TALLY: 2 }; diff --git a/packages/dapi-grpc/clients/platform/v0/objective-c/Platform.pbobjc.h b/packages/dapi-grpc/clients/platform/v0/objective-c/Platform.pbobjc.h index 225d1d56119..a07c1ffef31 100644 --- a/packages/dapi-grpc/clients/platform/v0/objective-c/Platform.pbobjc.h +++ b/packages/dapi-grpc/clients/platform/v0/objective-c/Platform.pbobjc.h @@ -229,10 +229,9 @@ typedef GPB_ENUM(GetContestedResourceVoteStateRequest_GetContestedResourceVoteSt * of the field. **/ GetContestedResourceVoteStateRequest_GetContestedResourceVoteStateRequestV0_ResultType_GPBUnrecognizedEnumeratorValue = kGPBUnrecognizedEnumeratorValue, - GetContestedResourceVoteStateRequest_GetContestedResourceVoteStateRequestV0_ResultType_IdentityIdsOnly = 0, - GetContestedResourceVoteStateRequest_GetContestedResourceVoteStateRequestV0_ResultType_Documents = 1, - GetContestedResourceVoteStateRequest_GetContestedResourceVoteStateRequestV0_ResultType_VoteTally = 2, - GetContestedResourceVoteStateRequest_GetContestedResourceVoteStateRequestV0_ResultType_DocumentsAndVoteTally = 3, + GetContestedResourceVoteStateRequest_GetContestedResourceVoteStateRequestV0_ResultType_Documents = 0, + GetContestedResourceVoteStateRequest_GetContestedResourceVoteStateRequestV0_ResultType_VoteTally = 1, + GetContestedResourceVoteStateRequest_GetContestedResourceVoteStateRequestV0_ResultType_DocumentsAndVoteTally = 2, }; GPBEnumDescriptor *GetContestedResourceVoteStateRequest_GetContestedResourceVoteStateRequestV0_ResultType_EnumDescriptor(void); diff --git a/packages/dapi-grpc/clients/platform/v0/objective-c/Platform.pbobjc.m b/packages/dapi-grpc/clients/platform/v0/objective-c/Platform.pbobjc.m index 480be3f6720..a9c0cf03622 100644 --- a/packages/dapi-grpc/clients/platform/v0/objective-c/Platform.pbobjc.m +++ b/packages/dapi-grpc/clients/platform/v0/objective-c/Platform.pbobjc.m @@ -8176,10 +8176,9 @@ void SetGetContestedResourceVoteStateRequest_GetContestedResourceVoteStateReques static _Atomic(GPBEnumDescriptor*) descriptor = nil; if (!descriptor) { static const char *valueNames = - "IdentityIdsOnly\000Documents\000VoteTally\000Docu" - "mentsAndVoteTally\000"; + "Documents\000VoteTally\000DocumentsAndVoteTall" + "y\000"; static const int32_t values[] = { - GetContestedResourceVoteStateRequest_GetContestedResourceVoteStateRequestV0_ResultType_IdentityIdsOnly, GetContestedResourceVoteStateRequest_GetContestedResourceVoteStateRequestV0_ResultType_Documents, GetContestedResourceVoteStateRequest_GetContestedResourceVoteStateRequestV0_ResultType_VoteTally, GetContestedResourceVoteStateRequest_GetContestedResourceVoteStateRequestV0_ResultType_DocumentsAndVoteTally, @@ -8200,7 +8199,6 @@ void SetGetContestedResourceVoteStateRequest_GetContestedResourceVoteStateReques BOOL GetContestedResourceVoteStateRequest_GetContestedResourceVoteStateRequestV0_ResultType_IsValidValue(int32_t value__) { switch (value__) { - case GetContestedResourceVoteStateRequest_GetContestedResourceVoteStateRequestV0_ResultType_IdentityIdsOnly: case GetContestedResourceVoteStateRequest_GetContestedResourceVoteStateRequestV0_ResultType_Documents: case GetContestedResourceVoteStateRequest_GetContestedResourceVoteStateRequestV0_ResultType_VoteTally: case GetContestedResourceVoteStateRequest_GetContestedResourceVoteStateRequestV0_ResultType_DocumentsAndVoteTally: diff --git a/packages/dapi-grpc/clients/platform/v0/python/platform_pb2.py b/packages/dapi-grpc/clients/platform/v0/python/platform_pb2.py index 0b59441a9e8..8b4a2aa9bac 100644 --- a/packages/dapi-grpc/clients/platform/v0/python/platform_pb2.py +++ b/packages/dapi-grpc/clients/platform/v0/python/platform_pb2.py @@ -23,7 +23,7 @@ syntax='proto3', serialized_options=None, create_key=_descriptor._internal_create_key, - serialized_pb=b'\n\x0eplatform.proto\x12\x19org.dash.platform.dapi.v0\x1a\x1egoogle/protobuf/wrappers.proto\x1a\x1cgoogle/protobuf/struct.proto\x1a\x1fgoogle/protobuf/timestamp.proto\"\x81\x01\n\x05Proof\x12\x15\n\rgrovedb_proof\x18\x01 \x01(\x0c\x12\x13\n\x0bquorum_hash\x18\x02 \x01(\x0c\x12\x11\n\tsignature\x18\x03 \x01(\x0c\x12\r\n\x05round\x18\x04 \x01(\r\x12\x15\n\rblock_id_hash\x18\x05 \x01(\x0c\x12\x13\n\x0bquorum_type\x18\x06 \x01(\r\"\x90\x01\n\x10ResponseMetadata\x12\x0e\n\x06height\x18\x01 \x01(\x04\x12 \n\x18\x63ore_chain_locked_height\x18\x02 \x01(\r\x12\r\n\x05\x65poch\x18\x03 \x01(\r\x12\x0f\n\x07time_ms\x18\x04 \x01(\x04\x12\x18\n\x10protocol_version\x18\x05 \x01(\r\x12\x10\n\x08\x63hain_id\x18\x06 \x01(\t\"L\n\x1dStateTransitionBroadcastError\x12\x0c\n\x04\x63ode\x18\x01 \x01(\r\x12\x0f\n\x07message\x18\x02 \x01(\t\x12\x0c\n\x04\x64\x61ta\x18\x03 \x01(\x0c\";\n\x1f\x42roadcastStateTransitionRequest\x12\x18\n\x10state_transition\x18\x01 \x01(\x0c\"\"\n BroadcastStateTransitionResponse\"\xa4\x01\n\x12GetIdentityRequest\x12P\n\x02v0\x18\x01 \x01(\x0b\x32\x42.org.dash.platform.dapi.v0.GetIdentityRequest.GetIdentityRequestV0H\x00\x1a\x31\n\x14GetIdentityRequestV0\x12\n\n\x02id\x18\x01 \x01(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\xc1\x01\n\x17GetIdentityNonceRequest\x12Z\n\x02v0\x18\x01 \x01(\x0b\x32L.org.dash.platform.dapi.v0.GetIdentityNonceRequest.GetIdentityNonceRequestV0H\x00\x1a?\n\x19GetIdentityNonceRequestV0\x12\x13\n\x0bidentity_id\x18\x01 \x01(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\xf6\x01\n\x1fGetIdentityContractNonceRequest\x12j\n\x02v0\x18\x01 \x01(\x0b\x32\\.org.dash.platform.dapi.v0.GetIdentityContractNonceRequest.GetIdentityContractNonceRequestV0H\x00\x1a\\\n!GetIdentityContractNonceRequestV0\x12\x13\n\x0bidentity_id\x18\x01 \x01(\x0c\x12\x13\n\x0b\x63ontract_id\x18\x02 \x01(\x0c\x12\r\n\x05prove\x18\x03 \x01(\x08\x42\t\n\x07version\"\xc0\x01\n\x19GetIdentityBalanceRequest\x12^\n\x02v0\x18\x01 \x01(\x0b\x32P.org.dash.platform.dapi.v0.GetIdentityBalanceRequest.GetIdentityBalanceRequestV0H\x00\x1a\x38\n\x1bGetIdentityBalanceRequestV0\x12\n\n\x02id\x18\x01 \x01(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\xec\x01\n$GetIdentityBalanceAndRevisionRequest\x12t\n\x02v0\x18\x01 \x01(\x0b\x32\x66.org.dash.platform.dapi.v0.GetIdentityBalanceAndRevisionRequest.GetIdentityBalanceAndRevisionRequestV0H\x00\x1a\x43\n&GetIdentityBalanceAndRevisionRequestV0\x12\n\n\x02id\x18\x01 \x01(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\x9e\x02\n\x13GetIdentityResponse\x12R\n\x02v0\x18\x01 \x01(\x0b\x32\x44.org.dash.platform.dapi.v0.GetIdentityResponse.GetIdentityResponseV0H\x00\x1a\xa7\x01\n\x15GetIdentityResponseV0\x12\x12\n\x08identity\x18\x01 \x01(\x0cH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\xb8\x02\n\x18GetIdentityNonceResponse\x12\\\n\x02v0\x18\x01 \x01(\x0b\x32N.org.dash.platform.dapi.v0.GetIdentityNonceResponse.GetIdentityNonceResponseV0H\x00\x1a\xb2\x01\n\x1aGetIdentityNonceResponseV0\x12\x18\n\x0eidentity_nonce\x18\x01 \x01(\x04H\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\xe1\x02\n GetIdentityContractNonceResponse\x12l\n\x02v0\x18\x01 \x01(\x0b\x32^.org.dash.platform.dapi.v0.GetIdentityContractNonceResponse.GetIdentityContractNonceResponseV0H\x00\x1a\xc3\x01\n\"GetIdentityContractNonceResponseV0\x12!\n\x17identity_contract_nonce\x18\x01 \x01(\x04H\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\xb9\x02\n\x1aGetIdentityBalanceResponse\x12`\n\x02v0\x18\x01 \x01(\x0b\x32R.org.dash.platform.dapi.v0.GetIdentityBalanceResponse.GetIdentityBalanceResponseV0H\x00\x1a\xad\x01\n\x1cGetIdentityBalanceResponseV0\x12\x11\n\x07\x62\x61lance\x18\x01 \x01(\x04H\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\xa9\x04\n%GetIdentityBalanceAndRevisionResponse\x12v\n\x02v0\x18\x01 \x01(\x0b\x32h.org.dash.platform.dapi.v0.GetIdentityBalanceAndRevisionResponse.GetIdentityBalanceAndRevisionResponseV0H\x00\x1a\xfc\x02\n\'GetIdentityBalanceAndRevisionResponseV0\x12\x9b\x01\n\x14\x62\x61lance_and_revision\x18\x01 \x01(\x0b\x32{.org.dash.platform.dapi.v0.GetIdentityBalanceAndRevisionResponse.GetIdentityBalanceAndRevisionResponseV0.BalanceAndRevisionH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\x37\n\x12\x42\x61lanceAndRevision\x12\x0f\n\x07\x62\x61lance\x18\x01 \x01(\x04\x12\x10\n\x08revision\x18\x02 \x01(\x04\x42\x08\n\x06resultB\t\n\x07version\"\xd1\x01\n\x0eKeyRequestType\x12\x36\n\x08\x61ll_keys\x18\x01 \x01(\x0b\x32\".org.dash.platform.dapi.v0.AllKeysH\x00\x12@\n\rspecific_keys\x18\x02 \x01(\x0b\x32\'.org.dash.platform.dapi.v0.SpecificKeysH\x00\x12:\n\nsearch_key\x18\x03 \x01(\x0b\x32$.org.dash.platform.dapi.v0.SearchKeyH\x00\x42\t\n\x07request\"\t\n\x07\x41llKeys\"\x1f\n\x0cSpecificKeys\x12\x0f\n\x07key_ids\x18\x01 \x03(\r\"\xb6\x01\n\tSearchKey\x12I\n\x0bpurpose_map\x18\x01 \x03(\x0b\x32\x34.org.dash.platform.dapi.v0.SearchKey.PurposeMapEntry\x1a^\n\x0fPurposeMapEntry\x12\x0b\n\x03key\x18\x01 \x01(\r\x12:\n\x05value\x18\x02 \x01(\x0b\x32+.org.dash.platform.dapi.v0.SecurityLevelMap:\x02\x38\x01\"\xbf\x02\n\x10SecurityLevelMap\x12]\n\x12security_level_map\x18\x01 \x03(\x0b\x32\x41.org.dash.platform.dapi.v0.SecurityLevelMap.SecurityLevelMapEntry\x1aw\n\x15SecurityLevelMapEntry\x12\x0b\n\x03key\x18\x01 \x01(\r\x12M\n\x05value\x18\x02 \x01(\x0e\x32>.org.dash.platform.dapi.v0.SecurityLevelMap.KeyKindRequestType:\x02\x38\x01\"S\n\x12KeyKindRequestType\x12\x1f\n\x1b\x43URRENT_KEY_OF_KIND_REQUEST\x10\x00\x12\x1c\n\x18\x41LL_KEYS_OF_KIND_REQUEST\x10\x01\"\xda\x02\n\x16GetIdentityKeysRequest\x12X\n\x02v0\x18\x01 \x01(\x0b\x32J.org.dash.platform.dapi.v0.GetIdentityKeysRequest.GetIdentityKeysRequestV0H\x00\x1a\xda\x01\n\x18GetIdentityKeysRequestV0\x12\x13\n\x0bidentity_id\x18\x01 \x01(\x0c\x12?\n\x0crequest_type\x18\x02 \x01(\x0b\x32).org.dash.platform.dapi.v0.KeyRequestType\x12+\n\x05limit\x18\x03 \x01(\x0b\x32\x1c.google.protobuf.UInt32Value\x12,\n\x06offset\x18\x04 \x01(\x0b\x32\x1c.google.protobuf.UInt32Value\x12\r\n\x05prove\x18\x05 \x01(\x08\x42\t\n\x07version\"\x99\x03\n\x17GetIdentityKeysResponse\x12Z\n\x02v0\x18\x01 \x01(\x0b\x32L.org.dash.platform.dapi.v0.GetIdentityKeysResponse.GetIdentityKeysResponseV0H\x00\x1a\x96\x02\n\x19GetIdentityKeysResponseV0\x12\x61\n\x04keys\x18\x01 \x01(\x0b\x32Q.org.dash.platform.dapi.v0.GetIdentityKeysResponse.GetIdentityKeysResponseV0.KeysH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\x1a\n\x04Keys\x12\x12\n\nkeys_bytes\x18\x01 \x03(\x0c\x42\x08\n\x06resultB\t\n\x07version\"\xef\x02\n GetIdentitiesContractKeysRequest\x12l\n\x02v0\x18\x01 \x01(\x0b\x32^.org.dash.platform.dapi.v0.GetIdentitiesContractKeysRequest.GetIdentitiesContractKeysRequestV0H\x00\x1a\xd1\x01\n\"GetIdentitiesContractKeysRequestV0\x12\x16\n\x0eidentities_ids\x18\x01 \x03(\x0c\x12\x13\n\x0b\x63ontract_id\x18\x02 \x01(\x0c\x12\x1f\n\x12\x64ocument_type_name\x18\x03 \x01(\tH\x00\x88\x01\x01\x12\x37\n\x08purposes\x18\x04 \x03(\x0e\x32%.org.dash.platform.dapi.v0.KeyPurpose\x12\r\n\x05prove\x18\x05 \x01(\x08\x42\x15\n\x13_document_type_nameB\t\n\x07version\"\xdf\x06\n!GetIdentitiesContractKeysResponse\x12n\n\x02v0\x18\x01 \x01(\x0b\x32`.org.dash.platform.dapi.v0.GetIdentitiesContractKeysResponse.GetIdentitiesContractKeysResponseV0H\x00\x1a\xbe\x05\n#GetIdentitiesContractKeysResponseV0\x12\x8a\x01\n\x0fidentities_keys\x18\x01 \x01(\x0b\x32o.org.dash.platform.dapi.v0.GetIdentitiesContractKeysResponse.GetIdentitiesContractKeysResponseV0.IdentitiesKeysH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1aY\n\x0bPurposeKeys\x12\x36\n\x07purpose\x18\x01 \x01(\x0e\x32%.org.dash.platform.dapi.v0.KeyPurpose\x12\x12\n\nkeys_bytes\x18\x02 \x03(\x0c\x1a\x9f\x01\n\x0cIdentityKeys\x12\x13\n\x0bidentity_id\x18\x01 \x01(\x0c\x12z\n\x04keys\x18\x02 \x03(\x0b\x32l.org.dash.platform.dapi.v0.GetIdentitiesContractKeysResponse.GetIdentitiesContractKeysResponseV0.PurposeKeys\x1a\x90\x01\n\x0eIdentitiesKeys\x12~\n\x07\x65ntries\x18\x01 \x03(\x0b\x32m.org.dash.platform.dapi.v0.GetIdentitiesContractKeysResponse.GetIdentitiesContractKeysResponseV0.IdentityKeysB\x08\n\x06resultB\t\n\x07version\"\xcb\x0b\n\x10GetProofsRequest\x12L\n\x02v0\x18\x01 \x01(\x0b\x32>.org.dash.platform.dapi.v0.GetProofsRequest.GetProofsRequestV0H\x00\x1a\xdd\n\n\x12GetProofsRequestV0\x12\x62\n\nidentities\x18\x01 \x03(\x0b\x32N.org.dash.platform.dapi.v0.GetProofsRequest.GetProofsRequestV0.IdentityRequest\x12\x61\n\tcontracts\x18\x02 \x03(\x0b\x32N.org.dash.platform.dapi.v0.GetProofsRequest.GetProofsRequestV0.ContractRequest\x12\x61\n\tdocuments\x18\x03 \x03(\x0b\x32N.org.dash.platform.dapi.v0.GetProofsRequest.GetProofsRequestV0.DocumentRequest\x12_\n\x05votes\x18\x04 \x03(\x0b\x32P.org.dash.platform.dapi.v0.GetProofsRequest.GetProofsRequestV0.VoteStatusRequest\x1a\xd5\x02\n\x0f\x44ocumentRequest\x12\x13\n\x0b\x63ontract_id\x18\x01 \x01(\x0c\x12\x15\n\rdocument_type\x18\x02 \x01(\t\x12#\n\x1b\x64ocument_type_keeps_history\x18\x03 \x01(\x08\x12\x13\n\x0b\x64ocument_id\x18\x04 \x01(\x0c\x12\x89\x01\n\x19\x64ocument_contested_status\x18\x05 \x01(\x0e\x32\x66.org.dash.platform.dapi.v0.GetProofsRequest.GetProofsRequestV0.DocumentRequest.DocumentContestedStatus\"P\n\x17\x44ocumentContestedStatus\x12\x11\n\rNOT_CONTESTED\x10\x00\x12\x13\n\x0fMAYBE_CONTESTED\x10\x01\x12\r\n\tCONTESTED\x10\x02\x1a\xd1\x01\n\x0fIdentityRequest\x12\x13\n\x0bidentity_id\x18\x01 \x01(\x0c\x12i\n\x0crequest_type\x18\x02 \x01(\x0e\x32S.org.dash.platform.dapi.v0.GetProofsRequest.GetProofsRequestV0.IdentityRequest.Type\">\n\x04Type\x12\x11\n\rFULL_IDENTITY\x10\x00\x12\x0b\n\x07\x42\x41LANCE\x10\x01\x12\x08\n\x04KEYS\x10\x02\x12\x0c\n\x08REVISION\x10\x03\x1a&\n\x0f\x43ontractRequest\x12\x13\n\x0b\x63ontract_id\x18\x01 \x01(\x0c\x1a\xe7\x02\n\x11VoteStatusRequest\x12\xa5\x01\n&contested_resource_vote_status_request\x18\x01 \x01(\x0b\x32s.org.dash.platform.dapi.v0.GetProofsRequest.GetProofsRequestV0.VoteStatusRequest.ContestedResourceVoteStatusRequestH\x00\x1a\x99\x01\n\"ContestedResourceVoteStatusRequest\x12\x13\n\x0b\x63ontract_id\x18\x01 \x01(\x0c\x12\x1a\n\x12\x64ocument_type_name\x18\x02 \x01(\t\x12\x12\n\nindex_name\x18\x03 \x01(\t\x12\x14\n\x0cindex_values\x18\x04 \x03(\x0c\x12\x18\n\x10voter_identifier\x18\x05 \x01(\x0c\x42\x0e\n\x0crequest_typeB\t\n\x07version\"\x82\x02\n\x11GetProofsResponse\x12N\n\x02v0\x18\x01 \x01(\x0b\x32@.org.dash.platform.dapi.v0.GetProofsResponse.GetProofsResponseV0H\x00\x1a\x91\x01\n\x13GetProofsResponseV0\x12\x31\n\x05proof\x18\x01 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x02 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\xb4\x01\n\x16GetDataContractRequest\x12X\n\x02v0\x18\x01 \x01(\x0b\x32J.org.dash.platform.dapi.v0.GetDataContractRequest.GetDataContractRequestV0H\x00\x1a\x35\n\x18GetDataContractRequestV0\x12\n\n\x02id\x18\x01 \x01(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\xb3\x02\n\x17GetDataContractResponse\x12Z\n\x02v0\x18\x01 \x01(\x0b\x32L.org.dash.platform.dapi.v0.GetDataContractResponse.GetDataContractResponseV0H\x00\x1a\xb0\x01\n\x19GetDataContractResponseV0\x12\x17\n\rdata_contract\x18\x01 \x01(\x0cH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\xb9\x01\n\x17GetDataContractsRequest\x12Z\n\x02v0\x18\x01 \x01(\x0b\x32L.org.dash.platform.dapi.v0.GetDataContractsRequest.GetDataContractsRequestV0H\x00\x1a\x37\n\x19GetDataContractsRequestV0\x12\x0b\n\x03ids\x18\x01 \x03(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\xcf\x04\n\x18GetDataContractsResponse\x12\\\n\x02v0\x18\x01 \x01(\x0b\x32N.org.dash.platform.dapi.v0.GetDataContractsResponse.GetDataContractsResponseV0H\x00\x1a[\n\x11\x44\x61taContractEntry\x12\x12\n\nidentifier\x18\x01 \x01(\x0c\x12\x32\n\rdata_contract\x18\x02 \x01(\x0b\x32\x1b.google.protobuf.BytesValue\x1au\n\rDataContracts\x12\x64\n\x15\x64\x61ta_contract_entries\x18\x01 \x03(\x0b\x32\x45.org.dash.platform.dapi.v0.GetDataContractsResponse.DataContractEntry\x1a\xf5\x01\n\x1aGetDataContractsResponseV0\x12[\n\x0e\x64\x61ta_contracts\x18\x01 \x01(\x0b\x32\x41.org.dash.platform.dapi.v0.GetDataContractsResponse.DataContractsH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\xc1\x02\n\x1dGetDataContractHistoryRequest\x12\x66\n\x02v0\x18\x01 \x01(\x0b\x32X.org.dash.platform.dapi.v0.GetDataContractHistoryRequest.GetDataContractHistoryRequestV0H\x00\x1a\xac\x01\n\x1fGetDataContractHistoryRequestV0\x12\n\n\x02id\x18\x01 \x01(\x0c\x12+\n\x05limit\x18\x02 \x01(\x0b\x32\x1c.google.protobuf.UInt32Value\x12,\n\x06offset\x18\x03 \x01(\x0b\x32\x1c.google.protobuf.UInt32Value\x12\x13\n\x0bstart_at_ms\x18\x04 \x01(\x04\x12\r\n\x05prove\x18\x05 \x01(\x08\x42\t\n\x07version\"\xae\x05\n\x1eGetDataContractHistoryResponse\x12h\n\x02v0\x18\x01 \x01(\x0b\x32Z.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.GetDataContractHistoryResponseV0H\x00\x1a\x96\x04\n GetDataContractHistoryResponseV0\x12\x8f\x01\n\x15\x64\x61ta_contract_history\x18\x01 \x01(\x0b\x32n.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.GetDataContractHistoryResponseV0.DataContractHistoryH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\x37\n\x18\x44\x61taContractHistoryEntry\x12\x0c\n\x04\x64\x61te\x18\x01 \x01(\x04\x12\r\n\x05value\x18\x02 \x01(\x0c\x1a\xaa\x01\n\x13\x44\x61taContractHistory\x12\x92\x01\n\x15\x64\x61ta_contract_entries\x18\x01 \x03(\x0b\x32s.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.GetDataContractHistoryResponseV0.DataContractHistoryEntryB\x08\n\x06resultB\t\n\x07version\"\xb2\x02\n\x13GetDocumentsRequest\x12R\n\x02v0\x18\x01 \x01(\x0b\x32\x44.org.dash.platform.dapi.v0.GetDocumentsRequest.GetDocumentsRequestV0H\x00\x1a\xbb\x01\n\x15GetDocumentsRequestV0\x12\x18\n\x10\x64\x61ta_contract_id\x18\x01 \x01(\x0c\x12\x15\n\rdocument_type\x18\x02 \x01(\t\x12\r\n\x05where\x18\x03 \x01(\x0c\x12\x10\n\x08order_by\x18\x04 \x01(\x0c\x12\r\n\x05limit\x18\x05 \x01(\r\x12\x15\n\x0bstart_after\x18\x06 \x01(\x0cH\x00\x12\x12\n\x08start_at\x18\x07 \x01(\x0cH\x00\x12\r\n\x05prove\x18\x08 \x01(\x08\x42\x07\n\x05startB\t\n\x07version\"\x95\x03\n\x14GetDocumentsResponse\x12T\n\x02v0\x18\x01 \x01(\x0b\x32\x46.org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocumentsResponseV0H\x00\x1a\x9b\x02\n\x16GetDocumentsResponseV0\x12\x65\n\tdocuments\x18\x01 \x01(\x0b\x32P.org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocumentsResponseV0.DocumentsH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\x1e\n\tDocuments\x12\x11\n\tdocuments\x18\x01 \x03(\x0c\x42\x08\n\x06resultB\t\n\x07version\"\xed\x01\n!GetIdentityByPublicKeyHashRequest\x12n\n\x02v0\x18\x01 \x01(\x0b\x32`.org.dash.platform.dapi.v0.GetIdentityByPublicKeyHashRequest.GetIdentityByPublicKeyHashRequestV0H\x00\x1aM\n#GetIdentityByPublicKeyHashRequestV0\x12\x17\n\x0fpublic_key_hash\x18\x01 \x01(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\xda\x02\n\"GetIdentityByPublicKeyHashResponse\x12p\n\x02v0\x18\x01 \x01(\x0b\x32\x62.org.dash.platform.dapi.v0.GetIdentityByPublicKeyHashResponse.GetIdentityByPublicKeyHashResponseV0H\x00\x1a\xb6\x01\n$GetIdentityByPublicKeyHashResponseV0\x12\x12\n\x08identity\x18\x01 \x01(\x0cH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\xfb\x01\n#WaitForStateTransitionResultRequest\x12r\n\x02v0\x18\x01 \x01(\x0b\x32\x64.org.dash.platform.dapi.v0.WaitForStateTransitionResultRequest.WaitForStateTransitionResultRequestV0H\x00\x1aU\n%WaitForStateTransitionResultRequestV0\x12\x1d\n\x15state_transition_hash\x18\x01 \x01(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\x99\x03\n$WaitForStateTransitionResultResponse\x12t\n\x02v0\x18\x01 \x01(\x0b\x32\x66.org.dash.platform.dapi.v0.WaitForStateTransitionResultResponse.WaitForStateTransitionResultResponseV0H\x00\x1a\xef\x01\n&WaitForStateTransitionResultResponseV0\x12I\n\x05\x65rror\x18\x01 \x01(\x0b\x32\x38.org.dash.platform.dapi.v0.StateTransitionBroadcastErrorH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\xc4\x01\n\x19GetConsensusParamsRequest\x12^\n\x02v0\x18\x01 \x01(\x0b\x32P.org.dash.platform.dapi.v0.GetConsensusParamsRequest.GetConsensusParamsRequestV0H\x00\x1a<\n\x1bGetConsensusParamsRequestV0\x12\x0e\n\x06height\x18\x01 \x01(\x05\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\x9c\x04\n\x1aGetConsensusParamsResponse\x12`\n\x02v0\x18\x01 \x01(\x0b\x32R.org.dash.platform.dapi.v0.GetConsensusParamsResponse.GetConsensusParamsResponseV0H\x00\x1aP\n\x14\x43onsensusParamsBlock\x12\x11\n\tmax_bytes\x18\x01 \x01(\t\x12\x0f\n\x07max_gas\x18\x02 \x01(\t\x12\x14\n\x0ctime_iota_ms\x18\x03 \x01(\t\x1a\x62\n\x17\x43onsensusParamsEvidence\x12\x1a\n\x12max_age_num_blocks\x18\x01 \x01(\t\x12\x18\n\x10max_age_duration\x18\x02 \x01(\t\x12\x11\n\tmax_bytes\x18\x03 \x01(\t\x1a\xda\x01\n\x1cGetConsensusParamsResponseV0\x12Y\n\x05\x62lock\x18\x01 \x01(\x0b\x32J.org.dash.platform.dapi.v0.GetConsensusParamsResponse.ConsensusParamsBlock\x12_\n\x08\x65vidence\x18\x02 \x01(\x0b\x32M.org.dash.platform.dapi.v0.GetConsensusParamsResponse.ConsensusParamsEvidenceB\t\n\x07version\"\xe4\x01\n%GetProtocolVersionUpgradeStateRequest\x12v\n\x02v0\x18\x01 \x01(\x0b\x32h.org.dash.platform.dapi.v0.GetProtocolVersionUpgradeStateRequest.GetProtocolVersionUpgradeStateRequestV0H\x00\x1a\x38\n\'GetProtocolVersionUpgradeStateRequestV0\x12\r\n\x05prove\x18\x01 \x01(\x08\x42\t\n\x07version\"\xb5\x05\n&GetProtocolVersionUpgradeStateResponse\x12x\n\x02v0\x18\x01 \x01(\x0b\x32j.org.dash.platform.dapi.v0.GetProtocolVersionUpgradeStateResponse.GetProtocolVersionUpgradeStateResponseV0H\x00\x1a\x85\x04\n(GetProtocolVersionUpgradeStateResponseV0\x12\x87\x01\n\x08versions\x18\x01 \x01(\x0b\x32s.org.dash.platform.dapi.v0.GetProtocolVersionUpgradeStateResponse.GetProtocolVersionUpgradeStateResponseV0.VersionsH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\x96\x01\n\x08Versions\x12\x89\x01\n\x08versions\x18\x01 \x03(\x0b\x32w.org.dash.platform.dapi.v0.GetProtocolVersionUpgradeStateResponse.GetProtocolVersionUpgradeStateResponseV0.VersionEntry\x1a:\n\x0cVersionEntry\x12\x16\n\x0eversion_number\x18\x01 \x01(\r\x12\x12\n\nvote_count\x18\x02 \x01(\rB\x08\n\x06resultB\t\n\x07version\"\xa3\x02\n*GetProtocolVersionUpgradeVoteStatusRequest\x12\x80\x01\n\x02v0\x18\x01 \x01(\x0b\x32r.org.dash.platform.dapi.v0.GetProtocolVersionUpgradeVoteStatusRequest.GetProtocolVersionUpgradeVoteStatusRequestV0H\x00\x1ag\n,GetProtocolVersionUpgradeVoteStatusRequestV0\x12\x19\n\x11start_pro_tx_hash\x18\x01 \x01(\x0c\x12\r\n\x05\x63ount\x18\x02 \x01(\r\x12\r\n\x05prove\x18\x03 \x01(\x08\x42\t\n\x07version\"\xef\x05\n+GetProtocolVersionUpgradeVoteStatusResponse\x12\x82\x01\n\x02v0\x18\x01 \x01(\x0b\x32t.org.dash.platform.dapi.v0.GetProtocolVersionUpgradeVoteStatusResponse.GetProtocolVersionUpgradeVoteStatusResponseV0H\x00\x1a\xaf\x04\n-GetProtocolVersionUpgradeVoteStatusResponseV0\x12\x98\x01\n\x08versions\x18\x01 \x01(\x0b\x32\x83\x01.org.dash.platform.dapi.v0.GetProtocolVersionUpgradeVoteStatusResponse.GetProtocolVersionUpgradeVoteStatusResponseV0.VersionSignalsH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\xaf\x01\n\x0eVersionSignals\x12\x9c\x01\n\x0fversion_signals\x18\x01 \x03(\x0b\x32\x82\x01.org.dash.platform.dapi.v0.GetProtocolVersionUpgradeVoteStatusResponse.GetProtocolVersionUpgradeVoteStatusResponseV0.VersionSignal\x1a\x35\n\rVersionSignal\x12\x13\n\x0bpro_tx_hash\x18\x01 \x01(\x0c\x12\x0f\n\x07version\x18\x02 \x01(\rB\x08\n\x06resultB\t\n\x07version\"\xf5\x01\n\x14GetEpochsInfoRequest\x12T\n\x02v0\x18\x01 \x01(\x0b\x32\x46.org.dash.platform.dapi.v0.GetEpochsInfoRequest.GetEpochsInfoRequestV0H\x00\x1a|\n\x16GetEpochsInfoRequestV0\x12\x31\n\x0bstart_epoch\x18\x01 \x01(\x0b\x32\x1c.google.protobuf.UInt32Value\x12\r\n\x05\x63ount\x18\x02 \x01(\r\x12\x11\n\tascending\x18\x03 \x01(\x08\x12\r\n\x05prove\x18\x04 \x01(\x08\x42\t\n\x07version\"\x91\x05\n\x15GetEpochsInfoResponse\x12V\n\x02v0\x18\x01 \x01(\x0b\x32H.org.dash.platform.dapi.v0.GetEpochsInfoResponse.GetEpochsInfoResponseV0H\x00\x1a\x94\x04\n\x17GetEpochsInfoResponseV0\x12\x65\n\x06\x65pochs\x18\x01 \x01(\x0b\x32S.org.dash.platform.dapi.v0.GetEpochsInfoResponse.GetEpochsInfoResponseV0.EpochInfosH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1au\n\nEpochInfos\x12g\n\x0b\x65poch_infos\x18\x01 \x03(\x0b\x32R.org.dash.platform.dapi.v0.GetEpochsInfoResponse.GetEpochsInfoResponseV0.EpochInfo\x1a\x9e\x01\n\tEpochInfo\x12\x0e\n\x06number\x18\x01 \x01(\r\x12\x1a\n\x12\x66irst_block_height\x18\x02 \x01(\x04\x12\x1f\n\x17\x66irst_core_block_height\x18\x03 \x01(\r\x12\x12\n\nstart_time\x18\x04 \x01(\x04\x12\x16\n\x0e\x66\x65\x65_multiplier\x18\x05 \x01(\x01\x12\x18\n\x10protocol_version\x18\x06 \x01(\rB\x08\n\x06resultB\t\n\x07version\"\xde\x04\n\x1cGetContestedResourcesRequest\x12\x64\n\x02v0\x18\x01 \x01(\x0b\x32V.org.dash.platform.dapi.v0.GetContestedResourcesRequest.GetContestedResourcesRequestV0H\x00\x1a\xcc\x03\n\x1eGetContestedResourcesRequestV0\x12\x13\n\x0b\x63ontract_id\x18\x01 \x01(\x0c\x12\x1a\n\x12\x64ocument_type_name\x18\x02 \x01(\t\x12\x12\n\nindex_name\x18\x03 \x01(\t\x12\x1a\n\x12start_index_values\x18\x04 \x03(\x0c\x12\x18\n\x10\x65nd_index_values\x18\x05 \x03(\x0c\x12\x89\x01\n\x13start_at_value_info\x18\x06 \x01(\x0b\x32g.org.dash.platform.dapi.v0.GetContestedResourcesRequest.GetContestedResourcesRequestV0.StartAtValueInfoH\x00\x88\x01\x01\x12\x12\n\x05\x63ount\x18\x07 \x01(\rH\x01\x88\x01\x01\x12\x17\n\x0forder_ascending\x18\x08 \x01(\x08\x12\r\n\x05prove\x18\t \x01(\x08\x1a\x45\n\x10StartAtValueInfo\x12\x13\n\x0bstart_value\x18\x01 \x01(\x0c\x12\x1c\n\x14start_value_included\x18\x02 \x01(\x08\x42\x16\n\x14_start_at_value_infoB\x08\n\x06_countB\t\n\x07version\"\x88\x04\n\x1dGetContestedResourcesResponse\x12\x66\n\x02v0\x18\x01 \x01(\x0b\x32X.org.dash.platform.dapi.v0.GetContestedResourcesResponse.GetContestedResourcesResponseV0H\x00\x1a\xf3\x02\n\x1fGetContestedResourcesResponseV0\x12\x95\x01\n\x19\x63ontested_resource_values\x18\x01 \x01(\x0b\x32p.org.dash.platform.dapi.v0.GetContestedResourcesResponse.GetContestedResourcesResponseV0.ContestedResourceValuesH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a<\n\x17\x43ontestedResourceValues\x12!\n\x19\x63ontested_resource_values\x18\x01 \x03(\x0c\x42\x08\n\x06resultB\t\n\x07version\"\xca\x05\n\x1cGetVotePollsByEndDateRequest\x12\x64\n\x02v0\x18\x01 \x01(\x0b\x32V.org.dash.platform.dapi.v0.GetVotePollsByEndDateRequest.GetVotePollsByEndDateRequestV0H\x00\x1a\xb8\x04\n\x1eGetVotePollsByEndDateRequestV0\x12\x84\x01\n\x0fstart_time_info\x18\x01 \x01(\x0b\x32\x66.org.dash.platform.dapi.v0.GetVotePollsByEndDateRequest.GetVotePollsByEndDateRequestV0.StartAtTimeInfoH\x00\x88\x01\x01\x12\x80\x01\n\rend_time_info\x18\x02 \x01(\x0b\x32\x64.org.dash.platform.dapi.v0.GetVotePollsByEndDateRequest.GetVotePollsByEndDateRequestV0.EndAtTimeInfoH\x01\x88\x01\x01\x12\x12\n\x05limit\x18\x03 \x01(\rH\x02\x88\x01\x01\x12\x13\n\x06offset\x18\x04 \x01(\rH\x03\x88\x01\x01\x12\x11\n\tascending\x18\x05 \x01(\x08\x12\r\n\x05prove\x18\x06 \x01(\x08\x1a\x45\n\x0fStartAtTimeInfo\x12\x15\n\rstart_time_ms\x18\x01 \x01(\x04\x12\x1b\n\x13start_time_included\x18\x02 \x01(\x08\x1a?\n\rEndAtTimeInfo\x12\x13\n\x0b\x65nd_time_ms\x18\x01 \x01(\x04\x12\x19\n\x11\x65nd_time_included\x18\x02 \x01(\x08\x42\x12\n\x10_start_time_infoB\x10\n\x0e_end_time_infoB\x08\n\x06_limitB\t\n\x07_offsetB\t\n\x07version\"\xff\x05\n\x1dGetVotePollsByEndDateResponse\x12\x66\n\x02v0\x18\x01 \x01(\x0b\x32X.org.dash.platform.dapi.v0.GetVotePollsByEndDateResponse.GetVotePollsByEndDateResponseV0H\x00\x1a\xea\x04\n\x1fGetVotePollsByEndDateResponseV0\x12\x9c\x01\n\x18vote_polls_by_timestamps\x18\x01 \x01(\x0b\x32x.org.dash.platform.dapi.v0.GetVotePollsByEndDateResponse.GetVotePollsByEndDateResponseV0.SerializedVotePollsByTimestampsH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1aR\n\x1eSerializedVotePollsByTimestamp\x12\x11\n\ttimestamp\x18\x01 \x01(\x04\x12\x1d\n\x15serialized_vote_polls\x18\x02 \x03(\x0c\x1a\xd7\x01\n\x1fSerializedVotePollsByTimestamps\x12\x99\x01\n\x18vote_polls_by_timestamps\x18\x01 \x03(\x0b\x32w.org.dash.platform.dapi.v0.GetVotePollsByEndDateResponse.GetVotePollsByEndDateResponseV0.SerializedVotePollsByTimestamp\x12\x18\n\x10\x66inished_results\x18\x02 \x01(\x08\x42\x08\n\x06resultB\t\n\x07version\"\x96\x07\n$GetContestedResourceVoteStateRequest\x12t\n\x02v0\x18\x01 \x01(\x0b\x32\x66.org.dash.platform.dapi.v0.GetContestedResourceVoteStateRequest.GetContestedResourceVoteStateRequestV0H\x00\x1a\xec\x05\n&GetContestedResourceVoteStateRequestV0\x12\x13\n\x0b\x63ontract_id\x18\x01 \x01(\x0c\x12\x1a\n\x12\x64ocument_type_name\x18\x02 \x01(\t\x12\x12\n\nindex_name\x18\x03 \x01(\t\x12\x14\n\x0cindex_values\x18\x04 \x03(\x0c\x12\x86\x01\n\x0bresult_type\x18\x05 \x01(\x0e\x32q.org.dash.platform.dapi.v0.GetContestedResourceVoteStateRequest.GetContestedResourceVoteStateRequestV0.ResultType\x12\x36\n.allow_include_locked_and_abstaining_vote_tally\x18\x06 \x01(\x08\x12\xa3\x01\n\x18start_at_identifier_info\x18\x07 \x01(\x0b\x32|.org.dash.platform.dapi.v0.GetContestedResourceVoteStateRequest.GetContestedResourceVoteStateRequestV0.StartAtIdentifierInfoH\x00\x88\x01\x01\x12\x12\n\x05\x63ount\x18\x08 \x01(\rH\x01\x88\x01\x01\x12\r\n\x05prove\x18\t \x01(\x08\x1aT\n\x15StartAtIdentifierInfo\x12\x18\n\x10start_identifier\x18\x01 \x01(\x0c\x12!\n\x19start_identifier_included\x18\x02 \x01(\x08\"`\n\nResultType\x12\x15\n\x11IDENTITY_IDS_ONLY\x10\x00\x12\r\n\tDOCUMENTS\x10\x01\x12\x0e\n\nVOTE_TALLY\x10\x02\x12\x1c\n\x18\x44OCUMENTS_AND_VOTE_TALLY\x10\x03\x42\x1b\n\x19_start_at_identifier_infoB\x08\n\x06_countB\t\n\x07version\"\x8c\x0c\n%GetContestedResourceVoteStateResponse\x12v\n\x02v0\x18\x01 \x01(\x0b\x32h.org.dash.platform.dapi.v0.GetContestedResourceVoteStateResponse.GetContestedResourceVoteStateResponseV0H\x00\x1a\xdf\n\n\'GetContestedResourceVoteStateResponseV0\x12\xae\x01\n\x1d\x63ontested_resource_contenders\x18\x01 \x01(\x0b\x32\x84\x01.org.dash.platform.dapi.v0.GetContestedResourceVoteStateResponse.GetContestedResourceVoteStateResponseV0.ContestedResourceContendersH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\xd2\x03\n\x10\x46inishedVoteInfo\x12\xad\x01\n\x15\x66inished_vote_outcome\x18\x01 \x01(\x0e\x32\x8d\x01.org.dash.platform.dapi.v0.GetContestedResourceVoteStateResponse.GetContestedResourceVoteStateResponseV0.FinishedVoteInfo.FinishedVoteOutcome\x12\x1f\n\x12won_by_identity_id\x18\x02 \x01(\x0cH\x00\x88\x01\x01\x12 \n\x18\x66inished_at_block_height\x18\x03 \x01(\x04\x12%\n\x1d\x66inished_at_core_block_height\x18\x04 \x01(\r\x12!\n\x19\x66inished_at_block_time_ms\x18\x05 \x01(\x04\x12\x19\n\x11\x66inished_at_epoch\x18\x06 \x01(\r\"O\n\x13\x46inishedVoteOutcome\x12\x14\n\x10TOWARDS_IDENTITY\x10\x00\x12\n\n\x06LOCKED\x10\x01\x12\x16\n\x12NO_PREVIOUS_WINNER\x10\x02\x42\x15\n\x13_won_by_identity_id\x1a\xc4\x03\n\x1b\x43ontestedResourceContenders\x12\x86\x01\n\ncontenders\x18\x01 \x03(\x0b\x32r.org.dash.platform.dapi.v0.GetContestedResourceVoteStateResponse.GetContestedResourceVoteStateResponseV0.Contender\x12\x1f\n\x12\x61\x62stain_vote_tally\x18\x02 \x01(\rH\x00\x88\x01\x01\x12\x1c\n\x0flock_vote_tally\x18\x03 \x01(\rH\x01\x88\x01\x01\x12\x9a\x01\n\x12\x66inished_vote_info\x18\x04 \x01(\x0b\x32y.org.dash.platform.dapi.v0.GetContestedResourceVoteStateResponse.GetContestedResourceVoteStateResponseV0.FinishedVoteInfoH\x02\x88\x01\x01\x42\x15\n\x13_abstain_vote_tallyB\x12\n\x10_lock_vote_tallyB\x15\n\x13_finished_vote_info\x1ak\n\tContender\x12\x12\n\nidentifier\x18\x01 \x01(\x0c\x12\x17\n\nvote_count\x18\x02 \x01(\rH\x00\x88\x01\x01\x12\x15\n\x08\x64ocument\x18\x03 \x01(\x0cH\x01\x88\x01\x01\x42\r\n\x0b_vote_countB\x0b\n\t_documentB\x08\n\x06resultB\t\n\x07version\"\xd5\x05\n,GetContestedResourceVotersForIdentityRequest\x12\x84\x01\n\x02v0\x18\x01 \x01(\x0b\x32v.org.dash.platform.dapi.v0.GetContestedResourceVotersForIdentityRequest.GetContestedResourceVotersForIdentityRequestV0H\x00\x1a\x92\x04\n.GetContestedResourceVotersForIdentityRequestV0\x12\x13\n\x0b\x63ontract_id\x18\x01 \x01(\x0c\x12\x1a\n\x12\x64ocument_type_name\x18\x02 \x01(\t\x12\x12\n\nindex_name\x18\x03 \x01(\t\x12\x14\n\x0cindex_values\x18\x04 \x03(\x0c\x12\x15\n\rcontestant_id\x18\x05 \x01(\x0c\x12\xb4\x01\n\x18start_at_identifier_info\x18\x06 \x01(\x0b\x32\x8c\x01.org.dash.platform.dapi.v0.GetContestedResourceVotersForIdentityRequest.GetContestedResourceVotersForIdentityRequestV0.StartAtIdentifierInfoH\x00\x88\x01\x01\x12\x12\n\x05\x63ount\x18\x07 \x01(\rH\x01\x88\x01\x01\x12\x17\n\x0forder_ascending\x18\x08 \x01(\x08\x12\r\n\x05prove\x18\t \x01(\x08\x1aT\n\x15StartAtIdentifierInfo\x12\x18\n\x10start_identifier\x18\x01 \x01(\x0c\x12!\n\x19start_identifier_included\x18\x02 \x01(\x08\x42\x1b\n\x19_start_at_identifier_infoB\x08\n\x06_countB\t\n\x07version\"\xf1\x04\n-GetContestedResourceVotersForIdentityResponse\x12\x86\x01\n\x02v0\x18\x01 \x01(\x0b\x32x.org.dash.platform.dapi.v0.GetContestedResourceVotersForIdentityResponse.GetContestedResourceVotersForIdentityResponseV0H\x00\x1a\xab\x03\n/GetContestedResourceVotersForIdentityResponseV0\x12\xb6\x01\n\x19\x63ontested_resource_voters\x18\x01 \x01(\x0b\x32\x90\x01.org.dash.platform.dapi.v0.GetContestedResourceVotersForIdentityResponse.GetContestedResourceVotersForIdentityResponseV0.ContestedResourceVotersH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\x43\n\x17\x43ontestedResourceVoters\x12\x0e\n\x06voters\x18\x01 \x03(\x0c\x12\x18\n\x10\x66inished_results\x18\x02 \x01(\x08\x42\x08\n\x06resultB\t\n\x07version\"\xad\x05\n(GetContestedResourceIdentityVotesRequest\x12|\n\x02v0\x18\x01 \x01(\x0b\x32n.org.dash.platform.dapi.v0.GetContestedResourceIdentityVotesRequest.GetContestedResourceIdentityVotesRequestV0H\x00\x1a\xf7\x03\n*GetContestedResourceIdentityVotesRequestV0\x12\x13\n\x0bidentity_id\x18\x01 \x01(\x0c\x12+\n\x05limit\x18\x02 \x01(\x0b\x32\x1c.google.protobuf.UInt32Value\x12,\n\x06offset\x18\x03 \x01(\x0b\x32\x1c.google.protobuf.UInt32Value\x12\x17\n\x0forder_ascending\x18\x04 \x01(\x08\x12\xae\x01\n\x1astart_at_vote_poll_id_info\x18\x05 \x01(\x0b\x32\x84\x01.org.dash.platform.dapi.v0.GetContestedResourceIdentityVotesRequest.GetContestedResourceIdentityVotesRequestV0.StartAtVotePollIdInfoH\x00\x88\x01\x01\x12\r\n\x05prove\x18\x06 \x01(\x08\x1a\x61\n\x15StartAtVotePollIdInfo\x12 \n\x18start_at_poll_identifier\x18\x01 \x01(\x0c\x12&\n\x1estart_poll_identifier_included\x18\x02 \x01(\x08\x42\x1d\n\x1b_start_at_vote_poll_id_infoB\t\n\x07version\"\xc8\n\n)GetContestedResourceIdentityVotesResponse\x12~\n\x02v0\x18\x01 \x01(\x0b\x32p.org.dash.platform.dapi.v0.GetContestedResourceIdentityVotesResponse.GetContestedResourceIdentityVotesResponseV0H\x00\x1a\x8f\t\n+GetContestedResourceIdentityVotesResponseV0\x12\xa1\x01\n\x05votes\x18\x01 \x01(\x0b\x32\x8f\x01.org.dash.platform.dapi.v0.GetContestedResourceIdentityVotesResponse.GetContestedResourceIdentityVotesResponseV0.ContestedResourceIdentityVotesH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\xf7\x01\n\x1e\x43ontestedResourceIdentityVotes\x12\xba\x01\n!contested_resource_identity_votes\x18\x01 \x03(\x0b\x32\x8e\x01.org.dash.platform.dapi.v0.GetContestedResourceIdentityVotesResponse.GetContestedResourceIdentityVotesResponseV0.ContestedResourceIdentityVote\x12\x18\n\x10\x66inished_results\x18\x02 \x01(\x08\x1a\xad\x02\n\x12ResourceVoteChoice\x12\xad\x01\n\x10vote_choice_type\x18\x01 \x01(\x0e\x32\x92\x01.org.dash.platform.dapi.v0.GetContestedResourceIdentityVotesResponse.GetContestedResourceIdentityVotesResponseV0.ResourceVoteChoice.VoteChoiceType\x12\x18\n\x0bidentity_id\x18\x02 \x01(\x0cH\x00\x88\x01\x01\"=\n\x0eVoteChoiceType\x12\x14\n\x10TOWARDS_IDENTITY\x10\x00\x12\x0b\n\x07\x41\x42STAIN\x10\x01\x12\x08\n\x04LOCK\x10\x02\x42\x0e\n\x0c_identity_id\x1a\x95\x02\n\x1d\x43ontestedResourceIdentityVote\x12\x13\n\x0b\x63ontract_id\x18\x01 \x01(\x0c\x12\x1a\n\x12\x64ocument_type_name\x18\x02 \x01(\t\x12\'\n\x1fserialized_index_storage_values\x18\x03 \x03(\x0c\x12\x99\x01\n\x0bvote_choice\x18\x04 \x01(\x0b\x32\x83\x01.org.dash.platform.dapi.v0.GetContestedResourceIdentityVotesResponse.GetContestedResourceIdentityVotesResponseV0.ResourceVoteChoiceB\x08\n\x06resultB\t\n\x07version\"\xf0\x01\n%GetPrefundedSpecializedBalanceRequest\x12v\n\x02v0\x18\x01 \x01(\x0b\x32h.org.dash.platform.dapi.v0.GetPrefundedSpecializedBalanceRequest.GetPrefundedSpecializedBalanceRequestV0H\x00\x1a\x44\n\'GetPrefundedSpecializedBalanceRequestV0\x12\n\n\x02id\x18\x01 \x01(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\xe9\x02\n&GetPrefundedSpecializedBalanceResponse\x12x\n\x02v0\x18\x01 \x01(\x0b\x32j.org.dash.platform.dapi.v0.GetPrefundedSpecializedBalanceResponse.GetPrefundedSpecializedBalanceResponseV0H\x00\x1a\xb9\x01\n(GetPrefundedSpecializedBalanceResponseV0\x12\x11\n\x07\x62\x61lance\x18\x01 \x01(\x04H\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\xc4\x01\n\x16GetPathElementsRequest\x12X\n\x02v0\x18\x01 \x01(\x0b\x32J.org.dash.platform.dapi.v0.GetPathElementsRequest.GetPathElementsRequestV0H\x00\x1a\x45\n\x18GetPathElementsRequestV0\x12\x0c\n\x04path\x18\x01 \x03(\x0c\x12\x0c\n\x04keys\x18\x02 \x03(\x0c\x12\r\n\x05prove\x18\x03 \x01(\x08\x42\t\n\x07version\"\xa3\x03\n\x17GetPathElementsResponse\x12Z\n\x02v0\x18\x01 \x01(\x0b\x32L.org.dash.platform.dapi.v0.GetPathElementsResponse.GetPathElementsResponseV0H\x00\x1a\xa0\x02\n\x19GetPathElementsResponseV0\x12i\n\x08\x65lements\x18\x01 \x01(\x0b\x32U.org.dash.platform.dapi.v0.GetPathElementsResponse.GetPathElementsResponseV0.ElementsH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\x1c\n\x08\x45lements\x12\x10\n\x08\x65lements\x18\x01 \x03(\x0c\x42\x08\n\x06resultB\t\n\x07version*Z\n\nKeyPurpose\x12\x12\n\x0e\x41UTHENTICATION\x10\x00\x12\x0e\n\nENCRYPTION\x10\x01\x12\x0e\n\nDECRYPTION\x10\x02\x12\x0c\n\x08TRANSFER\x10\x03\x12\n\n\x06VOTING\x10\x05\x32\xa1\x1d\n\x08Platform\x12\x93\x01\n\x18\x62roadcastStateTransition\x12:.org.dash.platform.dapi.v0.BroadcastStateTransitionRequest\x1a;.org.dash.platform.dapi.v0.BroadcastStateTransitionResponse\x12l\n\x0bgetIdentity\x12-.org.dash.platform.dapi.v0.GetIdentityRequest\x1a..org.dash.platform.dapi.v0.GetIdentityResponse\x12x\n\x0fgetIdentityKeys\x12\x31.org.dash.platform.dapi.v0.GetIdentityKeysRequest\x1a\x32.org.dash.platform.dapi.v0.GetIdentityKeysResponse\x12\x96\x01\n\x19getIdentitiesContractKeys\x12;.org.dash.platform.dapi.v0.GetIdentitiesContractKeysRequest\x1a<.org.dash.platform.dapi.v0.GetIdentitiesContractKeysResponse\x12{\n\x10getIdentityNonce\x12\x32.org.dash.platform.dapi.v0.GetIdentityNonceRequest\x1a\x33.org.dash.platform.dapi.v0.GetIdentityNonceResponse\x12\x93\x01\n\x18getIdentityContractNonce\x12:.org.dash.platform.dapi.v0.GetIdentityContractNonceRequest\x1a;.org.dash.platform.dapi.v0.GetIdentityContractNonceResponse\x12\x81\x01\n\x12getIdentityBalance\x12\x34.org.dash.platform.dapi.v0.GetIdentityBalanceRequest\x1a\x35.org.dash.platform.dapi.v0.GetIdentityBalanceResponse\x12\xa2\x01\n\x1dgetIdentityBalanceAndRevision\x12?.org.dash.platform.dapi.v0.GetIdentityBalanceAndRevisionRequest\x1a@.org.dash.platform.dapi.v0.GetIdentityBalanceAndRevisionResponse\x12\x66\n\tgetProofs\x12+.org.dash.platform.dapi.v0.GetProofsRequest\x1a,.org.dash.platform.dapi.v0.GetProofsResponse\x12x\n\x0fgetDataContract\x12\x31.org.dash.platform.dapi.v0.GetDataContractRequest\x1a\x32.org.dash.platform.dapi.v0.GetDataContractResponse\x12\x8d\x01\n\x16getDataContractHistory\x12\x38.org.dash.platform.dapi.v0.GetDataContractHistoryRequest\x1a\x39.org.dash.platform.dapi.v0.GetDataContractHistoryResponse\x12{\n\x10getDataContracts\x12\x32.org.dash.platform.dapi.v0.GetDataContractsRequest\x1a\x33.org.dash.platform.dapi.v0.GetDataContractsResponse\x12o\n\x0cgetDocuments\x12..org.dash.platform.dapi.v0.GetDocumentsRequest\x1a/.org.dash.platform.dapi.v0.GetDocumentsResponse\x12\x99\x01\n\x1agetIdentityByPublicKeyHash\x12<.org.dash.platform.dapi.v0.GetIdentityByPublicKeyHashRequest\x1a=.org.dash.platform.dapi.v0.GetIdentityByPublicKeyHashResponse\x12\x9f\x01\n\x1cwaitForStateTransitionResult\x12>.org.dash.platform.dapi.v0.WaitForStateTransitionResultRequest\x1a?.org.dash.platform.dapi.v0.WaitForStateTransitionResultResponse\x12\x81\x01\n\x12getConsensusParams\x12\x34.org.dash.platform.dapi.v0.GetConsensusParamsRequest\x1a\x35.org.dash.platform.dapi.v0.GetConsensusParamsResponse\x12\xa5\x01\n\x1egetProtocolVersionUpgradeState\x12@.org.dash.platform.dapi.v0.GetProtocolVersionUpgradeStateRequest\x1a\x41.org.dash.platform.dapi.v0.GetProtocolVersionUpgradeStateResponse\x12\xb4\x01\n#getProtocolVersionUpgradeVoteStatus\x12\x45.org.dash.platform.dapi.v0.GetProtocolVersionUpgradeVoteStatusRequest\x1a\x46.org.dash.platform.dapi.v0.GetProtocolVersionUpgradeVoteStatusResponse\x12r\n\rgetEpochsInfo\x12/.org.dash.platform.dapi.v0.GetEpochsInfoRequest\x1a\x30.org.dash.platform.dapi.v0.GetEpochsInfoResponse\x12\x8a\x01\n\x15getContestedResources\x12\x37.org.dash.platform.dapi.v0.GetContestedResourcesRequest\x1a\x38.org.dash.platform.dapi.v0.GetContestedResourcesResponse\x12\xa2\x01\n\x1dgetContestedResourceVoteState\x12?.org.dash.platform.dapi.v0.GetContestedResourceVoteStateRequest\x1a@.org.dash.platform.dapi.v0.GetContestedResourceVoteStateResponse\x12\xba\x01\n%getContestedResourceVotersForIdentity\x12G.org.dash.platform.dapi.v0.GetContestedResourceVotersForIdentityRequest\x1aH.org.dash.platform.dapi.v0.GetContestedResourceVotersForIdentityResponse\x12\xae\x01\n!getContestedResourceIdentityVotes\x12\x43.org.dash.platform.dapi.v0.GetContestedResourceIdentityVotesRequest\x1a\x44.org.dash.platform.dapi.v0.GetContestedResourceIdentityVotesResponse\x12\x8a\x01\n\x15getVotePollsByEndDate\x12\x37.org.dash.platform.dapi.v0.GetVotePollsByEndDateRequest\x1a\x38.org.dash.platform.dapi.v0.GetVotePollsByEndDateResponse\x12\xa5\x01\n\x1egetPrefundedSpecializedBalance\x12@.org.dash.platform.dapi.v0.GetPrefundedSpecializedBalanceRequest\x1a\x41.org.dash.platform.dapi.v0.GetPrefundedSpecializedBalanceResponse\x12x\n\x0fgetPathElements\x12\x31.org.dash.platform.dapi.v0.GetPathElementsRequest\x1a\x32.org.dash.platform.dapi.v0.GetPathElementsResponseb\x06proto3' + serialized_pb=b'\n\x0eplatform.proto\x12\x19org.dash.platform.dapi.v0\x1a\x1egoogle/protobuf/wrappers.proto\x1a\x1cgoogle/protobuf/struct.proto\x1a\x1fgoogle/protobuf/timestamp.proto\"\x81\x01\n\x05Proof\x12\x15\n\rgrovedb_proof\x18\x01 \x01(\x0c\x12\x13\n\x0bquorum_hash\x18\x02 \x01(\x0c\x12\x11\n\tsignature\x18\x03 \x01(\x0c\x12\r\n\x05round\x18\x04 \x01(\r\x12\x15\n\rblock_id_hash\x18\x05 \x01(\x0c\x12\x13\n\x0bquorum_type\x18\x06 \x01(\r\"\x90\x01\n\x10ResponseMetadata\x12\x0e\n\x06height\x18\x01 \x01(\x04\x12 \n\x18\x63ore_chain_locked_height\x18\x02 \x01(\r\x12\r\n\x05\x65poch\x18\x03 \x01(\r\x12\x0f\n\x07time_ms\x18\x04 \x01(\x04\x12\x18\n\x10protocol_version\x18\x05 \x01(\r\x12\x10\n\x08\x63hain_id\x18\x06 \x01(\t\"L\n\x1dStateTransitionBroadcastError\x12\x0c\n\x04\x63ode\x18\x01 \x01(\r\x12\x0f\n\x07message\x18\x02 \x01(\t\x12\x0c\n\x04\x64\x61ta\x18\x03 \x01(\x0c\";\n\x1f\x42roadcastStateTransitionRequest\x12\x18\n\x10state_transition\x18\x01 \x01(\x0c\"\"\n BroadcastStateTransitionResponse\"\xa4\x01\n\x12GetIdentityRequest\x12P\n\x02v0\x18\x01 \x01(\x0b\x32\x42.org.dash.platform.dapi.v0.GetIdentityRequest.GetIdentityRequestV0H\x00\x1a\x31\n\x14GetIdentityRequestV0\x12\n\n\x02id\x18\x01 \x01(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\xc1\x01\n\x17GetIdentityNonceRequest\x12Z\n\x02v0\x18\x01 \x01(\x0b\x32L.org.dash.platform.dapi.v0.GetIdentityNonceRequest.GetIdentityNonceRequestV0H\x00\x1a?\n\x19GetIdentityNonceRequestV0\x12\x13\n\x0bidentity_id\x18\x01 \x01(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\xf6\x01\n\x1fGetIdentityContractNonceRequest\x12j\n\x02v0\x18\x01 \x01(\x0b\x32\\.org.dash.platform.dapi.v0.GetIdentityContractNonceRequest.GetIdentityContractNonceRequestV0H\x00\x1a\\\n!GetIdentityContractNonceRequestV0\x12\x13\n\x0bidentity_id\x18\x01 \x01(\x0c\x12\x13\n\x0b\x63ontract_id\x18\x02 \x01(\x0c\x12\r\n\x05prove\x18\x03 \x01(\x08\x42\t\n\x07version\"\xc0\x01\n\x19GetIdentityBalanceRequest\x12^\n\x02v0\x18\x01 \x01(\x0b\x32P.org.dash.platform.dapi.v0.GetIdentityBalanceRequest.GetIdentityBalanceRequestV0H\x00\x1a\x38\n\x1bGetIdentityBalanceRequestV0\x12\n\n\x02id\x18\x01 \x01(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\xec\x01\n$GetIdentityBalanceAndRevisionRequest\x12t\n\x02v0\x18\x01 \x01(\x0b\x32\x66.org.dash.platform.dapi.v0.GetIdentityBalanceAndRevisionRequest.GetIdentityBalanceAndRevisionRequestV0H\x00\x1a\x43\n&GetIdentityBalanceAndRevisionRequestV0\x12\n\n\x02id\x18\x01 \x01(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\x9e\x02\n\x13GetIdentityResponse\x12R\n\x02v0\x18\x01 \x01(\x0b\x32\x44.org.dash.platform.dapi.v0.GetIdentityResponse.GetIdentityResponseV0H\x00\x1a\xa7\x01\n\x15GetIdentityResponseV0\x12\x12\n\x08identity\x18\x01 \x01(\x0cH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\xb8\x02\n\x18GetIdentityNonceResponse\x12\\\n\x02v0\x18\x01 \x01(\x0b\x32N.org.dash.platform.dapi.v0.GetIdentityNonceResponse.GetIdentityNonceResponseV0H\x00\x1a\xb2\x01\n\x1aGetIdentityNonceResponseV0\x12\x18\n\x0eidentity_nonce\x18\x01 \x01(\x04H\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\xe1\x02\n GetIdentityContractNonceResponse\x12l\n\x02v0\x18\x01 \x01(\x0b\x32^.org.dash.platform.dapi.v0.GetIdentityContractNonceResponse.GetIdentityContractNonceResponseV0H\x00\x1a\xc3\x01\n\"GetIdentityContractNonceResponseV0\x12!\n\x17identity_contract_nonce\x18\x01 \x01(\x04H\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\xb9\x02\n\x1aGetIdentityBalanceResponse\x12`\n\x02v0\x18\x01 \x01(\x0b\x32R.org.dash.platform.dapi.v0.GetIdentityBalanceResponse.GetIdentityBalanceResponseV0H\x00\x1a\xad\x01\n\x1cGetIdentityBalanceResponseV0\x12\x11\n\x07\x62\x61lance\x18\x01 \x01(\x04H\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\xa9\x04\n%GetIdentityBalanceAndRevisionResponse\x12v\n\x02v0\x18\x01 \x01(\x0b\x32h.org.dash.platform.dapi.v0.GetIdentityBalanceAndRevisionResponse.GetIdentityBalanceAndRevisionResponseV0H\x00\x1a\xfc\x02\n\'GetIdentityBalanceAndRevisionResponseV0\x12\x9b\x01\n\x14\x62\x61lance_and_revision\x18\x01 \x01(\x0b\x32{.org.dash.platform.dapi.v0.GetIdentityBalanceAndRevisionResponse.GetIdentityBalanceAndRevisionResponseV0.BalanceAndRevisionH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\x37\n\x12\x42\x61lanceAndRevision\x12\x0f\n\x07\x62\x61lance\x18\x01 \x01(\x04\x12\x10\n\x08revision\x18\x02 \x01(\x04\x42\x08\n\x06resultB\t\n\x07version\"\xd1\x01\n\x0eKeyRequestType\x12\x36\n\x08\x61ll_keys\x18\x01 \x01(\x0b\x32\".org.dash.platform.dapi.v0.AllKeysH\x00\x12@\n\rspecific_keys\x18\x02 \x01(\x0b\x32\'.org.dash.platform.dapi.v0.SpecificKeysH\x00\x12:\n\nsearch_key\x18\x03 \x01(\x0b\x32$.org.dash.platform.dapi.v0.SearchKeyH\x00\x42\t\n\x07request\"\t\n\x07\x41llKeys\"\x1f\n\x0cSpecificKeys\x12\x0f\n\x07key_ids\x18\x01 \x03(\r\"\xb6\x01\n\tSearchKey\x12I\n\x0bpurpose_map\x18\x01 \x03(\x0b\x32\x34.org.dash.platform.dapi.v0.SearchKey.PurposeMapEntry\x1a^\n\x0fPurposeMapEntry\x12\x0b\n\x03key\x18\x01 \x01(\r\x12:\n\x05value\x18\x02 \x01(\x0b\x32+.org.dash.platform.dapi.v0.SecurityLevelMap:\x02\x38\x01\"\xbf\x02\n\x10SecurityLevelMap\x12]\n\x12security_level_map\x18\x01 \x03(\x0b\x32\x41.org.dash.platform.dapi.v0.SecurityLevelMap.SecurityLevelMapEntry\x1aw\n\x15SecurityLevelMapEntry\x12\x0b\n\x03key\x18\x01 \x01(\r\x12M\n\x05value\x18\x02 \x01(\x0e\x32>.org.dash.platform.dapi.v0.SecurityLevelMap.KeyKindRequestType:\x02\x38\x01\"S\n\x12KeyKindRequestType\x12\x1f\n\x1b\x43URRENT_KEY_OF_KIND_REQUEST\x10\x00\x12\x1c\n\x18\x41LL_KEYS_OF_KIND_REQUEST\x10\x01\"\xda\x02\n\x16GetIdentityKeysRequest\x12X\n\x02v0\x18\x01 \x01(\x0b\x32J.org.dash.platform.dapi.v0.GetIdentityKeysRequest.GetIdentityKeysRequestV0H\x00\x1a\xda\x01\n\x18GetIdentityKeysRequestV0\x12\x13\n\x0bidentity_id\x18\x01 \x01(\x0c\x12?\n\x0crequest_type\x18\x02 \x01(\x0b\x32).org.dash.platform.dapi.v0.KeyRequestType\x12+\n\x05limit\x18\x03 \x01(\x0b\x32\x1c.google.protobuf.UInt32Value\x12,\n\x06offset\x18\x04 \x01(\x0b\x32\x1c.google.protobuf.UInt32Value\x12\r\n\x05prove\x18\x05 \x01(\x08\x42\t\n\x07version\"\x99\x03\n\x17GetIdentityKeysResponse\x12Z\n\x02v0\x18\x01 \x01(\x0b\x32L.org.dash.platform.dapi.v0.GetIdentityKeysResponse.GetIdentityKeysResponseV0H\x00\x1a\x96\x02\n\x19GetIdentityKeysResponseV0\x12\x61\n\x04keys\x18\x01 \x01(\x0b\x32Q.org.dash.platform.dapi.v0.GetIdentityKeysResponse.GetIdentityKeysResponseV0.KeysH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\x1a\n\x04Keys\x12\x12\n\nkeys_bytes\x18\x01 \x03(\x0c\x42\x08\n\x06resultB\t\n\x07version\"\xef\x02\n GetIdentitiesContractKeysRequest\x12l\n\x02v0\x18\x01 \x01(\x0b\x32^.org.dash.platform.dapi.v0.GetIdentitiesContractKeysRequest.GetIdentitiesContractKeysRequestV0H\x00\x1a\xd1\x01\n\"GetIdentitiesContractKeysRequestV0\x12\x16\n\x0eidentities_ids\x18\x01 \x03(\x0c\x12\x13\n\x0b\x63ontract_id\x18\x02 \x01(\x0c\x12\x1f\n\x12\x64ocument_type_name\x18\x03 \x01(\tH\x00\x88\x01\x01\x12\x37\n\x08purposes\x18\x04 \x03(\x0e\x32%.org.dash.platform.dapi.v0.KeyPurpose\x12\r\n\x05prove\x18\x05 \x01(\x08\x42\x15\n\x13_document_type_nameB\t\n\x07version\"\xdf\x06\n!GetIdentitiesContractKeysResponse\x12n\n\x02v0\x18\x01 \x01(\x0b\x32`.org.dash.platform.dapi.v0.GetIdentitiesContractKeysResponse.GetIdentitiesContractKeysResponseV0H\x00\x1a\xbe\x05\n#GetIdentitiesContractKeysResponseV0\x12\x8a\x01\n\x0fidentities_keys\x18\x01 \x01(\x0b\x32o.org.dash.platform.dapi.v0.GetIdentitiesContractKeysResponse.GetIdentitiesContractKeysResponseV0.IdentitiesKeysH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1aY\n\x0bPurposeKeys\x12\x36\n\x07purpose\x18\x01 \x01(\x0e\x32%.org.dash.platform.dapi.v0.KeyPurpose\x12\x12\n\nkeys_bytes\x18\x02 \x03(\x0c\x1a\x9f\x01\n\x0cIdentityKeys\x12\x13\n\x0bidentity_id\x18\x01 \x01(\x0c\x12z\n\x04keys\x18\x02 \x03(\x0b\x32l.org.dash.platform.dapi.v0.GetIdentitiesContractKeysResponse.GetIdentitiesContractKeysResponseV0.PurposeKeys\x1a\x90\x01\n\x0eIdentitiesKeys\x12~\n\x07\x65ntries\x18\x01 \x03(\x0b\x32m.org.dash.platform.dapi.v0.GetIdentitiesContractKeysResponse.GetIdentitiesContractKeysResponseV0.IdentityKeysB\x08\n\x06resultB\t\n\x07version\"\xcb\x0b\n\x10GetProofsRequest\x12L\n\x02v0\x18\x01 \x01(\x0b\x32>.org.dash.platform.dapi.v0.GetProofsRequest.GetProofsRequestV0H\x00\x1a\xdd\n\n\x12GetProofsRequestV0\x12\x62\n\nidentities\x18\x01 \x03(\x0b\x32N.org.dash.platform.dapi.v0.GetProofsRequest.GetProofsRequestV0.IdentityRequest\x12\x61\n\tcontracts\x18\x02 \x03(\x0b\x32N.org.dash.platform.dapi.v0.GetProofsRequest.GetProofsRequestV0.ContractRequest\x12\x61\n\tdocuments\x18\x03 \x03(\x0b\x32N.org.dash.platform.dapi.v0.GetProofsRequest.GetProofsRequestV0.DocumentRequest\x12_\n\x05votes\x18\x04 \x03(\x0b\x32P.org.dash.platform.dapi.v0.GetProofsRequest.GetProofsRequestV0.VoteStatusRequest\x1a\xd5\x02\n\x0f\x44ocumentRequest\x12\x13\n\x0b\x63ontract_id\x18\x01 \x01(\x0c\x12\x15\n\rdocument_type\x18\x02 \x01(\t\x12#\n\x1b\x64ocument_type_keeps_history\x18\x03 \x01(\x08\x12\x13\n\x0b\x64ocument_id\x18\x04 \x01(\x0c\x12\x89\x01\n\x19\x64ocument_contested_status\x18\x05 \x01(\x0e\x32\x66.org.dash.platform.dapi.v0.GetProofsRequest.GetProofsRequestV0.DocumentRequest.DocumentContestedStatus\"P\n\x17\x44ocumentContestedStatus\x12\x11\n\rNOT_CONTESTED\x10\x00\x12\x13\n\x0fMAYBE_CONTESTED\x10\x01\x12\r\n\tCONTESTED\x10\x02\x1a\xd1\x01\n\x0fIdentityRequest\x12\x13\n\x0bidentity_id\x18\x01 \x01(\x0c\x12i\n\x0crequest_type\x18\x02 \x01(\x0e\x32S.org.dash.platform.dapi.v0.GetProofsRequest.GetProofsRequestV0.IdentityRequest.Type\">\n\x04Type\x12\x11\n\rFULL_IDENTITY\x10\x00\x12\x0b\n\x07\x42\x41LANCE\x10\x01\x12\x08\n\x04KEYS\x10\x02\x12\x0c\n\x08REVISION\x10\x03\x1a&\n\x0f\x43ontractRequest\x12\x13\n\x0b\x63ontract_id\x18\x01 \x01(\x0c\x1a\xe7\x02\n\x11VoteStatusRequest\x12\xa5\x01\n&contested_resource_vote_status_request\x18\x01 \x01(\x0b\x32s.org.dash.platform.dapi.v0.GetProofsRequest.GetProofsRequestV0.VoteStatusRequest.ContestedResourceVoteStatusRequestH\x00\x1a\x99\x01\n\"ContestedResourceVoteStatusRequest\x12\x13\n\x0b\x63ontract_id\x18\x01 \x01(\x0c\x12\x1a\n\x12\x64ocument_type_name\x18\x02 \x01(\t\x12\x12\n\nindex_name\x18\x03 \x01(\t\x12\x14\n\x0cindex_values\x18\x04 \x03(\x0c\x12\x18\n\x10voter_identifier\x18\x05 \x01(\x0c\x42\x0e\n\x0crequest_typeB\t\n\x07version\"\x82\x02\n\x11GetProofsResponse\x12N\n\x02v0\x18\x01 \x01(\x0b\x32@.org.dash.platform.dapi.v0.GetProofsResponse.GetProofsResponseV0H\x00\x1a\x91\x01\n\x13GetProofsResponseV0\x12\x31\n\x05proof\x18\x01 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x02 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\xb4\x01\n\x16GetDataContractRequest\x12X\n\x02v0\x18\x01 \x01(\x0b\x32J.org.dash.platform.dapi.v0.GetDataContractRequest.GetDataContractRequestV0H\x00\x1a\x35\n\x18GetDataContractRequestV0\x12\n\n\x02id\x18\x01 \x01(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\xb3\x02\n\x17GetDataContractResponse\x12Z\n\x02v0\x18\x01 \x01(\x0b\x32L.org.dash.platform.dapi.v0.GetDataContractResponse.GetDataContractResponseV0H\x00\x1a\xb0\x01\n\x19GetDataContractResponseV0\x12\x17\n\rdata_contract\x18\x01 \x01(\x0cH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\xb9\x01\n\x17GetDataContractsRequest\x12Z\n\x02v0\x18\x01 \x01(\x0b\x32L.org.dash.platform.dapi.v0.GetDataContractsRequest.GetDataContractsRequestV0H\x00\x1a\x37\n\x19GetDataContractsRequestV0\x12\x0b\n\x03ids\x18\x01 \x03(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\xcf\x04\n\x18GetDataContractsResponse\x12\\\n\x02v0\x18\x01 \x01(\x0b\x32N.org.dash.platform.dapi.v0.GetDataContractsResponse.GetDataContractsResponseV0H\x00\x1a[\n\x11\x44\x61taContractEntry\x12\x12\n\nidentifier\x18\x01 \x01(\x0c\x12\x32\n\rdata_contract\x18\x02 \x01(\x0b\x32\x1b.google.protobuf.BytesValue\x1au\n\rDataContracts\x12\x64\n\x15\x64\x61ta_contract_entries\x18\x01 \x03(\x0b\x32\x45.org.dash.platform.dapi.v0.GetDataContractsResponse.DataContractEntry\x1a\xf5\x01\n\x1aGetDataContractsResponseV0\x12[\n\x0e\x64\x61ta_contracts\x18\x01 \x01(\x0b\x32\x41.org.dash.platform.dapi.v0.GetDataContractsResponse.DataContractsH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\xc1\x02\n\x1dGetDataContractHistoryRequest\x12\x66\n\x02v0\x18\x01 \x01(\x0b\x32X.org.dash.platform.dapi.v0.GetDataContractHistoryRequest.GetDataContractHistoryRequestV0H\x00\x1a\xac\x01\n\x1fGetDataContractHistoryRequestV0\x12\n\n\x02id\x18\x01 \x01(\x0c\x12+\n\x05limit\x18\x02 \x01(\x0b\x32\x1c.google.protobuf.UInt32Value\x12,\n\x06offset\x18\x03 \x01(\x0b\x32\x1c.google.protobuf.UInt32Value\x12\x13\n\x0bstart_at_ms\x18\x04 \x01(\x04\x12\r\n\x05prove\x18\x05 \x01(\x08\x42\t\n\x07version\"\xae\x05\n\x1eGetDataContractHistoryResponse\x12h\n\x02v0\x18\x01 \x01(\x0b\x32Z.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.GetDataContractHistoryResponseV0H\x00\x1a\x96\x04\n GetDataContractHistoryResponseV0\x12\x8f\x01\n\x15\x64\x61ta_contract_history\x18\x01 \x01(\x0b\x32n.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.GetDataContractHistoryResponseV0.DataContractHistoryH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\x37\n\x18\x44\x61taContractHistoryEntry\x12\x0c\n\x04\x64\x61te\x18\x01 \x01(\x04\x12\r\n\x05value\x18\x02 \x01(\x0c\x1a\xaa\x01\n\x13\x44\x61taContractHistory\x12\x92\x01\n\x15\x64\x61ta_contract_entries\x18\x01 \x03(\x0b\x32s.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.GetDataContractHistoryResponseV0.DataContractHistoryEntryB\x08\n\x06resultB\t\n\x07version\"\xb2\x02\n\x13GetDocumentsRequest\x12R\n\x02v0\x18\x01 \x01(\x0b\x32\x44.org.dash.platform.dapi.v0.GetDocumentsRequest.GetDocumentsRequestV0H\x00\x1a\xbb\x01\n\x15GetDocumentsRequestV0\x12\x18\n\x10\x64\x61ta_contract_id\x18\x01 \x01(\x0c\x12\x15\n\rdocument_type\x18\x02 \x01(\t\x12\r\n\x05where\x18\x03 \x01(\x0c\x12\x10\n\x08order_by\x18\x04 \x01(\x0c\x12\r\n\x05limit\x18\x05 \x01(\r\x12\x15\n\x0bstart_after\x18\x06 \x01(\x0cH\x00\x12\x12\n\x08start_at\x18\x07 \x01(\x0cH\x00\x12\r\n\x05prove\x18\x08 \x01(\x08\x42\x07\n\x05startB\t\n\x07version\"\x95\x03\n\x14GetDocumentsResponse\x12T\n\x02v0\x18\x01 \x01(\x0b\x32\x46.org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocumentsResponseV0H\x00\x1a\x9b\x02\n\x16GetDocumentsResponseV0\x12\x65\n\tdocuments\x18\x01 \x01(\x0b\x32P.org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocumentsResponseV0.DocumentsH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\x1e\n\tDocuments\x12\x11\n\tdocuments\x18\x01 \x03(\x0c\x42\x08\n\x06resultB\t\n\x07version\"\xed\x01\n!GetIdentityByPublicKeyHashRequest\x12n\n\x02v0\x18\x01 \x01(\x0b\x32`.org.dash.platform.dapi.v0.GetIdentityByPublicKeyHashRequest.GetIdentityByPublicKeyHashRequestV0H\x00\x1aM\n#GetIdentityByPublicKeyHashRequestV0\x12\x17\n\x0fpublic_key_hash\x18\x01 \x01(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\xda\x02\n\"GetIdentityByPublicKeyHashResponse\x12p\n\x02v0\x18\x01 \x01(\x0b\x32\x62.org.dash.platform.dapi.v0.GetIdentityByPublicKeyHashResponse.GetIdentityByPublicKeyHashResponseV0H\x00\x1a\xb6\x01\n$GetIdentityByPublicKeyHashResponseV0\x12\x12\n\x08identity\x18\x01 \x01(\x0cH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\xfb\x01\n#WaitForStateTransitionResultRequest\x12r\n\x02v0\x18\x01 \x01(\x0b\x32\x64.org.dash.platform.dapi.v0.WaitForStateTransitionResultRequest.WaitForStateTransitionResultRequestV0H\x00\x1aU\n%WaitForStateTransitionResultRequestV0\x12\x1d\n\x15state_transition_hash\x18\x01 \x01(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\x99\x03\n$WaitForStateTransitionResultResponse\x12t\n\x02v0\x18\x01 \x01(\x0b\x32\x66.org.dash.platform.dapi.v0.WaitForStateTransitionResultResponse.WaitForStateTransitionResultResponseV0H\x00\x1a\xef\x01\n&WaitForStateTransitionResultResponseV0\x12I\n\x05\x65rror\x18\x01 \x01(\x0b\x32\x38.org.dash.platform.dapi.v0.StateTransitionBroadcastErrorH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\xc4\x01\n\x19GetConsensusParamsRequest\x12^\n\x02v0\x18\x01 \x01(\x0b\x32P.org.dash.platform.dapi.v0.GetConsensusParamsRequest.GetConsensusParamsRequestV0H\x00\x1a<\n\x1bGetConsensusParamsRequestV0\x12\x0e\n\x06height\x18\x01 \x01(\x05\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\x9c\x04\n\x1aGetConsensusParamsResponse\x12`\n\x02v0\x18\x01 \x01(\x0b\x32R.org.dash.platform.dapi.v0.GetConsensusParamsResponse.GetConsensusParamsResponseV0H\x00\x1aP\n\x14\x43onsensusParamsBlock\x12\x11\n\tmax_bytes\x18\x01 \x01(\t\x12\x0f\n\x07max_gas\x18\x02 \x01(\t\x12\x14\n\x0ctime_iota_ms\x18\x03 \x01(\t\x1a\x62\n\x17\x43onsensusParamsEvidence\x12\x1a\n\x12max_age_num_blocks\x18\x01 \x01(\t\x12\x18\n\x10max_age_duration\x18\x02 \x01(\t\x12\x11\n\tmax_bytes\x18\x03 \x01(\t\x1a\xda\x01\n\x1cGetConsensusParamsResponseV0\x12Y\n\x05\x62lock\x18\x01 \x01(\x0b\x32J.org.dash.platform.dapi.v0.GetConsensusParamsResponse.ConsensusParamsBlock\x12_\n\x08\x65vidence\x18\x02 \x01(\x0b\x32M.org.dash.platform.dapi.v0.GetConsensusParamsResponse.ConsensusParamsEvidenceB\t\n\x07version\"\xe4\x01\n%GetProtocolVersionUpgradeStateRequest\x12v\n\x02v0\x18\x01 \x01(\x0b\x32h.org.dash.platform.dapi.v0.GetProtocolVersionUpgradeStateRequest.GetProtocolVersionUpgradeStateRequestV0H\x00\x1a\x38\n\'GetProtocolVersionUpgradeStateRequestV0\x12\r\n\x05prove\x18\x01 \x01(\x08\x42\t\n\x07version\"\xb5\x05\n&GetProtocolVersionUpgradeStateResponse\x12x\n\x02v0\x18\x01 \x01(\x0b\x32j.org.dash.platform.dapi.v0.GetProtocolVersionUpgradeStateResponse.GetProtocolVersionUpgradeStateResponseV0H\x00\x1a\x85\x04\n(GetProtocolVersionUpgradeStateResponseV0\x12\x87\x01\n\x08versions\x18\x01 \x01(\x0b\x32s.org.dash.platform.dapi.v0.GetProtocolVersionUpgradeStateResponse.GetProtocolVersionUpgradeStateResponseV0.VersionsH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\x96\x01\n\x08Versions\x12\x89\x01\n\x08versions\x18\x01 \x03(\x0b\x32w.org.dash.platform.dapi.v0.GetProtocolVersionUpgradeStateResponse.GetProtocolVersionUpgradeStateResponseV0.VersionEntry\x1a:\n\x0cVersionEntry\x12\x16\n\x0eversion_number\x18\x01 \x01(\r\x12\x12\n\nvote_count\x18\x02 \x01(\rB\x08\n\x06resultB\t\n\x07version\"\xa3\x02\n*GetProtocolVersionUpgradeVoteStatusRequest\x12\x80\x01\n\x02v0\x18\x01 \x01(\x0b\x32r.org.dash.platform.dapi.v0.GetProtocolVersionUpgradeVoteStatusRequest.GetProtocolVersionUpgradeVoteStatusRequestV0H\x00\x1ag\n,GetProtocolVersionUpgradeVoteStatusRequestV0\x12\x19\n\x11start_pro_tx_hash\x18\x01 \x01(\x0c\x12\r\n\x05\x63ount\x18\x02 \x01(\r\x12\r\n\x05prove\x18\x03 \x01(\x08\x42\t\n\x07version\"\xef\x05\n+GetProtocolVersionUpgradeVoteStatusResponse\x12\x82\x01\n\x02v0\x18\x01 \x01(\x0b\x32t.org.dash.platform.dapi.v0.GetProtocolVersionUpgradeVoteStatusResponse.GetProtocolVersionUpgradeVoteStatusResponseV0H\x00\x1a\xaf\x04\n-GetProtocolVersionUpgradeVoteStatusResponseV0\x12\x98\x01\n\x08versions\x18\x01 \x01(\x0b\x32\x83\x01.org.dash.platform.dapi.v0.GetProtocolVersionUpgradeVoteStatusResponse.GetProtocolVersionUpgradeVoteStatusResponseV0.VersionSignalsH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\xaf\x01\n\x0eVersionSignals\x12\x9c\x01\n\x0fversion_signals\x18\x01 \x03(\x0b\x32\x82\x01.org.dash.platform.dapi.v0.GetProtocolVersionUpgradeVoteStatusResponse.GetProtocolVersionUpgradeVoteStatusResponseV0.VersionSignal\x1a\x35\n\rVersionSignal\x12\x13\n\x0bpro_tx_hash\x18\x01 \x01(\x0c\x12\x0f\n\x07version\x18\x02 \x01(\rB\x08\n\x06resultB\t\n\x07version\"\xf5\x01\n\x14GetEpochsInfoRequest\x12T\n\x02v0\x18\x01 \x01(\x0b\x32\x46.org.dash.platform.dapi.v0.GetEpochsInfoRequest.GetEpochsInfoRequestV0H\x00\x1a|\n\x16GetEpochsInfoRequestV0\x12\x31\n\x0bstart_epoch\x18\x01 \x01(\x0b\x32\x1c.google.protobuf.UInt32Value\x12\r\n\x05\x63ount\x18\x02 \x01(\r\x12\x11\n\tascending\x18\x03 \x01(\x08\x12\r\n\x05prove\x18\x04 \x01(\x08\x42\t\n\x07version\"\x91\x05\n\x15GetEpochsInfoResponse\x12V\n\x02v0\x18\x01 \x01(\x0b\x32H.org.dash.platform.dapi.v0.GetEpochsInfoResponse.GetEpochsInfoResponseV0H\x00\x1a\x94\x04\n\x17GetEpochsInfoResponseV0\x12\x65\n\x06\x65pochs\x18\x01 \x01(\x0b\x32S.org.dash.platform.dapi.v0.GetEpochsInfoResponse.GetEpochsInfoResponseV0.EpochInfosH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1au\n\nEpochInfos\x12g\n\x0b\x65poch_infos\x18\x01 \x03(\x0b\x32R.org.dash.platform.dapi.v0.GetEpochsInfoResponse.GetEpochsInfoResponseV0.EpochInfo\x1a\x9e\x01\n\tEpochInfo\x12\x0e\n\x06number\x18\x01 \x01(\r\x12\x1a\n\x12\x66irst_block_height\x18\x02 \x01(\x04\x12\x1f\n\x17\x66irst_core_block_height\x18\x03 \x01(\r\x12\x12\n\nstart_time\x18\x04 \x01(\x04\x12\x16\n\x0e\x66\x65\x65_multiplier\x18\x05 \x01(\x01\x12\x18\n\x10protocol_version\x18\x06 \x01(\rB\x08\n\x06resultB\t\n\x07version\"\xde\x04\n\x1cGetContestedResourcesRequest\x12\x64\n\x02v0\x18\x01 \x01(\x0b\x32V.org.dash.platform.dapi.v0.GetContestedResourcesRequest.GetContestedResourcesRequestV0H\x00\x1a\xcc\x03\n\x1eGetContestedResourcesRequestV0\x12\x13\n\x0b\x63ontract_id\x18\x01 \x01(\x0c\x12\x1a\n\x12\x64ocument_type_name\x18\x02 \x01(\t\x12\x12\n\nindex_name\x18\x03 \x01(\t\x12\x1a\n\x12start_index_values\x18\x04 \x03(\x0c\x12\x18\n\x10\x65nd_index_values\x18\x05 \x03(\x0c\x12\x89\x01\n\x13start_at_value_info\x18\x06 \x01(\x0b\x32g.org.dash.platform.dapi.v0.GetContestedResourcesRequest.GetContestedResourcesRequestV0.StartAtValueInfoH\x00\x88\x01\x01\x12\x12\n\x05\x63ount\x18\x07 \x01(\rH\x01\x88\x01\x01\x12\x17\n\x0forder_ascending\x18\x08 \x01(\x08\x12\r\n\x05prove\x18\t \x01(\x08\x1a\x45\n\x10StartAtValueInfo\x12\x13\n\x0bstart_value\x18\x01 \x01(\x0c\x12\x1c\n\x14start_value_included\x18\x02 \x01(\x08\x42\x16\n\x14_start_at_value_infoB\x08\n\x06_countB\t\n\x07version\"\x88\x04\n\x1dGetContestedResourcesResponse\x12\x66\n\x02v0\x18\x01 \x01(\x0b\x32X.org.dash.platform.dapi.v0.GetContestedResourcesResponse.GetContestedResourcesResponseV0H\x00\x1a\xf3\x02\n\x1fGetContestedResourcesResponseV0\x12\x95\x01\n\x19\x63ontested_resource_values\x18\x01 \x01(\x0b\x32p.org.dash.platform.dapi.v0.GetContestedResourcesResponse.GetContestedResourcesResponseV0.ContestedResourceValuesH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a<\n\x17\x43ontestedResourceValues\x12!\n\x19\x63ontested_resource_values\x18\x01 \x03(\x0c\x42\x08\n\x06resultB\t\n\x07version\"\xca\x05\n\x1cGetVotePollsByEndDateRequest\x12\x64\n\x02v0\x18\x01 \x01(\x0b\x32V.org.dash.platform.dapi.v0.GetVotePollsByEndDateRequest.GetVotePollsByEndDateRequestV0H\x00\x1a\xb8\x04\n\x1eGetVotePollsByEndDateRequestV0\x12\x84\x01\n\x0fstart_time_info\x18\x01 \x01(\x0b\x32\x66.org.dash.platform.dapi.v0.GetVotePollsByEndDateRequest.GetVotePollsByEndDateRequestV0.StartAtTimeInfoH\x00\x88\x01\x01\x12\x80\x01\n\rend_time_info\x18\x02 \x01(\x0b\x32\x64.org.dash.platform.dapi.v0.GetVotePollsByEndDateRequest.GetVotePollsByEndDateRequestV0.EndAtTimeInfoH\x01\x88\x01\x01\x12\x12\n\x05limit\x18\x03 \x01(\rH\x02\x88\x01\x01\x12\x13\n\x06offset\x18\x04 \x01(\rH\x03\x88\x01\x01\x12\x11\n\tascending\x18\x05 \x01(\x08\x12\r\n\x05prove\x18\x06 \x01(\x08\x1a\x45\n\x0fStartAtTimeInfo\x12\x15\n\rstart_time_ms\x18\x01 \x01(\x04\x12\x1b\n\x13start_time_included\x18\x02 \x01(\x08\x1a?\n\rEndAtTimeInfo\x12\x13\n\x0b\x65nd_time_ms\x18\x01 \x01(\x04\x12\x19\n\x11\x65nd_time_included\x18\x02 \x01(\x08\x42\x12\n\x10_start_time_infoB\x10\n\x0e_end_time_infoB\x08\n\x06_limitB\t\n\x07_offsetB\t\n\x07version\"\xff\x05\n\x1dGetVotePollsByEndDateResponse\x12\x66\n\x02v0\x18\x01 \x01(\x0b\x32X.org.dash.platform.dapi.v0.GetVotePollsByEndDateResponse.GetVotePollsByEndDateResponseV0H\x00\x1a\xea\x04\n\x1fGetVotePollsByEndDateResponseV0\x12\x9c\x01\n\x18vote_polls_by_timestamps\x18\x01 \x01(\x0b\x32x.org.dash.platform.dapi.v0.GetVotePollsByEndDateResponse.GetVotePollsByEndDateResponseV0.SerializedVotePollsByTimestampsH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1aR\n\x1eSerializedVotePollsByTimestamp\x12\x11\n\ttimestamp\x18\x01 \x01(\x04\x12\x1d\n\x15serialized_vote_polls\x18\x02 \x03(\x0c\x1a\xd7\x01\n\x1fSerializedVotePollsByTimestamps\x12\x99\x01\n\x18vote_polls_by_timestamps\x18\x01 \x03(\x0b\x32w.org.dash.platform.dapi.v0.GetVotePollsByEndDateResponse.GetVotePollsByEndDateResponseV0.SerializedVotePollsByTimestamp\x12\x18\n\x10\x66inished_results\x18\x02 \x01(\x08\x42\x08\n\x06resultB\t\n\x07version\"\xff\x06\n$GetContestedResourceVoteStateRequest\x12t\n\x02v0\x18\x01 \x01(\x0b\x32\x66.org.dash.platform.dapi.v0.GetContestedResourceVoteStateRequest.GetContestedResourceVoteStateRequestV0H\x00\x1a\xd5\x05\n&GetContestedResourceVoteStateRequestV0\x12\x13\n\x0b\x63ontract_id\x18\x01 \x01(\x0c\x12\x1a\n\x12\x64ocument_type_name\x18\x02 \x01(\t\x12\x12\n\nindex_name\x18\x03 \x01(\t\x12\x14\n\x0cindex_values\x18\x04 \x03(\x0c\x12\x86\x01\n\x0bresult_type\x18\x05 \x01(\x0e\x32q.org.dash.platform.dapi.v0.GetContestedResourceVoteStateRequest.GetContestedResourceVoteStateRequestV0.ResultType\x12\x36\n.allow_include_locked_and_abstaining_vote_tally\x18\x06 \x01(\x08\x12\xa3\x01\n\x18start_at_identifier_info\x18\x07 \x01(\x0b\x32|.org.dash.platform.dapi.v0.GetContestedResourceVoteStateRequest.GetContestedResourceVoteStateRequestV0.StartAtIdentifierInfoH\x00\x88\x01\x01\x12\x12\n\x05\x63ount\x18\x08 \x01(\rH\x01\x88\x01\x01\x12\r\n\x05prove\x18\t \x01(\x08\x1aT\n\x15StartAtIdentifierInfo\x12\x18\n\x10start_identifier\x18\x01 \x01(\x0c\x12!\n\x19start_identifier_included\x18\x02 \x01(\x08\"I\n\nResultType\x12\r\n\tDOCUMENTS\x10\x00\x12\x0e\n\nVOTE_TALLY\x10\x01\x12\x1c\n\x18\x44OCUMENTS_AND_VOTE_TALLY\x10\x02\x42\x1b\n\x19_start_at_identifier_infoB\x08\n\x06_countB\t\n\x07version\"\x8c\x0c\n%GetContestedResourceVoteStateResponse\x12v\n\x02v0\x18\x01 \x01(\x0b\x32h.org.dash.platform.dapi.v0.GetContestedResourceVoteStateResponse.GetContestedResourceVoteStateResponseV0H\x00\x1a\xdf\n\n\'GetContestedResourceVoteStateResponseV0\x12\xae\x01\n\x1d\x63ontested_resource_contenders\x18\x01 \x01(\x0b\x32\x84\x01.org.dash.platform.dapi.v0.GetContestedResourceVoteStateResponse.GetContestedResourceVoteStateResponseV0.ContestedResourceContendersH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\xd2\x03\n\x10\x46inishedVoteInfo\x12\xad\x01\n\x15\x66inished_vote_outcome\x18\x01 \x01(\x0e\x32\x8d\x01.org.dash.platform.dapi.v0.GetContestedResourceVoteStateResponse.GetContestedResourceVoteStateResponseV0.FinishedVoteInfo.FinishedVoteOutcome\x12\x1f\n\x12won_by_identity_id\x18\x02 \x01(\x0cH\x00\x88\x01\x01\x12 \n\x18\x66inished_at_block_height\x18\x03 \x01(\x04\x12%\n\x1d\x66inished_at_core_block_height\x18\x04 \x01(\r\x12!\n\x19\x66inished_at_block_time_ms\x18\x05 \x01(\x04\x12\x19\n\x11\x66inished_at_epoch\x18\x06 \x01(\r\"O\n\x13\x46inishedVoteOutcome\x12\x14\n\x10TOWARDS_IDENTITY\x10\x00\x12\n\n\x06LOCKED\x10\x01\x12\x16\n\x12NO_PREVIOUS_WINNER\x10\x02\x42\x15\n\x13_won_by_identity_id\x1a\xc4\x03\n\x1b\x43ontestedResourceContenders\x12\x86\x01\n\ncontenders\x18\x01 \x03(\x0b\x32r.org.dash.platform.dapi.v0.GetContestedResourceVoteStateResponse.GetContestedResourceVoteStateResponseV0.Contender\x12\x1f\n\x12\x61\x62stain_vote_tally\x18\x02 \x01(\rH\x00\x88\x01\x01\x12\x1c\n\x0flock_vote_tally\x18\x03 \x01(\rH\x01\x88\x01\x01\x12\x9a\x01\n\x12\x66inished_vote_info\x18\x04 \x01(\x0b\x32y.org.dash.platform.dapi.v0.GetContestedResourceVoteStateResponse.GetContestedResourceVoteStateResponseV0.FinishedVoteInfoH\x02\x88\x01\x01\x42\x15\n\x13_abstain_vote_tallyB\x12\n\x10_lock_vote_tallyB\x15\n\x13_finished_vote_info\x1ak\n\tContender\x12\x12\n\nidentifier\x18\x01 \x01(\x0c\x12\x17\n\nvote_count\x18\x02 \x01(\rH\x00\x88\x01\x01\x12\x15\n\x08\x64ocument\x18\x03 \x01(\x0cH\x01\x88\x01\x01\x42\r\n\x0b_vote_countB\x0b\n\t_documentB\x08\n\x06resultB\t\n\x07version\"\xd5\x05\n,GetContestedResourceVotersForIdentityRequest\x12\x84\x01\n\x02v0\x18\x01 \x01(\x0b\x32v.org.dash.platform.dapi.v0.GetContestedResourceVotersForIdentityRequest.GetContestedResourceVotersForIdentityRequestV0H\x00\x1a\x92\x04\n.GetContestedResourceVotersForIdentityRequestV0\x12\x13\n\x0b\x63ontract_id\x18\x01 \x01(\x0c\x12\x1a\n\x12\x64ocument_type_name\x18\x02 \x01(\t\x12\x12\n\nindex_name\x18\x03 \x01(\t\x12\x14\n\x0cindex_values\x18\x04 \x03(\x0c\x12\x15\n\rcontestant_id\x18\x05 \x01(\x0c\x12\xb4\x01\n\x18start_at_identifier_info\x18\x06 \x01(\x0b\x32\x8c\x01.org.dash.platform.dapi.v0.GetContestedResourceVotersForIdentityRequest.GetContestedResourceVotersForIdentityRequestV0.StartAtIdentifierInfoH\x00\x88\x01\x01\x12\x12\n\x05\x63ount\x18\x07 \x01(\rH\x01\x88\x01\x01\x12\x17\n\x0forder_ascending\x18\x08 \x01(\x08\x12\r\n\x05prove\x18\t \x01(\x08\x1aT\n\x15StartAtIdentifierInfo\x12\x18\n\x10start_identifier\x18\x01 \x01(\x0c\x12!\n\x19start_identifier_included\x18\x02 \x01(\x08\x42\x1b\n\x19_start_at_identifier_infoB\x08\n\x06_countB\t\n\x07version\"\xf1\x04\n-GetContestedResourceVotersForIdentityResponse\x12\x86\x01\n\x02v0\x18\x01 \x01(\x0b\x32x.org.dash.platform.dapi.v0.GetContestedResourceVotersForIdentityResponse.GetContestedResourceVotersForIdentityResponseV0H\x00\x1a\xab\x03\n/GetContestedResourceVotersForIdentityResponseV0\x12\xb6\x01\n\x19\x63ontested_resource_voters\x18\x01 \x01(\x0b\x32\x90\x01.org.dash.platform.dapi.v0.GetContestedResourceVotersForIdentityResponse.GetContestedResourceVotersForIdentityResponseV0.ContestedResourceVotersH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\x43\n\x17\x43ontestedResourceVoters\x12\x0e\n\x06voters\x18\x01 \x03(\x0c\x12\x18\n\x10\x66inished_results\x18\x02 \x01(\x08\x42\x08\n\x06resultB\t\n\x07version\"\xad\x05\n(GetContestedResourceIdentityVotesRequest\x12|\n\x02v0\x18\x01 \x01(\x0b\x32n.org.dash.platform.dapi.v0.GetContestedResourceIdentityVotesRequest.GetContestedResourceIdentityVotesRequestV0H\x00\x1a\xf7\x03\n*GetContestedResourceIdentityVotesRequestV0\x12\x13\n\x0bidentity_id\x18\x01 \x01(\x0c\x12+\n\x05limit\x18\x02 \x01(\x0b\x32\x1c.google.protobuf.UInt32Value\x12,\n\x06offset\x18\x03 \x01(\x0b\x32\x1c.google.protobuf.UInt32Value\x12\x17\n\x0forder_ascending\x18\x04 \x01(\x08\x12\xae\x01\n\x1astart_at_vote_poll_id_info\x18\x05 \x01(\x0b\x32\x84\x01.org.dash.platform.dapi.v0.GetContestedResourceIdentityVotesRequest.GetContestedResourceIdentityVotesRequestV0.StartAtVotePollIdInfoH\x00\x88\x01\x01\x12\r\n\x05prove\x18\x06 \x01(\x08\x1a\x61\n\x15StartAtVotePollIdInfo\x12 \n\x18start_at_poll_identifier\x18\x01 \x01(\x0c\x12&\n\x1estart_poll_identifier_included\x18\x02 \x01(\x08\x42\x1d\n\x1b_start_at_vote_poll_id_infoB\t\n\x07version\"\xc8\n\n)GetContestedResourceIdentityVotesResponse\x12~\n\x02v0\x18\x01 \x01(\x0b\x32p.org.dash.platform.dapi.v0.GetContestedResourceIdentityVotesResponse.GetContestedResourceIdentityVotesResponseV0H\x00\x1a\x8f\t\n+GetContestedResourceIdentityVotesResponseV0\x12\xa1\x01\n\x05votes\x18\x01 \x01(\x0b\x32\x8f\x01.org.dash.platform.dapi.v0.GetContestedResourceIdentityVotesResponse.GetContestedResourceIdentityVotesResponseV0.ContestedResourceIdentityVotesH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\xf7\x01\n\x1e\x43ontestedResourceIdentityVotes\x12\xba\x01\n!contested_resource_identity_votes\x18\x01 \x03(\x0b\x32\x8e\x01.org.dash.platform.dapi.v0.GetContestedResourceIdentityVotesResponse.GetContestedResourceIdentityVotesResponseV0.ContestedResourceIdentityVote\x12\x18\n\x10\x66inished_results\x18\x02 \x01(\x08\x1a\xad\x02\n\x12ResourceVoteChoice\x12\xad\x01\n\x10vote_choice_type\x18\x01 \x01(\x0e\x32\x92\x01.org.dash.platform.dapi.v0.GetContestedResourceIdentityVotesResponse.GetContestedResourceIdentityVotesResponseV0.ResourceVoteChoice.VoteChoiceType\x12\x18\n\x0bidentity_id\x18\x02 \x01(\x0cH\x00\x88\x01\x01\"=\n\x0eVoteChoiceType\x12\x14\n\x10TOWARDS_IDENTITY\x10\x00\x12\x0b\n\x07\x41\x42STAIN\x10\x01\x12\x08\n\x04LOCK\x10\x02\x42\x0e\n\x0c_identity_id\x1a\x95\x02\n\x1d\x43ontestedResourceIdentityVote\x12\x13\n\x0b\x63ontract_id\x18\x01 \x01(\x0c\x12\x1a\n\x12\x64ocument_type_name\x18\x02 \x01(\t\x12\'\n\x1fserialized_index_storage_values\x18\x03 \x03(\x0c\x12\x99\x01\n\x0bvote_choice\x18\x04 \x01(\x0b\x32\x83\x01.org.dash.platform.dapi.v0.GetContestedResourceIdentityVotesResponse.GetContestedResourceIdentityVotesResponseV0.ResourceVoteChoiceB\x08\n\x06resultB\t\n\x07version\"\xf0\x01\n%GetPrefundedSpecializedBalanceRequest\x12v\n\x02v0\x18\x01 \x01(\x0b\x32h.org.dash.platform.dapi.v0.GetPrefundedSpecializedBalanceRequest.GetPrefundedSpecializedBalanceRequestV0H\x00\x1a\x44\n\'GetPrefundedSpecializedBalanceRequestV0\x12\n\n\x02id\x18\x01 \x01(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\xe9\x02\n&GetPrefundedSpecializedBalanceResponse\x12x\n\x02v0\x18\x01 \x01(\x0b\x32j.org.dash.platform.dapi.v0.GetPrefundedSpecializedBalanceResponse.GetPrefundedSpecializedBalanceResponseV0H\x00\x1a\xb9\x01\n(GetPrefundedSpecializedBalanceResponseV0\x12\x11\n\x07\x62\x61lance\x18\x01 \x01(\x04H\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\xc4\x01\n\x16GetPathElementsRequest\x12X\n\x02v0\x18\x01 \x01(\x0b\x32J.org.dash.platform.dapi.v0.GetPathElementsRequest.GetPathElementsRequestV0H\x00\x1a\x45\n\x18GetPathElementsRequestV0\x12\x0c\n\x04path\x18\x01 \x03(\x0c\x12\x0c\n\x04keys\x18\x02 \x03(\x0c\x12\r\n\x05prove\x18\x03 \x01(\x08\x42\t\n\x07version\"\xa3\x03\n\x17GetPathElementsResponse\x12Z\n\x02v0\x18\x01 \x01(\x0b\x32L.org.dash.platform.dapi.v0.GetPathElementsResponse.GetPathElementsResponseV0H\x00\x1a\xa0\x02\n\x19GetPathElementsResponseV0\x12i\n\x08\x65lements\x18\x01 \x01(\x0b\x32U.org.dash.platform.dapi.v0.GetPathElementsResponse.GetPathElementsResponseV0.ElementsH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\x1c\n\x08\x45lements\x12\x10\n\x08\x65lements\x18\x01 \x03(\x0c\x42\x08\n\x06resultB\t\n\x07version*Z\n\nKeyPurpose\x12\x12\n\x0e\x41UTHENTICATION\x10\x00\x12\x0e\n\nENCRYPTION\x10\x01\x12\x0e\n\nDECRYPTION\x10\x02\x12\x0c\n\x08TRANSFER\x10\x03\x12\n\n\x06VOTING\x10\x05\x32\xa1\x1d\n\x08Platform\x12\x93\x01\n\x18\x62roadcastStateTransition\x12:.org.dash.platform.dapi.v0.BroadcastStateTransitionRequest\x1a;.org.dash.platform.dapi.v0.BroadcastStateTransitionResponse\x12l\n\x0bgetIdentity\x12-.org.dash.platform.dapi.v0.GetIdentityRequest\x1a..org.dash.platform.dapi.v0.GetIdentityResponse\x12x\n\x0fgetIdentityKeys\x12\x31.org.dash.platform.dapi.v0.GetIdentityKeysRequest\x1a\x32.org.dash.platform.dapi.v0.GetIdentityKeysResponse\x12\x96\x01\n\x19getIdentitiesContractKeys\x12;.org.dash.platform.dapi.v0.GetIdentitiesContractKeysRequest\x1a<.org.dash.platform.dapi.v0.GetIdentitiesContractKeysResponse\x12{\n\x10getIdentityNonce\x12\x32.org.dash.platform.dapi.v0.GetIdentityNonceRequest\x1a\x33.org.dash.platform.dapi.v0.GetIdentityNonceResponse\x12\x93\x01\n\x18getIdentityContractNonce\x12:.org.dash.platform.dapi.v0.GetIdentityContractNonceRequest\x1a;.org.dash.platform.dapi.v0.GetIdentityContractNonceResponse\x12\x81\x01\n\x12getIdentityBalance\x12\x34.org.dash.platform.dapi.v0.GetIdentityBalanceRequest\x1a\x35.org.dash.platform.dapi.v0.GetIdentityBalanceResponse\x12\xa2\x01\n\x1dgetIdentityBalanceAndRevision\x12?.org.dash.platform.dapi.v0.GetIdentityBalanceAndRevisionRequest\x1a@.org.dash.platform.dapi.v0.GetIdentityBalanceAndRevisionResponse\x12\x66\n\tgetProofs\x12+.org.dash.platform.dapi.v0.GetProofsRequest\x1a,.org.dash.platform.dapi.v0.GetProofsResponse\x12x\n\x0fgetDataContract\x12\x31.org.dash.platform.dapi.v0.GetDataContractRequest\x1a\x32.org.dash.platform.dapi.v0.GetDataContractResponse\x12\x8d\x01\n\x16getDataContractHistory\x12\x38.org.dash.platform.dapi.v0.GetDataContractHistoryRequest\x1a\x39.org.dash.platform.dapi.v0.GetDataContractHistoryResponse\x12{\n\x10getDataContracts\x12\x32.org.dash.platform.dapi.v0.GetDataContractsRequest\x1a\x33.org.dash.platform.dapi.v0.GetDataContractsResponse\x12o\n\x0cgetDocuments\x12..org.dash.platform.dapi.v0.GetDocumentsRequest\x1a/.org.dash.platform.dapi.v0.GetDocumentsResponse\x12\x99\x01\n\x1agetIdentityByPublicKeyHash\x12<.org.dash.platform.dapi.v0.GetIdentityByPublicKeyHashRequest\x1a=.org.dash.platform.dapi.v0.GetIdentityByPublicKeyHashResponse\x12\x9f\x01\n\x1cwaitForStateTransitionResult\x12>.org.dash.platform.dapi.v0.WaitForStateTransitionResultRequest\x1a?.org.dash.platform.dapi.v0.WaitForStateTransitionResultResponse\x12\x81\x01\n\x12getConsensusParams\x12\x34.org.dash.platform.dapi.v0.GetConsensusParamsRequest\x1a\x35.org.dash.platform.dapi.v0.GetConsensusParamsResponse\x12\xa5\x01\n\x1egetProtocolVersionUpgradeState\x12@.org.dash.platform.dapi.v0.GetProtocolVersionUpgradeStateRequest\x1a\x41.org.dash.platform.dapi.v0.GetProtocolVersionUpgradeStateResponse\x12\xb4\x01\n#getProtocolVersionUpgradeVoteStatus\x12\x45.org.dash.platform.dapi.v0.GetProtocolVersionUpgradeVoteStatusRequest\x1a\x46.org.dash.platform.dapi.v0.GetProtocolVersionUpgradeVoteStatusResponse\x12r\n\rgetEpochsInfo\x12/.org.dash.platform.dapi.v0.GetEpochsInfoRequest\x1a\x30.org.dash.platform.dapi.v0.GetEpochsInfoResponse\x12\x8a\x01\n\x15getContestedResources\x12\x37.org.dash.platform.dapi.v0.GetContestedResourcesRequest\x1a\x38.org.dash.platform.dapi.v0.GetContestedResourcesResponse\x12\xa2\x01\n\x1dgetContestedResourceVoteState\x12?.org.dash.platform.dapi.v0.GetContestedResourceVoteStateRequest\x1a@.org.dash.platform.dapi.v0.GetContestedResourceVoteStateResponse\x12\xba\x01\n%getContestedResourceVotersForIdentity\x12G.org.dash.platform.dapi.v0.GetContestedResourceVotersForIdentityRequest\x1aH.org.dash.platform.dapi.v0.GetContestedResourceVotersForIdentityResponse\x12\xae\x01\n!getContestedResourceIdentityVotes\x12\x43.org.dash.platform.dapi.v0.GetContestedResourceIdentityVotesRequest\x1a\x44.org.dash.platform.dapi.v0.GetContestedResourceIdentityVotesResponse\x12\x8a\x01\n\x15getVotePollsByEndDate\x12\x37.org.dash.platform.dapi.v0.GetVotePollsByEndDateRequest\x1a\x38.org.dash.platform.dapi.v0.GetVotePollsByEndDateResponse\x12\xa5\x01\n\x1egetPrefundedSpecializedBalance\x12@.org.dash.platform.dapi.v0.GetPrefundedSpecializedBalanceRequest\x1a\x41.org.dash.platform.dapi.v0.GetPrefundedSpecializedBalanceResponse\x12x\n\x0fgetPathElements\x12\x31.org.dash.platform.dapi.v0.GetPathElementsRequest\x1a\x32.org.dash.platform.dapi.v0.GetPathElementsResponseb\x06proto3' , dependencies=[google_dot_protobuf_dot_wrappers__pb2.DESCRIPTOR,google_dot_protobuf_dot_struct__pb2.DESCRIPTOR,google_dot_protobuf_dot_timestamp__pb2.DESCRIPTOR,]) @@ -62,8 +62,8 @@ ], containing_type=None, serialized_options=None, - serialized_start=25582, - serialized_end=25672, + serialized_start=25559, + serialized_end=25649, ) _sym_db.RegisterEnumDescriptor(_KEYPURPOSE) @@ -173,22 +173,17 @@ create_key=_descriptor._internal_create_key, values=[ _descriptor.EnumValueDescriptor( - name='IDENTITY_IDS_ONLY', index=0, number=0, + name='DOCUMENTS', index=0, number=0, serialized_options=None, type=None, create_key=_descriptor._internal_create_key), _descriptor.EnumValueDescriptor( - name='DOCUMENTS', index=1, number=1, + name='VOTE_TALLY', index=1, number=1, serialized_options=None, type=None, create_key=_descriptor._internal_create_key), _descriptor.EnumValueDescriptor( - name='VOTE_TALLY', index=2, number=2, - serialized_options=None, - type=None, - create_key=_descriptor._internal_create_key), - _descriptor.EnumValueDescriptor( - name='DOCUMENTS_AND_VOTE_TALLY', index=3, number=3, + name='DOCUMENTS_AND_VOTE_TALLY', index=2, number=2, serialized_options=None, type=None, create_key=_descriptor._internal_create_key), @@ -196,7 +191,7 @@ containing_type=None, serialized_options=None, serialized_start=19256, - serialized_end=19352, + serialized_end=19329, ) _sym_db.RegisterEnumDescriptor(_GETCONTESTEDRESOURCEVOTESTATEREQUEST_GETCONTESTEDRESOURCEVOTESTATEREQUESTV0_RESULTTYPE) @@ -225,8 +220,8 @@ ], containing_type=None, serialized_options=None, - serialized_start=20266, - serialized_end=20345, + serialized_start=20243, + serialized_end=20322, ) _sym_db.RegisterEnumDescriptor(_GETCONTESTEDRESOURCEVOTESTATERESPONSE_GETCONTESTEDRESOURCEVOTESTATERESPONSEV0_FINISHEDVOTEINFO_FINISHEDVOTEOUTCOME) @@ -255,8 +250,8 @@ ], containing_type=None, serialized_options=None, - serialized_start=23974, - serialized_end=24035, + serialized_start=23951, + serialized_end=24012, ) _sym_db.RegisterEnumDescriptor(_GETCONTESTEDRESOURCEIDENTITYVOTESRESPONSE_GETCONTESTEDRESOURCEIDENTITYVOTESRESPONSEV0_RESOURCEVOTECHOICE_VOTECHOICETYPE) @@ -5474,7 +5469,7 @@ fields=[]), ], serialized_start=18643, - serialized_end=19391, + serialized_end=19368, ) _GETCONTESTEDRESOURCEVOTESTATEREQUEST = _descriptor.Descriptor( @@ -5510,7 +5505,7 @@ fields=[]), ], serialized_start=18484, - serialized_end=19402, + serialized_end=19379, ) @@ -5582,8 +5577,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=19902, - serialized_end=20368, + serialized_start=19879, + serialized_end=20345, ) _GETCONTESTEDRESOURCEVOTESTATERESPONSE_GETCONTESTEDRESOURCEVOTESTATERESPONSEV0_CONTESTEDRESOURCECONTENDERS = _descriptor.Descriptor( @@ -5649,8 +5644,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=20371, - serialized_end=20823, + serialized_start=20348, + serialized_end=20800, ) _GETCONTESTEDRESOURCEVOTESTATERESPONSE_GETCONTESTEDRESOURCEVOTESTATERESPONSEV0_CONTENDER = _descriptor.Descriptor( @@ -5704,8 +5699,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=20825, - serialized_end=20932, + serialized_start=20802, + serialized_end=20909, ) _GETCONTESTEDRESOURCEVOTESTATERESPONSE_GETCONTESTEDRESOURCEVOTESTATERESPONSEV0 = _descriptor.Descriptor( @@ -5754,8 +5749,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=19567, - serialized_end=20942, + serialized_start=19544, + serialized_end=20919, ) _GETCONTESTEDRESOURCEVOTESTATERESPONSE = _descriptor.Descriptor( @@ -5790,8 +5785,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=19405, - serialized_end=20953, + serialized_start=19382, + serialized_end=20930, ) @@ -5926,8 +5921,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=21140, - serialized_end=21670, + serialized_start=21117, + serialized_end=21647, ) _GETCONTESTEDRESOURCEVOTERSFORIDENTITYREQUEST = _descriptor.Descriptor( @@ -5962,8 +5957,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=20956, - serialized_end=21681, + serialized_start=20933, + serialized_end=21658, ) @@ -6001,8 +5996,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=22221, - serialized_end=22288, + serialized_start=22198, + serialized_end=22265, ) _GETCONTESTEDRESOURCEVOTERSFORIDENTITYRESPONSE_GETCONTESTEDRESOURCEVOTERSFORIDENTITYRESPONSEV0 = _descriptor.Descriptor( @@ -6051,8 +6046,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=21871, - serialized_end=22298, + serialized_start=21848, + serialized_end=22275, ) _GETCONTESTEDRESOURCEVOTERSFORIDENTITYRESPONSE = _descriptor.Descriptor( @@ -6087,8 +6082,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=21684, - serialized_end=22309, + serialized_start=21661, + serialized_end=22286, ) @@ -6126,8 +6121,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=22858, - serialized_end=22955, + serialized_start=22835, + serialized_end=22932, ) _GETCONTESTEDRESOURCEIDENTITYVOTESREQUEST_GETCONTESTEDRESOURCEIDENTITYVOTESREQUESTV0 = _descriptor.Descriptor( @@ -6197,8 +6192,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=22483, - serialized_end=22986, + serialized_start=22460, + serialized_end=22963, ) _GETCONTESTEDRESOURCEIDENTITYVOTESREQUEST = _descriptor.Descriptor( @@ -6233,8 +6228,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=22312, - serialized_end=22997, + serialized_start=22289, + serialized_end=22974, ) @@ -6272,8 +6267,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=23500, - serialized_end=23747, + serialized_start=23477, + serialized_end=23724, ) _GETCONTESTEDRESOURCEIDENTITYVOTESRESPONSE_GETCONTESTEDRESOURCEIDENTITYVOTESRESPONSEV0_RESOURCEVOTECHOICE = _descriptor.Descriptor( @@ -6316,8 +6311,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=23750, - serialized_end=24051, + serialized_start=23727, + serialized_end=24028, ) _GETCONTESTEDRESOURCEIDENTITYVOTESRESPONSE_GETCONTESTEDRESOURCEIDENTITYVOTESRESPONSEV0_CONTESTEDRESOURCEIDENTITYVOTE = _descriptor.Descriptor( @@ -6368,8 +6363,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=24054, - serialized_end=24331, + serialized_start=24031, + serialized_end=24308, ) _GETCONTESTEDRESOURCEIDENTITYVOTESRESPONSE_GETCONTESTEDRESOURCEIDENTITYVOTESRESPONSEV0 = _descriptor.Descriptor( @@ -6418,8 +6413,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=23174, - serialized_end=24341, + serialized_start=23151, + serialized_end=24318, ) _GETCONTESTEDRESOURCEIDENTITYVOTESRESPONSE = _descriptor.Descriptor( @@ -6454,8 +6449,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=23000, - serialized_end=24352, + serialized_start=22977, + serialized_end=24329, ) @@ -6493,8 +6488,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=24516, - serialized_end=24584, + serialized_start=24493, + serialized_end=24561, ) _GETPREFUNDEDSPECIALIZEDBALANCEREQUEST = _descriptor.Descriptor( @@ -6529,8 +6524,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=24355, - serialized_end=24595, + serialized_start=24332, + serialized_end=24572, ) @@ -6580,8 +6575,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=24763, - serialized_end=24948, + serialized_start=24740, + serialized_end=24925, ) _GETPREFUNDEDSPECIALIZEDBALANCERESPONSE = _descriptor.Descriptor( @@ -6616,8 +6611,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=24598, - serialized_end=24959, + serialized_start=24575, + serialized_end=24936, ) @@ -6662,8 +6657,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=25078, - serialized_end=25147, + serialized_start=25055, + serialized_end=25124, ) _GETPATHELEMENTSREQUEST = _descriptor.Descriptor( @@ -6698,8 +6693,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=24962, - serialized_end=25158, + serialized_start=24939, + serialized_end=25135, ) @@ -6730,8 +6725,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=25531, - serialized_end=25559, + serialized_start=25508, + serialized_end=25536, ) _GETPATHELEMENTSRESPONSE_GETPATHELEMENTSRESPONSEV0 = _descriptor.Descriptor( @@ -6780,8 +6775,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=25281, - serialized_end=25569, + serialized_start=25258, + serialized_end=25546, ) _GETPATHELEMENTSRESPONSE = _descriptor.Descriptor( @@ -6816,8 +6811,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=25161, - serialized_end=25580, + serialized_start=25138, + serialized_end=25557, ) _GETIDENTITYREQUEST_GETIDENTITYREQUESTV0.containing_type = _GETIDENTITYREQUEST @@ -8676,8 +8671,8 @@ index=0, serialized_options=None, create_key=_descriptor._internal_create_key, - serialized_start=25675, - serialized_end=29420, + serialized_start=25652, + serialized_end=29397, methods=[ _descriptor.MethodDescriptor( name='broadcastStateTransition', diff --git a/packages/dapi-grpc/clients/platform/v0/web/platform_pb.d.ts b/packages/dapi-grpc/clients/platform/v0/web/platform_pb.d.ts index 4cec80dc281..9614ea37c38 100644 --- a/packages/dapi-grpc/clients/platform/v0/web/platform_pb.d.ts +++ b/packages/dapi-grpc/clients/platform/v0/web/platform_pb.d.ts @@ -3817,10 +3817,9 @@ export namespace GetContestedResourceVoteStateRequest { } export interface ResultTypeMap { - IDENTITY_IDS_ONLY: 0; - DOCUMENTS: 1; - VOTE_TALLY: 2; - DOCUMENTS_AND_VOTE_TALLY: 3; + DOCUMENTS: 0; + VOTE_TALLY: 1; + DOCUMENTS_AND_VOTE_TALLY: 2; } export const ResultType: ResultTypeMap; diff --git a/packages/dapi-grpc/clients/platform/v0/web/platform_pb.js b/packages/dapi-grpc/clients/platform/v0/web/platform_pb.js index 62d8ac471c0..8d995602b92 100644 --- a/packages/dapi-grpc/clients/platform/v0/web/platform_pb.js +++ b/packages/dapi-grpc/clients/platform/v0/web/platform_pb.js @@ -29030,10 +29030,9 @@ proto.org.dash.platform.dapi.v0.GetContestedResourceVoteStateRequest.GetConteste * @enum {number} */ proto.org.dash.platform.dapi.v0.GetContestedResourceVoteStateRequest.GetContestedResourceVoteStateRequestV0.ResultType = { - IDENTITY_IDS_ONLY: 0, - DOCUMENTS: 1, - VOTE_TALLY: 2, - DOCUMENTS_AND_VOTE_TALLY: 3 + DOCUMENTS: 0, + VOTE_TALLY: 1, + DOCUMENTS_AND_VOTE_TALLY: 2 }; diff --git a/packages/dapi/lib/externalApis/drive/fetchProofForStateTransitionFactory.js b/packages/dapi/lib/externalApis/drive/fetchProofForStateTransitionFactory.js index a14108e58d2..941751ee0a3 100644 --- a/packages/dapi/lib/externalApis/drive/fetchProofForStateTransitionFactory.js +++ b/packages/dapi/lib/externalApis/drive/fetchProofForStateTransitionFactory.js @@ -75,6 +75,30 @@ function fetchProofForStateTransitionFactory(driveClient) { }); requestV0.setContractsList(contractsList); + } if (stateTransition.isVotingStateTransition()) { + const { VoteStatusRequest } = GetProofsRequestV0; + const { ContestedResourceVoteStatusRequest } = VoteStatusRequest; + + const contestedResourceVoteStatusRequest = new ContestedResourceVoteStatusRequest(); + + const contestedVotePoll = stateTransition.getContestedDocumentResourceVotePoll(); + + if (!contestedVotePoll) { + throw new Error('Masternode vote state transition should have a contested vote poll'); + } + + contestedResourceVoteStatusRequest.setContractId(contestedVotePoll.contractId.toBuffer()); + contestedResourceVoteStatusRequest.setDocumentTypeName(contestedVotePoll.documentTypeName); + contestedResourceVoteStatusRequest.setIndexName(contestedVotePoll.indexName); + contestedResourceVoteStatusRequest.setIndexValuesList(contestedVotePoll.indexValues); + contestedResourceVoteStatusRequest.setVoterIdentifier( + stateTransition.getProTxHash().toBuffer(), + ); + + const voteStatus = new VoteStatusRequest(); + voteStatus.setContestedResourceVoteStatusRequest(contestedResourceVoteStatusRequest); + + requestV0.setVotesList([voteStatus]); } const request = new GetProofsRequest(); diff --git a/packages/dapi/test/unit/externalApis/drive/fetchProofForStateTransitionFactory.spec.js b/packages/dapi/test/unit/externalApis/drive/fetchProofForStateTransitionFactory.spec.js index 91c277b8fd3..07ce55a1fb0 100644 --- a/packages/dapi/test/unit/externalApis/drive/fetchProofForStateTransitionFactory.spec.js +++ b/packages/dapi/test/unit/externalApis/drive/fetchProofForStateTransitionFactory.spec.js @@ -1,4 +1,5 @@ const { expect } = require('chai'); +const crypto = require('crypto'); const { v0: { @@ -18,6 +19,7 @@ describe('fetchProofForStateTransition', () => { let identitiesProofResponse; let dataContractsProofResponse; let documentsProofResponse; + let masternodeVoteResponse; let stateTransitionFixture; beforeEach(async function beforeEach() { @@ -28,6 +30,8 @@ describe('fetchProofForStateTransition', () => { documentsProofResponse.setV0(new GetProofsResponseV0().setProof(new Proof([Buffer.from('documents contracts proof')]))); identitiesProofResponse = new GetProofsResponse(); identitiesProofResponse.setV0(new GetProofsResponseV0().setProof(new Proof([Buffer.from('identities contracts proof')]))); + masternodeVoteResponse = new GetProofsResponse(); + masternodeVoteResponse.setV0(new GetProofsResponseV0().setProof(new Proof([Buffer.from('masternode vote proof')]))); driveClientMock = { getProofs: this.sinon.stub().callsFake(async (requestProto) => { @@ -37,6 +41,8 @@ describe('fetchProofForStateTransition', () => { return documentsProofResponse; } if (requestProto.getV0().getContractsList().length > 0) { return dataContractsProofResponse; + } if (requestProto.getV0().getVotesList().length > 0) { + return masternodeVoteResponse; } return null; @@ -44,6 +50,7 @@ describe('fetchProofForStateTransition', () => { }; stateTransitionFixture = { + isVotingStateTransition: this.sinon.stub(), isIdentityStateTransition: this.sinon.stub(), isDocumentStateTransition: this.sinon.stub(), isDataContractStateTransition: this.sinon.stub(), @@ -86,4 +93,25 @@ describe('fetchProofForStateTransition', () => { expect(result.serializeBinary()).to.deep .equal(documentsProofResponse.serializeBinary()); }); + + it('should fetch masternode vote proofs', async function it() { + const proTxHash = await generateRandomIdentifierAsync(); + const contractId = await generateRandomIdentifierAsync(); + const documentTypeName = 'documentType'; + const indexName = 'indexName'; + const indexValues = [crypto.randomBytes(32), crypto.randomBytes(32)]; + + stateTransitionFixture.getProTxHash = this.sinon.stub().returns(proTxHash); + stateTransitionFixture.isVotingStateTransition.returns(true); + stateTransitionFixture.getContestedDocumentResourceVotePoll = this.sinon.stub().returns({ + contractId, + documentTypeName, + indexName, + indexValues, + }); + + const result = await fetchProofForStateTransition(stateTransitionFixture); + expect(result.serializeBinary()).to.deep + .equal(masternodeVoteResponse.serializeBinary()); + }); }); diff --git a/packages/wasm-dpp/Cargo.toml b/packages/wasm-dpp/Cargo.toml index b83aacf8d25..2503b751d1e 100644 --- a/packages/wasm-dpp/Cargo.toml +++ b/packages/wasm-dpp/Cargo.toml @@ -51,6 +51,7 @@ anyhow = { version = "1.0.75" } # required, cargo-machete false positive wasm-bindgen-futures = "0.4.33" async-trait = "0.1.59" +bincode = "2.0.0-rc.3" [profile.release] lto = true opt-level = 's' diff --git a/packages/wasm-dpp/src/voting/state_transition/masternode_vote_transition/mod.rs b/packages/wasm-dpp/src/voting/state_transition/masternode_vote_transition/mod.rs index fb6b05e3c54..120105e0212 100644 --- a/packages/wasm-dpp/src/voting/state_transition/masternode_vote_transition/mod.rs +++ b/packages/wasm-dpp/src/voting/state_transition/masternode_vote_transition/mod.rs @@ -1,5 +1,6 @@ mod to_object; +use js_sys::{Array, Object, Reflect, Uint8Array}; use crate::bls_adapter::{BlsAdapter, JsBlsAdapter}; use crate::buffer::Buffer; use crate::errors::from_dpp_err; @@ -17,6 +18,9 @@ use dpp::state_transition::{StateTransition, StateTransitionIdentitySigned, Stat use dpp::version::PlatformVersion; use wasm_bindgen::prelude::wasm_bindgen; use wasm_bindgen::{JsError, JsValue}; +use dpp::voting::vote_polls::VotePoll; +use dpp::voting::votes::resource_vote::accessors::v0::ResourceVoteGettersV0; +use dpp::voting::votes::Vote; #[derive(Clone)] #[wasm_bindgen(js_name=MasternodeVoteTransition)] @@ -51,7 +55,7 @@ impl MasternodeVoteTransitionWasm { self.0.state_transition_type() as u8 } - #[wasm_bindgen(getter, js_name=proTxHash)] + #[wasm_bindgen(getter, js_name=getProTxHash)] pub fn pro_tx_hash(&self) -> IdentifierWrapper { self.get_pro_tx_hash() } @@ -215,6 +219,43 @@ impl MasternodeVoteTransitionWasm { self.0.is_voting_state_transition() } + #[wasm_bindgen(js_name=getContestedDocumentResourceVotePoll)] + pub fn contested_document_resource_vote_poll(&self) -> Option { + match self.0.vote() { + Vote::ResourceVote(vote) => match vote.vote_poll() { + VotePoll::ContestedDocumentResourceVotePoll(contested_document_resource_vote_poll) => { + let js_object = Object::new(); + + let contract_id = IdentifierWrapper::from(contested_document_resource_vote_poll.contract_id.clone()); + + Reflect::set(&js_object, &"contractId".into(), &contract_id.into()).unwrap(); + Reflect::set(&js_object, &"documentTypeName".into(), &contested_document_resource_vote_poll.document_type_name.clone().into()).unwrap(); + Reflect::set(&js_object, &"indexName".into(), &contested_document_resource_vote_poll.index_name.clone().into()).unwrap(); + + let config = bincode::config::standard() + .with_big_endian() + .with_no_limit(); + + let serialized_index_values = contested_document_resource_vote_poll + .index_values + .iter() + .map(|value| { + JsValue::from(Buffer::from_bytes_owned( + bincode::encode_to_vec(value, config) + .expect("expected to encode value in path") + )) + }); + + let js_array = Array::from_iter(serialized_index_values); + + Reflect::set(&js_object, &"indexValues".into(), &js_array.into()).unwrap(); + + Some(js_object) + } + } + } + } + #[wasm_bindgen(js_name=signByPrivateKey)] pub fn sign_by_private_key( &mut self, From bdb85cabb9730ab91507b55877ff9c1aabb6a0a3 Mon Sep 17 00:00:00 2001 From: Lukasz Klimek <842586+lklimek@users.noreply.github.com> Date: Fri, 28 Jun 2024 09:13:16 +0200 Subject: [PATCH 33/55] build: update cargo.lock --- Cargo.lock | 42 ++++++++++++++++++++++++------------------ 1 file changed, 24 insertions(+), 18 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f2d433c74fa..1ded28bf627 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -421,7 +421,7 @@ dependencies = [ "bitflags 2.6.0", "cexpr", "clang-sys", - "itertools 0.10.5", + "itertools 0.12.1", "lazy_static", "lazycell", "proc-macro2", @@ -2234,7 +2234,7 @@ checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" [[package]] name = "grovedb" version = "1.0.0-rc.2" -source = "git+https://github.com/dashpay/grovedb?branch=feat/QuerySumTree#1696c2ef47a674be5ec213b9ff723afe4c45fb90" +source = "git+https://github.com/dashpay/grovedb?branch=feat/QuerySumTree#53642edc24893ab51d5dcbc06ee3b4e0001b8624" dependencies = [ "bincode 2.0.0-rc.3", "bitvec", @@ -2258,7 +2258,7 @@ dependencies = [ [[package]] name = "grovedb-costs" version = "1.0.0-rc.2" -source = "git+https://github.com/dashpay/grovedb?branch=feat/QuerySumTree#1696c2ef47a674be5ec213b9ff723afe4c45fb90" +source = "git+https://github.com/dashpay/grovedb?branch=feat/QuerySumTree#53642edc24893ab51d5dcbc06ee3b4e0001b8624" dependencies = [ "integer-encoding", "intmap", @@ -2268,7 +2268,7 @@ dependencies = [ [[package]] name = "grovedb-merk" version = "1.0.0-rc.2" -source = "git+https://github.com/dashpay/grovedb?branch=feat/QuerySumTree#1696c2ef47a674be5ec213b9ff723afe4c45fb90" +source = "git+https://github.com/dashpay/grovedb?branch=feat/QuerySumTree#53642edc24893ab51d5dcbc06ee3b4e0001b8624" dependencies = [ "blake3", "byteorder", @@ -2291,12 +2291,12 @@ dependencies = [ [[package]] name = "grovedb-path" version = "1.0.0-rc.2" -source = "git+https://github.com/dashpay/grovedb?branch=feat/QuerySumTree#1696c2ef47a674be5ec213b9ff723afe4c45fb90" +source = "git+https://github.com/dashpay/grovedb?branch=feat/QuerySumTree#53642edc24893ab51d5dcbc06ee3b4e0001b8624" [[package]] name = "grovedb-storage" version = "1.0.0-rc.2" -source = "git+https://github.com/dashpay/grovedb?branch=feat/QuerySumTree#1696c2ef47a674be5ec213b9ff723afe4c45fb90" +source = "git+https://github.com/dashpay/grovedb?branch=feat/QuerySumTree#53642edc24893ab51d5dcbc06ee3b4e0001b8624" dependencies = [ "blake3", "grovedb-costs", @@ -2315,7 +2315,7 @@ dependencies = [ [[package]] name = "grovedb-visualize" version = "1.0.0-rc.2" -source = "git+https://github.com/dashpay/grovedb?branch=feat/QuerySumTree#1696c2ef47a674be5ec213b9ff723afe4c45fb90" +source = "git+https://github.com/dashpay/grovedb?branch=feat/QuerySumTree#53642edc24893ab51d5dcbc06ee3b4e0001b8624" dependencies = [ "hex", "itertools 0.12.1", @@ -2890,7 +2890,7 @@ source = "git+https://github.com/fominok/jsonschema-rs?branch=feat-unevaluated-p dependencies = [ "ahash 0.8.11", "anyhow", - "base64 0.13.1", + "base64 0.22.1", "bytecount", "fancy-regex", "fraction", @@ -2956,7 +2956,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e310b3a6b5907f99202fcdb4960ff45b93735d7c7d96b760fcff8db2dc0e103d" dependencies = [ "cfg-if", - "windows-targets 0.48.5", + "windows-targets 0.52.5", ] [[package]] @@ -3020,9 +3020,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.21" +version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" [[package]] name = "lru" @@ -3252,6 +3252,12 @@ version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a" +[[package]] +name = "multimap" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "defc4c55412d89136f966bbb339008b474350e5e6e78d2714439c386b3137a03" + [[package]] name = "murmur3" version = "0.5.2" @@ -3323,9 +3329,9 @@ dependencies = [ [[package]] name = "num-bigint" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c165a9ab64cf766f73521c0dd2cfdff64f488b8f0b3e621face3462d3db536d7" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" dependencies = [ "num-integer", "num-traits", @@ -3919,7 +3925,7 @@ dependencies = [ "itertools 0.10.5", "lazy_static", "log", - "multimap", + "multimap 0.8.3", "petgraph", "prettyplease 0.1.25", "prost 0.11.9", @@ -3937,10 +3943,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "22505a5c94da8e3b7c2996394d1c933236c4d743e81a410bcca4e6989fc066a4" dependencies = [ "bytes", - "heck 0.4.1", - "itertools 0.10.5", + "heck 0.5.0", + "itertools 0.12.1", "log", - "multimap", + "multimap 0.10.0", "once_cell", "petgraph", "prettyplease 0.2.20", @@ -3971,7 +3977,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "81bddcdb20abf9501610992b6759a4c888aef7d1a7247ef75e2404275ac24af1" dependencies = [ "anyhow", - "itertools 0.10.5", + "itertools 0.12.1", "proc-macro2", "quote", "syn 2.0.68", From 84dfbef9032e983e9264141fc8755cc7c0079bbe Mon Sep 17 00:00:00 2001 From: Ivan Shumkov Date: Fri, 28 Jun 2024 17:46:58 +0700 Subject: [PATCH 34/55] fix: stateTransition.getProTxHash is not a function --- .../masternode_vote_transition/mod.rs | 105 +++++++++++------- 1 file changed, 63 insertions(+), 42 deletions(-) diff --git a/packages/wasm-dpp/src/voting/state_transition/masternode_vote_transition/mod.rs b/packages/wasm-dpp/src/voting/state_transition/masternode_vote_transition/mod.rs index 120105e0212..7827a0868c8 100644 --- a/packages/wasm-dpp/src/voting/state_transition/masternode_vote_transition/mod.rs +++ b/packages/wasm-dpp/src/voting/state_transition/masternode_vote_transition/mod.rs @@ -1,6 +1,5 @@ mod to_object; -use js_sys::{Array, Object, Reflect, Uint8Array}; use crate::bls_adapter::{BlsAdapter, JsBlsAdapter}; use crate::buffer::Buffer; use crate::errors::from_dpp_err; @@ -16,11 +15,12 @@ use dpp::state_transition::masternode_vote_transition::accessors::MasternodeVote use dpp::state_transition::masternode_vote_transition::MasternodeVoteTransition; use dpp::state_transition::{StateTransition, StateTransitionIdentitySigned, StateTransitionLike}; use dpp::version::PlatformVersion; -use wasm_bindgen::prelude::wasm_bindgen; -use wasm_bindgen::{JsError, JsValue}; use dpp::voting::vote_polls::VotePoll; use dpp::voting::votes::resource_vote::accessors::v0::ResourceVoteGettersV0; use dpp::voting::votes::Vote; +use js_sys::{Array, Object, Reflect, Uint8Array}; +use wasm_bindgen::prelude::wasm_bindgen; +use wasm_bindgen::{JsError, JsValue}; #[derive(Clone)] #[wasm_bindgen(js_name=MasternodeVoteTransition)] @@ -50,25 +50,26 @@ impl MasternodeVoteTransitionWasm { .map_err(from_dpp_err) } + #[wasm_bindgen(js_name=getOwnerId)] + pub fn get_owner_id(&self) -> IdentifierWrapper { + self.0.owner_id().to_owned().into() + } + #[wasm_bindgen(js_name=getType)] pub fn get_type(&self) -> u8 { self.0.state_transition_type() as u8 } - #[wasm_bindgen(getter, js_name=getProTxHash)] - pub fn pro_tx_hash(&self) -> IdentifierWrapper { - self.get_pro_tx_hash() - } - - #[wasm_bindgen(js_name=getIdentityId)] + #[wasm_bindgen(js_name=getProTxHash)] pub fn get_pro_tx_hash(&self) -> IdentifierWrapper { self.0.pro_tx_hash().into() } - #[wasm_bindgen(js_name=setIdentityId)] + #[wasm_bindgen(js_name=setProTxHash)] pub fn set_pro_tx_hash(&mut self, pro_tx_hash: &IdentifierWrapper) { self.0.set_pro_tx_hash(pro_tx_hash.into()); } + #[wasm_bindgen(js_name=toObject)] pub fn to_object(&self, options: JsValue) -> Result { let opts: self::to_object::ToObjectOptions = if options.is_object() { @@ -221,39 +222,59 @@ impl MasternodeVoteTransitionWasm { #[wasm_bindgen(js_name=getContestedDocumentResourceVotePoll)] pub fn contested_document_resource_vote_poll(&self) -> Option { - match self.0.vote() { - Vote::ResourceVote(vote) => match vote.vote_poll() { - VotePoll::ContestedDocumentResourceVotePoll(contested_document_resource_vote_poll) => { - let js_object = Object::new(); - - let contract_id = IdentifierWrapper::from(contested_document_resource_vote_poll.contract_id.clone()); - - Reflect::set(&js_object, &"contractId".into(), &contract_id.into()).unwrap(); - Reflect::set(&js_object, &"documentTypeName".into(), &contested_document_resource_vote_poll.document_type_name.clone().into()).unwrap(); - Reflect::set(&js_object, &"indexName".into(), &contested_document_resource_vote_poll.index_name.clone().into()).unwrap(); - - let config = bincode::config::standard() - .with_big_endian() - .with_no_limit(); - - let serialized_index_values = contested_document_resource_vote_poll - .index_values - .iter() - .map(|value| { - JsValue::from(Buffer::from_bytes_owned( - bincode::encode_to_vec(value, config) - .expect("expected to encode value in path") - )) - }); - - let js_array = Array::from_iter(serialized_index_values); - - Reflect::set(&js_object, &"indexValues".into(), &js_array.into()).unwrap(); - - Some(js_object) - } + match self.0.vote() { + Vote::ResourceVote(vote) => match vote.vote_poll() { + VotePoll::ContestedDocumentResourceVotePoll( + contested_document_resource_vote_poll, + ) => { + let js_object = Object::new(); + + let contract_id = IdentifierWrapper::from( + contested_document_resource_vote_poll.contract_id.clone(), + ); + + Reflect::set(&js_object, &"contractId".into(), &contract_id.into()).unwrap(); + Reflect::set( + &js_object, + &"documentTypeName".into(), + &contested_document_resource_vote_poll + .document_type_name + .clone() + .into(), + ) + .unwrap(); + Reflect::set( + &js_object, + &"indexName".into(), + &contested_document_resource_vote_poll + .index_name + .clone() + .into(), + ) + .unwrap(); + + let config = bincode::config::standard() + .with_big_endian() + .with_no_limit(); + + let serialized_index_values = contested_document_resource_vote_poll + .index_values + .iter() + .map(|value| { + JsValue::from(Buffer::from_bytes_owned( + bincode::encode_to_vec(value, config) + .expect("expected to encode value in path"), + )) + }); + + let js_array = Array::from_iter(serialized_index_values); + + Reflect::set(&js_object, &"indexValues".into(), &js_array.into()).unwrap(); + + Some(js_object) + } + }, } - } } #[wasm_bindgen(js_name=signByPrivateKey)] From ccf2c0be3aafc2ad1a90f34e3cfd95c7b895606a Mon Sep 17 00:00:00 2001 From: Ivan Shumkov Date: Fri, 28 Jun 2024 18:15:40 +0700 Subject: [PATCH 35/55] fix: missing the document contested status --- .../drive/fetchProofForStateTransitionFactory.js | 7 +++++++ .../document_transition/mod.rs | 11 +++++++++++ 2 files changed, 18 insertions(+) diff --git a/packages/dapi/lib/externalApis/drive/fetchProofForStateTransitionFactory.js b/packages/dapi/lib/externalApis/drive/fetchProofForStateTransitionFactory.js index 941751ee0a3..0d50ddd67a7 100644 --- a/packages/dapi/lib/externalApis/drive/fetchProofForStateTransitionFactory.js +++ b/packages/dapi/lib/externalApis/drive/fetchProofForStateTransitionFactory.js @@ -30,6 +30,13 @@ function fetchProofForStateTransitionFactory(driveClient) { documentRequest.setContractId(documentTransition.getDataContractId().toBuffer()); documentRequest.setDocumentType(documentTransition.getType()); documentRequest.setDocumentId(documentTransition.getId().toBuffer()); + + const status = documentTransition.hasPrefundedBalance() + ? DocumentRequest.DocumentContestedStatus.CONTESTED + : DocumentRequest.DocumentContestedStatus.NOT_CONTESTED; + + documentRequest.setDocumentContestedStatus(status); + return documentRequest; }); diff --git a/packages/wasm-dpp/src/document/state_transition/document_batch_transition/document_transition/mod.rs b/packages/wasm-dpp/src/document/state_transition/document_batch_transition/document_transition/mod.rs index 8bf5078a2db..a26d579d7de 100644 --- a/packages/wasm-dpp/src/document/state_transition/document_batch_transition/document_transition/mod.rs +++ b/packages/wasm-dpp/src/document/state_transition/document_batch_transition/document_transition/mod.rs @@ -7,6 +7,7 @@ mod document_create_transition; // pub use document_replace_transition::*; use dpp::platform_value::Value; +use dpp::state_transition::documents_batch_transition::document_create_transition::v0::v0_methods::DocumentCreateTransitionV0Methods; use dpp::state_transition::documents_batch_transition::document_transition::action_type::TransitionActionTypeGetter; use dpp::state_transition::documents_batch_transition::document_transition::DocumentTransitionV0Methods; use dpp::{ @@ -71,6 +72,16 @@ impl DocumentTransitionWasm { pub fn set_revision(&mut self, revision: u32) { self.0.set_revision(revision as u64); } + + #[wasm_bindgen(js_name=hasPrefundedBalance)] + pub fn has_prefunded_balance(&self) -> bool { + match &self.0 { + DocumentTransition::Create(create_transition) => { + create_transition.prefunded_voting_balance().is_some() + } + _ => false, + } + } } impl From for DocumentTransitionWasm { From 170b3a09643c9cce1229ebd17fc252787400b4dc Mon Sep 17 00:00:00 2001 From: Quantum Explorer Date: Fri, 28 Jun 2024 19:05:12 +0700 Subject: [PATCH 36/55] refactor: use generic for verify --- .../state_transitions/masternode_vote/mod.rs | 10 +++++----- packages/rs-drive-proof-verifier/src/proof.rs | 9 ++++++--- .../verify_identity_votes_given_proof/mod.rs | 11 +++++++---- .../verify_identity_votes_given_proof/v0/mod.rs | 10 ++++++---- .../verify_vote_polls_end_date_query/mod.rs | 14 ++++++++++---- .../verify_vote_polls_end_date_query/v0/mod.rs | 16 +++++++++++----- 6 files changed, 45 insertions(+), 25 deletions(-) diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/masternode_vote/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/masternode_vote/mod.rs index 77173b24cf9..616f2a5bc85 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/masternode_vote/mod.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/masternode_vote/mod.rs @@ -3210,7 +3210,7 @@ mod tests { }; query - .verify_identity_votes_given_proof( + .verify_identity_votes_given_proof::>( proof.grovedb_proof.as_slice(), &contract_lookup_fn_for_contract(Arc::new(contract.to_owned())), platform_version, @@ -3708,7 +3708,7 @@ mod tests { }; let (_, vote_polls_by_timestamps) = vote_poll_by_end_date_query - .verify_vote_polls_by_end_date_proof( + .verify_vote_polls_by_end_date_proof::>( proof.grovedb_proof.as_ref(), platform_version, ) @@ -4013,7 +4013,7 @@ mod tests { }; let (_, vote_polls_by_timestamps) = vote_poll_by_end_date_query - .verify_vote_polls_by_end_date_proof( + .verify_vote_polls_by_end_date_proof::>( proof.grovedb_proof.as_ref(), platform_version, ) @@ -4850,7 +4850,7 @@ mod tests { }; let (_, vote_polls_by_timestamps) = vote_poll_by_end_date_query - .verify_vote_polls_by_end_date_proof( + .verify_vote_polls_by_end_date_proof::>( proof.grovedb_proof.as_ref(), platform_version, ) @@ -4943,7 +4943,7 @@ mod tests { }; let (_, vote_polls_by_timestamps) = vote_poll_by_end_date_query - .verify_vote_polls_by_end_date_proof( + .verify_vote_polls_by_end_date_proof::>( proof.grovedb_proof.as_ref(), platform_version, ) diff --git a/packages/rs-drive-proof-verifier/src/proof.rs b/packages/rs-drive-proof-verifier/src/proof.rs index bdd0a506149..45a0af8133c 100644 --- a/packages/rs-drive-proof-verifier/src/proof.rs +++ b/packages/rs-drive-proof-verifier/src/proof.rs @@ -1416,7 +1416,7 @@ impl FromProof for ResourceV let contract_provider_fn = known_contracts_provider_fn(provider); let (root_hash, voters) = drive_query - .verify_identity_votes_given_proof( + .verify_identity_votes_given_proof::>( &proof.grovedb_proof, &contract_provider_fn, platform_version, @@ -1460,14 +1460,17 @@ impl FromProof for VotePollsGroupedByTim let mtd = response.metadata().or(Err(Error::EmptyResponseMetadata))?; let (root_hash, vote_polls) = drive_query - .verify_vote_polls_by_end_date_proof(&proof.grovedb_proof, platform_version) + .verify_vote_polls_by_end_date_proof::>( + &proof.grovedb_proof, + platform_version, + ) .map_err(|e| Error::DriveError { error: e.to_string(), })?; verify_tenderdash_proof(proof, mtd, &root_hash, provider)?; - let response = VotePollsGroupedByTimestamp::from_iter(vote_polls); + let response = VotePollsGroupedByTimestamp(vote_polls); Ok((response.into_option(), mtd.clone())) } diff --git a/packages/rs-drive/src/drive/verify/voting/verify_identity_votes_given_proof/mod.rs b/packages/rs-drive/src/drive/verify/voting/verify_identity_votes_given_proof/mod.rs index e97a7069f1e..a4a77ec5390 100644 --- a/packages/rs-drive/src/drive/verify/voting/verify_identity_votes_given_proof/mod.rs +++ b/packages/rs-drive/src/drive/verify/voting/verify_identity_votes_given_proof/mod.rs @@ -15,7 +15,7 @@ use dpp::voting::votes::resource_vote::ResourceVote; impl ContestedResourceVotesGivenByIdentityQuery { /// Verifies a proof for the vote poll vote state proof. /// - /// This function verifies a given serialized proof and returns the root hash along with a vector of deserialized identifiers. + /// This function verifies a given serialized proof and returns the root hash along with a collection of deserialized identifiers and their corresponding resource votes. /// /// # Arguments /// @@ -26,7 +26,7 @@ impl ContestedResourceVotesGivenByIdentityQuery { /// # Returns /// /// A `Result` containing: - /// * A tuple with the root hash and a vector of deserialized `Identifier`s if the proof is valid. + /// * A tuple with the root hash and a collection of `(Identifier, ResourceVote)` pairs if the proof is valid. The collection type is flexible and determined by the generic parameter `I`. /// * An `Error` variant if the proof verification fails or a deserialization error occurs. /// /// # Errors @@ -34,12 +34,15 @@ impl ContestedResourceVotesGivenByIdentityQuery { /// This function will return an `Error` if: /// * The proof verification fails. /// * A deserialization error occurs when parsing the serialized document(s). - pub fn verify_identity_votes_given_proof( + pub fn verify_identity_votes_given_proof( &self, proof: &[u8], contract_lookup_fn: &ContractLookupFn, platform_version: &PlatformVersion, - ) -> Result<(RootHash, BTreeMap), Error> { + ) -> Result<(RootHash, I), Error> + where + I: FromIterator<(Identifier, ResourceVote)>, + { match platform_version .drive .methods diff --git a/packages/rs-drive/src/drive/verify/voting/verify_identity_votes_given_proof/v0/mod.rs b/packages/rs-drive/src/drive/verify/voting/verify_identity_votes_given_proof/v0/mod.rs index b2be4be4766..fc439a8b52e 100644 --- a/packages/rs-drive/src/drive/verify/voting/verify_identity_votes_given_proof/v0/mod.rs +++ b/packages/rs-drive/src/drive/verify/voting/verify_identity_votes_given_proof/v0/mod.rs @@ -11,16 +11,18 @@ use dpp::identifier::Identifier; use dpp::voting::votes::resource_vote::ResourceVote; use grovedb::GroveDb; use platform_version::version::PlatformVersion; -use std::collections::BTreeMap; impl ContestedResourceVotesGivenByIdentityQuery { #[inline(always)] - pub(super) fn verify_identity_votes_given_proof_v0( + pub(super) fn verify_identity_votes_given_proof_v0( &self, proof: &[u8], contract_lookup_fn: &ContractLookupFn, platform_version: &PlatformVersion, - ) -> Result<(RootHash, BTreeMap), Error> { + ) -> Result<(RootHash, I), Error> + where + I: FromIterator<(Identifier, ResourceVote)>, + { let path_query = self.construct_path_query()?; let (root_hash, proved_key_values) = GroveDb::verify_query(proof, &path_query)?; @@ -58,7 +60,7 @@ impl ContestedResourceVotesGivenByIdentityQuery { vote_storage_form.resolve_with_contract(&data_contract, platform_version)?; Ok((vote_id, resource_vote)) }) - .collect::, Error>>()?; + .collect::>()?; Ok((root_hash, voters)) } diff --git a/packages/rs-drive/src/drive/verify/voting/verify_vote_polls_end_date_query/mod.rs b/packages/rs-drive/src/drive/verify/voting/verify_vote_polls_end_date_query/mod.rs index a64cfbf8930..7c1f860fc0a 100644 --- a/packages/rs-drive/src/drive/verify/voting/verify_vote_polls_end_date_query/mod.rs +++ b/packages/rs-drive/src/drive/verify/voting/verify_vote_polls_end_date_query/mod.rs @@ -15,7 +15,7 @@ impl VotePollsByEndDateDriveQuery { /// Verifies the serialized proof for a vote poll based on the end date. /// /// This function analyzes a byte slice which contains the serialized proof, performs verification, and returns - /// the results, which include the root hash of the proof and a structured map of the contests. + /// the results, which include the root hash of the proof and a structured collection of the contests. /// /// # Arguments /// @@ -25,7 +25,10 @@ impl VotePollsByEndDateDriveQuery { /// # Returns /// /// A `Result` which is either: - /// * `Ok((RootHash, BTreeMap))` if the proof is verified successfully. + /// * `Ok((RootHash, I))` if the proof is verified successfully, where `I` is a collection of items with + /// keys as timestamps (in milliseconds since the epoch) and values as vectors of `ContestedDocumentResourceVotePoll` + /// objects, representing voting polls ending at those times. The collection type is flexible and determined by the + /// generic parameter `I`. /// * `Err(Error)` if there is a failure in proof verification or during the deserialization of documents. /// /// # Errors @@ -34,11 +37,14 @@ impl VotePollsByEndDateDriveQuery { /// 1. Proof verification fails due to invalid data or signature issues. /// 2. Deserialization error occurs due to malformed data or incompatible types in the document(s). /// - pub fn verify_vote_polls_by_end_date_proof( + pub fn verify_vote_polls_by_end_date_proof( &self, proof: &[u8], platform_version: &PlatformVersion, - ) -> Result<(RootHash, BTreeMap>), Error> { + ) -> Result<(RootHash, I), Error> + where + I: FromIterator<(TimestampMillis, Vec)>, + { match platform_version .drive .methods diff --git a/packages/rs-drive/src/drive/verify/voting/verify_vote_polls_end_date_query/v0/mod.rs b/packages/rs-drive/src/drive/verify/voting/verify_vote_polls_end_date_query/v0/mod.rs index 7659a5b8de4..7cb7a4b619a 100644 --- a/packages/rs-drive/src/drive/verify/voting/verify_vote_polls_end_date_query/v0/mod.rs +++ b/packages/rs-drive/src/drive/verify/voting/verify_vote_polls_end_date_query/v0/mod.rs @@ -26,9 +26,10 @@ impl VotePollsByEndDateDriveQuery { /// # Returns /// /// A `Result` containing: - /// * A tuple with a root hash and a `BTreeMap` where the keys are timestamps (in milliseconds since + /// * A tuple with a root hash and a collection of items where the keys are timestamps (in milliseconds since /// the epoch) and the values are vectors of `ContestedDocumentResourceVotePoll` objects, - /// representing voting polls ending at those times. The map entries are sorted by the timestamps. + /// representing voting polls ending at those times. The collection is flexible and determined by the + /// generic parameter `I`. /// * An `Error` variant, in case the proof verification fails or if there are deserialization /// errors while parsing the documents. /// @@ -41,10 +42,13 @@ impl VotePollsByEndDateDriveQuery { /// 3. A required path component (timestamp) is missing in any of the paths returned in the proof, /// indicating a potentially corrupted state. #[inline(always)] - pub(super) fn verify_vote_polls_by_end_date_proof_v0( + pub(super) fn verify_vote_polls_by_end_date_proof_v0( &self, proof: &[u8], - ) -> Result<(RootHash, BTreeMap>), Error> { + ) -> Result<(RootHash, I), Error> + where + I: FromIterator<(TimestampMillis, Vec)>, + { let path_query = self.construct_path_query(); let (root_hash, proved_key_values) = GroveDb::verify_query(proof, &path_query)?; let vote_polls_by_end_date = proved_key_values @@ -69,7 +73,9 @@ impl VotePollsByEndDateDriveQuery { acc.entry(timestamp).or_default().push(vote_poll); acc }, - ); + ) + .into_iter() + .collect::(); Ok((root_hash, vote_polls_by_end_date)) } From ba216c7d9c62d8b461c5cafc08f32adfee7316d0 Mon Sep 17 00:00:00 2001 From: Lukasz Klimek <842586+lklimek@users.noreply.github.com> Date: Fri, 28 Jun 2024 15:32:51 +0200 Subject: [PATCH 37/55] test(sdk): further sdk tests --- packages/dapi-grpc/Cargo.toml | 4 +- packages/rs-sdk/src/platform/query.rs | 24 +++++ .../rs-sdk/tests/fetch/contested_resource.rs | 46 +++++---- .../contested_resource_identity_votes.rs | 42 +++++++- .../fetch/contested_resource_polls_by_ts.rs | 4 +- .../fetch/contested_resource_vote_state.rs | 17 ++-- .../tests/fetch/contested_resource_voters.rs | 95 +++++++++++++------ packages/rs-sdk/tests/fetch/document.rs | 3 +- 8 files changed, 174 insertions(+), 61 deletions(-) diff --git a/packages/dapi-grpc/Cargo.toml b/packages/dapi-grpc/Cargo.toml index dc80fcf6ab3..ba95f370d87 100644 --- a/packages/dapi-grpc/Cargo.toml +++ b/packages/dapi-grpc/Cargo.toml @@ -42,7 +42,9 @@ tonic = { version = "0.11", features = [ serde = { version = "1.0.197", optional = true, features = ["derive"] } serde_bytes = { version = "0.11.12", optional = true } serde_json = { version = "1.0", optional = true } -tenderdash-proto = { git = "https://github.com/dashpay/rs-tenderdash-abci", version = "0.14.0-dev.12", tag = "v0.14.0-dev.12", default-features = false } +tenderdash-proto = { git = "https://github.com/dashpay/rs-tenderdash-abci", version = "0.14.0-dev.12", tag = "v0.14.0-dev.12", default-features = false, features = [ + "grpc", +] } dapi-grpc-macros = { path = "../rs-dapi-grpc-macros" } platform-version = { path = "../rs-platform-version" } diff --git a/packages/rs-sdk/src/platform/query.rs b/packages/rs-sdk/src/platform/query.rs index 87500822006..2d21fa5f8ca 100644 --- a/packages/rs-sdk/src/platform/query.rs +++ b/packages/rs-sdk/src/platform/query.rs @@ -520,3 +520,27 @@ impl Query for VoteQuery { .into()) } } + +impl Query for LimitQuery { + fn query(self, prove: bool) -> Result { + if !prove { + unimplemented!("queries without proofs are not supported yet"); + } + use proto::get_contested_resource_identity_votes_request::{ + get_contested_resource_identity_votes_request_v0::StartAtVotePollIdInfo, Version, + }; + + Ok(match self.query.query(prove)?.version { + None => return Err(Error::Protocol(dpp::ProtocolError::NoProtocolVersionError)), + Some(Version::V0(v0)) => GetContestedResourceIdentityVotesRequestV0 { + limit: self.limit, + start_at_vote_poll_id_info: self.start_info.map(|v| StartAtVotePollIdInfo { + start_at_poll_identifier: v.start_key.to_vec(), + start_poll_identifier_included: v.start_included, + }), + ..v0 + }, + } + .into()) + } +} diff --git a/packages/rs-sdk/tests/fetch/contested_resource.rs b/packages/rs-sdk/tests/fetch/contested_resource.rs index e51aab350b9..a391b7b2a50 100644 --- a/packages/rs-sdk/tests/fetch/contested_resource.rs +++ b/packages/rs-sdk/tests/fetch/contested_resource.rs @@ -141,13 +141,14 @@ async fn contested_resources_start_at_value() { /// ## Preconditions /// /// 1. At least 3 contested resources (eg. different DPNS names) exist -// TODO: fails due to PLAN-656, not tested enough so it can be faulty #[tokio::test(flavor = "multi_thread", worker_threads = 1)] #[cfg_attr( feature = "network-testing", ignore = "requires manual DPNS names setup for masternode voting tests; see fn check_mn_voting_prerequisities()" )] -async fn contested_resources_limit() { +#[allow(non_snake_case)] +async fn contested_resources_limit_PLAN_656() { + // TODO: fails due to PLAN-656, not tested enough so it can be faulty setup_logs(); let cfg = Config::new(); @@ -244,7 +245,7 @@ async fn contested_resources_fields() { TestCase { name: "unmodified base query is Ok", query_mut_fn: |_q| {}, - expect: Ok("aaa"), + expect: Ok("ContestedResources([Value(Text("), }, TestCase { name: "index value empty string is Ok", @@ -273,7 +274,7 @@ async fn contested_resources_fields() { ), }, TestCase { - name: "start_at_value wrong index type returns InvalidArgument PLAN-563", + name: "start_at_value wrong index type returns InvalidArgument PLAN-653", query_mut_fn: |q| q.start_at_value = Some((Value::Array(vec![]), true)), expect: Err(r#"code: InvalidArgument"#), }, @@ -295,8 +296,7 @@ async fn contested_resources_fields() { Value::Text("dada".to_string()), ] }, - expect: Err("incorrect index values error: too many start values were provided, since no end index values \ - were provided, the start index values must be less than the amount of properties in the contested index"), + expect: Err("incorrect index values error: too many start index values were provided, since no end index values were provided, the start index values must be less than the amount of properties in the contested index"), }, TestCase { name: "end_index_values one value with empty start_index_values returns 'dash'", @@ -305,7 +305,7 @@ async fn contested_resources_fields() { q.end_index_values = vec![Value::Text("dada".to_string())]; }, expect:Ok(r#"ContestedResources([Value(Text("dash"))])"#), - }, + }, TestCase { name: "end_index_values two values (1 nx) with empty start_index_values returns error", query_mut_fn: |q| { @@ -329,7 +329,7 @@ async fn contested_resources_fields() { q.end_index_values = vec![Value::Text("zzz non existing".to_string())]; }, expect:Ok(r#"ContestedResources([])"#), - }, + }, TestCase { // fails due to PLAN-662 name: "too many items in start_index_values returns error", @@ -340,28 +340,27 @@ async fn contested_resources_fields() { Value::Text("eee".to_string()), ] }, - expect: Err("incorrect index values error: too many start values were provided, since no end index values \ - were provided, the start index values must be less than the amount of properties in the contested index"), + expect: Err("incorrect index values error: too many start index values were provided, since no end index values were provided, the start index values must be less than the amount of properties in the contested index"), }, TestCase { - name: "Non existing end_index_values starting with zzz returns all previous values PLAN-667", + name: "Both start_ and end_index_values returns error", query_mut_fn: |q| { q.end_index_values = vec![Value::Text("zzz non existing".to_string())] }, - expect: Ok(r#"ContestedResources([Value(Text("dash"))])"#), + expect: Err("incorrect index values error: too many end index values were provided"), }, TestCase { - name: "Non existing end_index_values starting with aaa returns nothing PLAN-667", + name: "Non-existing end_index_values returns error", query_mut_fn: |q| { - q.end_index_values = vec![Value::Text("aaa non existing".to_string())] + q.start_index_values = vec![]; + q.end_index_values = vec![Value::Text("zzz non existing".to_string())] }, - expect: Ok(r#"ContestedResources([Value(Text("dash"))])"#), + expect:Ok("ContestedResources([])"), }, TestCase { - // fails due to PLAN-663 - name: "wrong type of end_index_values should return InvalidArgument PLAN-663 PLAN-667", + name: "wrong type of end_index_values should return InvalidArgument", query_mut_fn: |q| q.end_index_values = vec![Value::Array(vec![0.into(), 1.into()])], - expect: Err(r#"code: InvalidArgument a"#), + expect: Err("incorrect index values error: too many end index values were provided"), }, TestCase { name: "limit 0 returns InvalidArgument", @@ -373,6 +372,17 @@ async fn contested_resources_fields() { query_mut_fn: |q| q.limit = Some(std::u16::MAX), expect: Err(r#"code: InvalidArgument"#), }, + TestCase{ + name: "exact match query returns one object PLAN-656", + query_mut_fn: |q| { + q.start_index_values = vec![Value::Text("dash".to_string())]; + q.start_at_value = Some((Value::Text("dada".to_string()), true)); + q.limit = Some(1); + }, + expect: Ok(r#"ContestedResources([Value(Text("dada"))])"#), + + } + // start index + start at + limit 1 ]; let cfg = Config::new(); diff --git a/packages/rs-sdk/tests/fetch/contested_resource_identity_votes.rs b/packages/rs-sdk/tests/fetch/contested_resource_identity_votes.rs index 0902e88d774..09f358109c7 100644 --- a/packages/rs-sdk/tests/fetch/contested_resource_identity_votes.rs +++ b/packages/rs-sdk/tests/fetch/contested_resource_identity_votes.rs @@ -3,7 +3,9 @@ use crate::fetch::{common::setup_logs, config::Config}; use dash_sdk::platform::FetchMany; use dpp::{ - dashcore::ProTxHash, identifier::Identifier, voting::votes::resource_vote::ResourceVote, + dashcore::{hashes::Hash, ProTxHash}, + identifier::Identifier, + voting::votes::resource_vote::ResourceVote, }; use drive::query::contested_resource_votes_given_by_identity_query::ContestedResourceVotesGivenByIdentityQuery; @@ -41,9 +43,38 @@ async fn contested_resource_identity_votes_not_found() { /// ## Preconditions /// /// 1. At least one vote exists for the given masternode identity (protx hash). +/// +/// ## Setup process +/// +/// In order to setup this test, you need to: +/// +/// 0. Ensure you have at least 1 contested DPNS name `dada` in the system. +/// +/// 1. Grep log output of `yarn setup` to find `ProRegTx transaction ID` and `Owner Private Key`. +/// Use `ProRegTx transaction ID` as `protx_hex` variable below. +/// +/// 2. Load masternode identity into [rs-platform-explorer](https://github.com/dashpay/rs-platform-explorer/): +/// +/// * ensure `.env` file contains correct configuration +/// * start tui with `cargo run` +/// * select `w - wallet` +/// * ensure a wallet with positive balance is loaded; if not - load it (getting a wallet is out of scope of this document) +/// * select `p - Load Evonode Identity`. +/// * enter `ProRegTx transaction ID` and `Owner Private Key` from step 1. +/// * top up the identity balance using `t - Identity top up` option (1 DASH will be OK). +/// * exit Wallet screen using `q - Back to Main` +/// +/// 3. Vote for some contested resource using the masternode identity: +/// +/// * select `csnq`: `c - Contracts` -> `s - Fetch system contract` -> `n - Fetch DPNS contract` -> `q - Back to Contracts ` +/// * press ENTER to enter the fetched contract, then select `domain` -> `c - Query Contested Resources` +/// * Select `string dada`, use `v - Vote`, select some identity. +/// +/// Now, vote should be casted and you can run this test. +/// #[cfg_attr( feature = "network-testing", - ignore = "requires manual DPNS names setup for masternode voting tests; see fn check_mn_voting_prerequisities()" + ignore = "requires manual DPNS names setup for masternode voting tests; see docs of contested_resource_identity_votes_ok()" )] #[tokio::test(flavor = "multi_thread", worker_threads = 1)] async fn contested_resource_identity_votes_ok() { @@ -56,14 +87,17 @@ async fn contested_resource_identity_votes_ok() { // TODO: Fetch proTxHash from the network instead of hardcoding; it's not so trivial as it must support our mocking // mechanisms - let protx_hex = "7624E7D0D7C8837D4D02A19700F4116091A8AD145352420193DE8828F6D00BBF"; - let protx = ProTxHash::from_hex(protx_hex).expect("ProTxHash from hex"); + let protx_hex = "53fe73c78179e69a2e9dbe6c04ca0b6d4da596e5e8df0b5dc41a121bf5bda5a3"; + let protx = ProTxHash::from_slice(&hex::decode(protx_hex).expect("ProTxHash from hex")) + .expect("ProTxHash from slice"); // When I query for votes given by this identity let votes = ResourceVote::fetch_many(&sdk, protx) .await .expect("fetch votes for identity"); + tracing::debug!(?protx, ?votes, "votes of masternode"); + // Then I get some votes assert!(!votes.is_empty(), "votes expected for this query"); } diff --git a/packages/rs-sdk/tests/fetch/contested_resource_polls_by_ts.rs b/packages/rs-sdk/tests/fetch/contested_resource_polls_by_ts.rs index cb3273c5ba3..c82de4be2e4 100644 --- a/packages/rs-sdk/tests/fetch/contested_resource_polls_by_ts.rs +++ b/packages/rs-sdk/tests/fetch/contested_resource_polls_by_ts.rs @@ -52,8 +52,8 @@ async fn vote_polls_by_ts_ok() { feature = "network-testing", ignore = "requires manual DPNS names setup for masternode voting tests; see fn check_mn_voting_prerequisities()" )] -// fails due to PLAN-661 -async fn vote_polls_by_ts_order() { +#[allow(non_snake_case)] +async fn vote_polls_by_ts_order_PLAN_661() { setup_logs(); let cfg = Config::new(); diff --git a/packages/rs-sdk/tests/fetch/contested_resource_vote_state.rs b/packages/rs-sdk/tests/fetch/contested_resource_vote_state.rs index a7b6539e047..a2666a2f113 100644 --- a/packages/rs-sdk/tests/fetch/contested_resource_vote_state.rs +++ b/packages/rs-sdk/tests/fetch/contested_resource_vote_state.rs @@ -40,7 +40,7 @@ async fn contested_resource_vote_states_not_found() { start_at: None, vote_poll: ContestedDocumentResourceVotePoll { index_name: "parentNameAndLabel".to_string(), - index_values: vec![label.into()], + index_values: vec!["nx".into(), label.into()], document_type_name: cfg.existing_document_type_name, contract_id: data_contract_id, }, @@ -188,7 +188,8 @@ async fn contested_resource_vote_states_ok() { /// 1. There must be at least 3 condenders for name "dash" and value "dada". /// #[tokio::test(flavor = "multi_thread", worker_threads = 1)] -async fn contested_resource_vote_states_with_limit() { +#[allow(non_snake_case)] +async fn contested_resource_vote_states_with_limit_PLAN_674() { setup_logs(); let cfg = Config::new(); @@ -222,10 +223,12 @@ async fn contested_resource_vote_states_with_limit() { let all_contenders = ContenderWithSerializedDocument::fetch_many(&sdk, query_all.clone()) .await .expect("fetch many contenders") - .contenders - .len(); + .contenders; + + tracing::debug!(?all_contenders, "All contenders"); + assert!( - all_contenders > limit as usize, + all_contenders.len() > limit as usize, "we need more than {} contenders for this test", limit ); @@ -236,11 +239,11 @@ async fn contested_resource_vote_states_with_limit() { ..query_all }; - let contenders = ContenderWithSerializedDocument::fetch_many(&sdk, query) + let contenders = ContenderWithSerializedDocument::fetch_many(&sdk, query.clone()) .await .expect("fetch many contenders"); // Then I get no more than the limit of contenders - tracing::debug!(contenders=?contenders, "Contenders"); + tracing::debug!(contenders=?contenders, ?query, "Contenders"); assert_eq!( contenders.contenders.len(), diff --git a/packages/rs-sdk/tests/fetch/contested_resource_voters.rs b/packages/rs-sdk/tests/fetch/contested_resource_voters.rs index 20ef80e0aa9..bb153d1057f 100644 --- a/packages/rs-sdk/tests/fetch/contested_resource_voters.rs +++ b/packages/rs-sdk/tests/fetch/contested_resource_voters.rs @@ -1,13 +1,26 @@ //! Test GetContestedResourceVotersForIdentityRequest -use dash_sdk::platform::{Fetch, FetchMany}; -use dpp::{identifier::Identifier, identity::Identity, platform_value::Value}; -use drive::query::vote_poll_contestant_votes_query::ContestedDocumentVotePollVotesDriveQuery; +use dash_sdk::platform::FetchMany; +use dpp::{ + identifier::Identifier, + platform_value::{string_encoding::Encoding, Value}, + voting::contender_structs::ContenderWithSerializedDocument, +}; +use drive::query::{ + vote_poll_contestant_votes_query::ContestedDocumentVotePollVotesDriveQuery, + vote_poll_vote_state_query::{ + ContestedDocumentVotePollDriveQuery, ContestedDocumentVotePollDriveQueryResultType, + }, +}; use drive_proof_verifier::types::Voter; use crate::fetch::{common::setup_logs, config::Config}; /// When we request votes for a non-existing identity, we should get no votes. +#[cfg_attr( + feature = "network-testing", + ignore = "requires manual DPNS names setup for masternode voting tests; see docs of contested_resource_identity_votes_ok()" +)] #[tokio::test(flavor = "multi_thread", worker_threads = 1)] async fn test_contested_resource_voters_for_identity_not_found() { setup_logs(); @@ -56,44 +69,70 @@ async fn contested_resource_voters_for_existing_contestant() { .setup_api("contested_resource_voters_for_existing_contestant") .await; - // Given a known contestant ID that has votes - // TODO: lookup contestant ID - let contestant_id = Identifier::from_string( - "D63rWKSagCgEE53XPkouP3swN9n87jHvjesFEZEh1cLr", - dpp::platform_value::string_encoding::Encoding::Base58, - ) - .expect("valid contestant ID"); - - let index_name = "parentNameAndLabel"; + let index_name = "parentNameAndLabel".to_string(); let index_value = Value::Text("dada".to_string()); - // double-check that the contestant identity exist - let _contestant_identity = Identity::fetch(&sdk, contestant_id) + + // fetch contestant + let contestants_query = ContestedDocumentVotePollDriveQuery { + vote_poll: dpp::voting::vote_polls::contested_document_resource_vote_poll::ContestedDocumentResourceVotePoll { + contract_id: cfg.existing_data_contract_id, + document_type_name: cfg.existing_document_type_name.clone(), + index_name:index_name.clone(), + index_values: vec![Value::Text("dash".into()),index_value.clone()], + }, + limit: None, // TODO: Change to Some(1) when PLAN-656 is fixed + offset:None, + allow_include_locked_and_abstaining_vote_tally:true, + start_at: None, + result_type: ContestedDocumentVotePollDriveQueryResultType::DocumentsAndVoteTally, + }; + + let contenders = ContenderWithSerializedDocument::fetch_many(&sdk, contestants_query) .await - .expect("fetch identity") - .expect("contestant identity must exist"); + .expect("fetch contenders"); + let contender_ids = contenders + .contenders + .keys() + .map(|id| id.to_string(Encoding::Base58)) + .collect::>(); + tracing::debug!( + contenders = ?contender_ids, + "contenders for {}", + &index_value + ); - // When I query for votes given to this contestant - let query = ContestedDocumentVotePollVotesDriveQuery { + let mut votes = 0; + + for contestant in contenders.contenders.keys() { + let query = ContestedDocumentVotePollVotesDriveQuery { limit: None, offset: None, - order_ascending: true, start_at: None, + order_ascending: true, vote_poll: dpp::voting::vote_polls::contested_document_resource_vote_poll::ContestedDocumentResourceVotePoll { contract_id: cfg.existing_data_contract_id, - document_type_name: cfg.existing_document_type_name, + document_type_name: cfg.existing_document_type_name.clone(), index_name: index_name.to_string(), - index_values: vec!["dash".into(), index_value], + index_values: vec!["dash".into(), index_value.clone()], }, - contestant_id, + contestant_id:*contestant, }; - let rss = Voter::fetch_many(&sdk, query) - .await - .expect("fetch contested resources"); + let rss = Voter::fetch_many(&sdk, query) + .await + .expect("fetch contested resources"); + + tracing::debug!( + ?rss, + contender = contestant.to_string(Encoding::Base58), + "votes retrieved" + ); + votes += rss.0.len(); + } // We expect to find votes for the known contestant - assert!( - !rss.0.is_empty(), - "Expected to find votes for the existing contestant" + assert_ne!( + votes, 0, + "Expected to find at least one vote for any of the contestants" ); } diff --git a/packages/rs-sdk/tests/fetch/document.rs b/packages/rs-sdk/tests/fetch/document.rs index 942687eaa61..cc44b325671 100644 --- a/packages/rs-sdk/tests/fetch/document.rs +++ b/packages/rs-sdk/tests/fetch/document.rs @@ -188,7 +188,8 @@ async fn document_list_document_query() { /// then I don't get error: /// `query: storage: protocol: value error: structure error: value was a string, but could not be decoded from base 58`. #[tokio::test(flavor = "multi_thread", worker_threads = 1)] -async fn document_list_bug_value_text_decode_base58() { +#[allow(non_snake_case)] +async fn document_list_bug_value_text_decode_base58_PLAN_653() { setup_logs(); let cfg = Config::new(); From 7f3f3a5c4543cd1235ce2118693a52bcb55f9704 Mon Sep 17 00:00:00 2001 From: Lukasz Klimek <842586+lklimek@users.noreply.github.com> Date: Fri, 28 Jun 2024 16:03:12 +0200 Subject: [PATCH 38/55] chore(drive-proof-verifier): remove unused OrderedBTreeMap --- packages/rs-drive-proof-verifier/src/lib.rs | 1 - .../src/ordered_btreemap.rs | 130 ------------------ 2 files changed, 131 deletions(-) delete mode 100644 packages/rs-drive-proof-verifier/src/ordered_btreemap.rs diff --git a/packages/rs-drive-proof-verifier/src/lib.rs b/packages/rs-drive-proof-verifier/src/lib.rs index 21b45a876d3..bf38d555ef7 100644 --- a/packages/rs-drive-proof-verifier/src/lib.rs +++ b/packages/rs-drive-proof-verifier/src/lib.rs @@ -3,7 +3,6 @@ /// Errors that can occur during proof verification pub mod error; -pub mod ordered_btreemap; /// Implementation of proof verification mod proof; mod provider; diff --git a/packages/rs-drive-proof-verifier/src/ordered_btreemap.rs b/packages/rs-drive-proof-verifier/src/ordered_btreemap.rs deleted file mode 100644 index 16c9fc8f8a0..00000000000 --- a/packages/rs-drive-proof-verifier/src/ordered_btreemap.rs +++ /dev/null @@ -1,130 +0,0 @@ -//! [BTreeMap] that can be ordered in either ascending or descending order. -use bincode::{Decode, Encode}; -use std::collections::btree_map::{Iter, Keys}; -use std::{collections::BTreeMap, iter::Rev}; - -/// Iterator that can be either forward or reverse. -/// -/// Used to iterate over items in a map in either ascending or descending order. -pub enum OrderedIterator { - /// Items are iterated in ascending order. - Ascending(I), - /// Items are iterated in descending order. - Descending(Rev), -} - -/// BTreeMap that can be ordered in either ascending or descending order. -#[derive(Clone, Debug, Default, derive_more::From)] -#[cfg_attr(feature = "mocks", derive(Encode, Decode))] - -pub struct OrderedBTreeMap { - /// The inner map. - inner: BTreeMap, - /// When set to true, the map will be ordered in ascending order. - order_ascending: bool, -} - -impl OrderedBTreeMap { - /// Create a new OrderedBTreeMap with provided ordering. - pub fn new(order_ascending: bool) -> Self { - Self { - inner: BTreeMap::new(), - order_ascending, - } - } - - /// Creates a new OrderedBTreeMap from a BTreeMap with the provided ordering. - /// - /// This function consumes the provided map to avoid cloning it, thus it is more efficient than - /// creating a new OrderedBTreeMap and then extending it with the provided map. - pub fn from_btreemap(map: BTreeMap, order_ascending: bool) -> Self { - Self { - inner: map, - order_ascending, - } - } - - /// Returns an iterator over the map. - /// - /// See [BTreemap::iter()] for more information. - pub fn iter(&self) -> OrderedIterator> { - if self.order_ascending { - OrderedIterator::Ascending(self.inner.iter()) - } else { - OrderedIterator::Descending(self.inner.iter().rev()) - } - } - - /// Returns true if the map is empty. - pub fn is_empty(&self) -> bool { - self.inner.is_empty() - } - - /// Returns the number of elements in the map. - pub fn len(&self) -> usize { - self.inner.len() - } - - /// Gets an iterator over the keys of the map, in sorted order. - pub fn keys(&self) -> OrderedIterator> { - if self.order_ascending { - OrderedIterator::Ascending(self.inner.keys()) - } else { - OrderedIterator::Descending(self.inner.keys().rev()) - } - } - - /// Gets all values in the map as a vector, ordered by key. - pub fn values_vec(&self) -> Vec<&V> { - self.iter().map(|(_k, v)| v).collect() - } -} - -impl From> for BTreeMap { - fn from(value: OrderedBTreeMap) -> Self { - value.inner - } -} - -impl Extend<(K, V)> for OrderedBTreeMap { - fn extend(&mut self, iter: T) - where - T: IntoIterator, - { - self.inner.extend(iter) - } -} - -impl From> for OrderedBTreeMap { - fn from(value: BTreeMap) -> Self { - Self { - inner: value, - order_ascending: true, // btreemap is always ordered in ascending order - } - } -} - -impl IntoIterator for OrderedBTreeMap { - type Item = (K, V); - type IntoIter = OrderedIterator< as IntoIterator>::IntoIter>; - - fn into_iter(self) -> Self::IntoIter { - let iter = self.inner.into_iter(); - if self.order_ascending { - OrderedIterator::Ascending(iter) - } else { - OrderedIterator::Descending(iter.rev()) - } - } -} - -impl Iterator for OrderedIterator { - type Item = I::Item; - - fn next(&mut self) -> Option { - match self { - OrderedIterator::Ascending(iter) => iter.next(), - OrderedIterator::Descending(iter) => iter.next(), - } - } -} From bdfe46f994988bc8a07861f752dc346e0ca5f209 Mon Sep 17 00:00:00 2001 From: Lukasz Klimek <842586+lklimek@users.noreply.github.com> Date: Fri, 28 Jun 2024 16:07:10 +0200 Subject: [PATCH 39/55] refactor(sdk): VotePollsGroupedByTimestamp uses Vec, not BTreeMap --- packages/rs-drive-proof-verifier/src/proof.rs | 6 +-- packages/rs-drive-proof-verifier/src/types.rs | 45 +++++++++++-------- .../fetch/contested_resource_polls_by_ts.rs | 8 ++-- 3 files changed, 33 insertions(+), 26 deletions(-) diff --git a/packages/rs-drive-proof-verifier/src/proof.rs b/packages/rs-drive-proof-verifier/src/proof.rs index 4093e30814a..dcb02817b4c 100644 --- a/packages/rs-drive-proof-verifier/src/proof.rs +++ b/packages/rs-drive-proof-verifier/src/proof.rs @@ -1460,7 +1460,7 @@ impl FromProof for VotePollsGroupedByTim let mtd = response.metadata().or(Err(Error::EmptyResponseMetadata))?; let (root_hash, vote_polls) = drive_query - .verify_vote_polls_by_end_date_proof::>( + .verify_vote_polls_by_end_date_proof::>( &proof.grovedb_proof, platform_version, ) @@ -1470,7 +1470,7 @@ impl FromProof for VotePollsGroupedByTim verify_tenderdash_proof(proof, mtd, &root_hash, provider)?; - let response = VotePollsGroupedByTimestamp(vote_polls); + let response = VotePollsGroupedByTimestamp(vote_polls).sorted(drive_query.order_ascending); Ok((response.into_option(), mtd.clone())) } @@ -1668,7 +1668,7 @@ define_length!(Contenders, |x: &Contenders| x.contenders.len()); define_length!(Voters, |x: &Voters| x.0.len()); define_length!( VotePollsGroupedByTimestamp, - |x: &VotePollsGroupedByTimestamp| x.0.values_vec().into_iter().map(|v| v.len()).sum() + |x: &VotePollsGroupedByTimestamp| x.0.iter().map(|v| v.1.len()).sum() ); trait IntoOption where diff --git a/packages/rs-drive-proof-verifier/src/types.rs b/packages/rs-drive-proof-verifier/src/types.rs index 99d15ee1263..df390d3cd2c 100644 --- a/packages/rs-drive-proof-verifier/src/types.rs +++ b/packages/rs-drive-proof-verifier/src/types.rs @@ -5,7 +5,6 @@ //! In this case, the [FromProof](crate::FromProof) trait is implemented for dedicated object type //! defined in this module. -use crate::ordered_btreemap::{OrderedBTreeMap, OrderedIterator}; use dpp::data_contract::document_type::DocumentType; use dpp::fee::Credits; use dpp::platform_value::Value; @@ -26,7 +25,6 @@ use dpp::{ util::deserializer::ProtocolVersion, }; use drive::grovedb::Element; -use std::collections::btree_map::IntoIter; use std::collections::{BTreeMap, BTreeSet}; #[cfg(feature = "mocks")] @@ -296,26 +294,35 @@ impl From<&PrefundedSpecializedBalance> for Credits { derive(Encode, Decode, PlatformSerialize, PlatformDeserialize), platform_serialize(unversioned) )] -pub struct VotePollsGroupedByTimestamp(pub OrderedBTreeMap>); +pub struct VotePollsGroupedByTimestamp(pub Vec<(TimestampMillis, Vec)>); +impl VotePollsGroupedByTimestamp { + /// Sort the vote polls by timestamp. + pub fn sorted(mut self, ascending: bool) -> Self { + self.0.sort_by(|a, b| { + if ascending { + a.0.cmp(&b.0) + } else { + b.0.cmp(&a.0) + } + }); + + self + } +} /// Insert items into the map, appending them to the existing values for the same key. impl FromIterator<(u64, Vec)> for VotePollsGroupedByTimestamp { fn from_iter)>>(iter: T) -> Self { - let mut map = BTreeMap::new(); - - let mut order_ascending = true; - let mut prev = 0; - for (timestamp, vote_poll) in iter { - let entry = map.entry(timestamp).or_insert_with(Vec::new); - entry.extend(vote_poll); - - if timestamp < prev { - order_ascending = false; - } - prev = timestamp; - } - - OrderedBTreeMap::from_btreemap(map, order_ascending).into() + // collect all vote polls for the same timestamp into a single vector + let data = iter + .into_iter() + .fold(BTreeMap::new(), |mut acc, (timestamp, vote_poll)| { + let entry: &mut Vec = acc.entry(timestamp).or_default(); + entry.extend(vote_poll); + acc + }); + + Self(data.into_iter().collect()) } } @@ -339,7 +346,7 @@ impl FromIterator<(u64, Option)> for VotePollsGroupedByTimestamp { impl IntoIterator for VotePollsGroupedByTimestamp { type Item = (u64, Vec); - type IntoIter = OrderedIterator>>; + type IntoIter = std::vec::IntoIter<(u64, Vec)>; fn into_iter(self) -> Self::IntoIter { self.0.into_iter() diff --git a/packages/rs-sdk/tests/fetch/contested_resource_polls_by_ts.rs b/packages/rs-sdk/tests/fetch/contested_resource_polls_by_ts.rs index c82de4be2e4..3cb4006678e 100644 --- a/packages/rs-sdk/tests/fetch/contested_resource_polls_by_ts.rs +++ b/packages/rs-sdk/tests/fetch/contested_resource_polls_by_ts.rs @@ -178,7 +178,7 @@ async fn vote_polls_by_ts_limit() { .await .expect("fetch vote polls"); - let Some(last) = rss.0.keys().last().copied() else { + let Some(last) = rss.0.last() else { // no more vote polls break; }; @@ -194,12 +194,12 @@ async fn vote_polls_by_ts_limit() { }; let expected = &all_values[all_idx]; assert_eq!( - *current.0, expected.0, + current.0, expected.0, "inclusive {}: timestamp should match", inclusive ); assert_eq!( - current.1, &expected.1, + ¤t.1, &expected.1, "inclusive {}: vote polls should match", inclusive ); @@ -207,7 +207,7 @@ async fn vote_polls_by_ts_limit() { tracing::debug!(polls=?rss, checked_count, ?start_time, "Vote polls"); - start_time = Some((last, inclusive)); + start_time = Some((last.0, inclusive)); // when inclusive, we include the first item in checked_count only on first iteration checked_count += if inclusive && checked_count != 0 { length - 1 From 4cf0f83f44c5582874088345bdfca993514d5178 Mon Sep 17 00:00:00 2001 From: Lukasz Klimek <842586+lklimek@users.noreply.github.com> Date: Fri, 28 Jun 2024 17:25:39 +0200 Subject: [PATCH 40/55] fix(sdk): broadcasting state transition missing impl of contract provider --- packages/rs-drive-proof-verifier/src/lib.rs | 2 +- packages/rs-drive-proof-verifier/src/proof.rs | 29 +++++-------------- .../rs-drive-proof-verifier/src/provider.rs | 22 ++++++++++++++ .../v0/mod.rs | 7 +++-- .../src/platform/transition/broadcast.rs | 9 +++++- .../src/platform/transition/put_contract.rs | 9 +++++- .../src/platform/transition/put_identity.rs | 9 +++++- .../platform/transition/top_up_identity.rs | 9 +++++- .../rs-sdk/src/platform/transition/vote.rs | 8 ++++- .../transition/withdraw_from_identity.rs | 9 +++++- packages/rs-sdk/src/sdk.rs | 3 ++ 11 files changed, 85 insertions(+), 31 deletions(-) diff --git a/packages/rs-drive-proof-verifier/src/lib.rs b/packages/rs-drive-proof-verifier/src/lib.rs index bf38d555ef7..7e28b6691fe 100644 --- a/packages/rs-drive-proof-verifier/src/lib.rs +++ b/packages/rs-drive-proof-verifier/src/lib.rs @@ -10,9 +10,9 @@ pub mod types; mod verify; pub use error::Error; pub use proof::{FromProof, Length}; -pub use provider::ContextProvider; #[cfg(feature = "mocks")] pub use provider::MockContextProvider; +pub use provider::{ContextProvider, DataContractProvider}; pub mod from_request; // Needed for #[derive(PlatformSerialize, PlatformDeserialize)] diff --git a/packages/rs-drive-proof-verifier/src/proof.rs b/packages/rs-drive-proof-verifier/src/proof.rs index dcb02817b4c..618e9b1e468 100644 --- a/packages/rs-drive-proof-verifier/src/proof.rs +++ b/packages/rs-drive-proof-verifier/src/proof.rs @@ -1,4 +1,5 @@ use crate::from_request::TryFromRequest; +use crate::provider::DataContractProvider; use crate::{types, types::*, ContextProvider, Error}; use dapi_grpc::platform::v0::get_identities_contract_keys_request::GetIdentitiesContractKeysRequestV0; use dapi_grpc::platform::v0::get_path_elements_request::GetPathElementsRequestV0; @@ -46,11 +47,10 @@ use drive::query::contested_resource_votes_given_by_identity_query::ContestedRes use drive::query::vote_poll_contestant_votes_query::ContestedDocumentVotePollVotesDriveQuery; use drive::query::vote_poll_vote_state_query::ContestedDocumentVotePollDriveQuery; use drive::query::vote_polls_by_document_type_query::VotePollsByDocumentTypeQuery; -use drive::query::{ContractLookupFn, DriveQuery, VotePollsByEndDateDriveQuery}; +use drive::query::{DriveQuery, VotePollsByEndDateDriveQuery}; use std::array::TryFromSliceError; use std::collections::BTreeMap; use std::num::TryFromIntError; -use std::sync::Arc; use crate::verify::verify_tenderdash_proof; @@ -861,7 +861,7 @@ impl FromProof for StateTransitionPro epoch: (metadata.epoch as u16).try_into()?, }; - let contracts_provider_fn = known_contracts_provider_fn(provider); + let contracts_provider_fn = provider.as_contract_lookup_fn(); let (root_hash, result) = Drive::verify_state_transition_was_executed_with_proof( &state_transition, @@ -1271,8 +1271,8 @@ impl FromProof for ContestedResources { // Decode request to get drive query let drive_query = VotePollsByDocumentTypeQuery::try_from_request(request)?; - let resolved_request = drive_query - .resolve_with_known_contracts_provider(&known_contracts_provider_fn(provider))?; + let resolved_request = + drive_query.resolve_with_known_contracts_provider(&provider.as_contract_lookup_fn())?; // Parse response to read proof and metadata let proof = response.proof().or(Err(Error::NoProofInResult))?; @@ -1314,7 +1314,7 @@ impl FromProof for Contenders { let drive_query = ContestedDocumentVotePollDriveQuery::try_from_request(request)?; // Resolve request to get verify_*_proof - let contracts_provider = known_contracts_provider_fn(provider); + let contracts_provider = provider.as_contract_lookup_fn(); let resolved_request = drive_query.resolve_with_known_contracts_provider(&contracts_provider)?; @@ -1365,7 +1365,7 @@ impl FromProof for Voters { let drive_query = ContestedDocumentVotePollVotesDriveQuery::try_from_request(request)?; // Parse request to get resolved contract that implements verify_*_proof - let contracts_provider = known_contracts_provider_fn(provider); + let contracts_provider = provider.as_contract_lookup_fn(); let resolved_request = drive_query.resolve_with_known_contracts_provider(&contracts_provider)?; @@ -1414,7 +1414,7 @@ impl FromProof for ResourceV let proof = response.proof().or(Err(Error::NoProofInResult))?; let mtd = response.metadata().or(Err(Error::EmptyResponseMetadata))?; - let contract_provider_fn = known_contracts_provider_fn(provider); + let contract_provider_fn = provider.as_contract_lookup_fn(); let (root_hash, voters) = drive_query .verify_identity_votes_given_proof::>( &proof.grovedb_proof, @@ -1587,19 +1587,6 @@ fn u32_to_u16_opt(i: u32) -> Result, Error> { Ok(i) } -/// Returns function that uses [ContextProvider] to provide a [DataContract] to Drive proof verification functions -fn known_contracts_provider_fn<'a, P: ContextProvider + ?Sized + 'a>( - provider: &'a P, -) -> Box { - let f = |id: &Identifier| -> Result>, drive::error::Error> { - provider.get_data_contract(id).map_err(|e| { - drive::error::Error::Proof(ProofError::ErrorRetrievingContract(e.to_string())) - }) - }; - - Box::new(f) -} - /// Determine number of non-None elements pub trait Length { /// Return number of non-None elements in the data structure diff --git a/packages/rs-drive-proof-verifier/src/provider.rs b/packages/rs-drive-proof-verifier/src/provider.rs index 305154207e7..bc60cfed2b1 100644 --- a/packages/rs-drive-proof-verifier/src/provider.rs +++ b/packages/rs-drive-proof-verifier/src/provider.rs @@ -1,5 +1,6 @@ use crate::error::ContextProviderError; use dpp::prelude::{DataContract, Identifier}; +use drive::{error::proof::ProofError, query::ContractLookupFn}; #[cfg(feature = "mocks")] use hex::ToHex; use std::{io::ErrorKind, ops::Deref, sync::Arc}; @@ -95,6 +96,27 @@ where } } +/// A trait that provides a function that can be used to look up a [DataContract] by its [Identifier]. +/// +/// This trait is automatically implemented for any type that implements [ContextProvider]. +/// It is used internally by the Drive proof verification functions to look up data contracts. +pub trait DataContractProvider: Send + Sync { + /// Returns [ContractLookupFn] function that can be used to look up a [DataContract] by its [Identifier]. + fn as_contract_lookup_fn(&self) -> Box; +} +impl DataContractProvider for C { + /// Returns function that uses [ContextProvider] to provide a [DataContract] to Drive proof verification functions + fn as_contract_lookup_fn(&self) -> Box { + let f = |id: &Identifier| -> Result>, drive::error::Error> { + self.get_data_contract(id).map_err(|e| { + drive::error::Error::Proof(ProofError::ErrorRetrievingContract(e.to_string())) + }) + }; + + Box::new(f) + } +} + /// Mock ContextProvider that can read quorum keys from files. /// /// Use [dash_sdk::SdkBuilder::with_dump_dir()] to generate quorum keys files. diff --git a/packages/rs-drive/src/drive/verify/state_transition/verify_state_transition_was_executed_with_proof/v0/mod.rs b/packages/rs-drive/src/drive/verify/state_transition/verify_state_transition_was_executed_with_proof/v0/mod.rs index f9e9d18ded4..7e904267e64 100644 --- a/packages/rs-drive/src/drive/verify/state_transition/verify_state_transition_was_executed_with_proof/v0/mod.rs +++ b/packages/rs-drive/src/drive/verify/state_transition/verify_state_transition_was_executed_with_proof/v0/mod.rs @@ -114,11 +114,12 @@ impl Drive { let document_type = contract .document_type_for_name(transition.document_type_name()) - .map_err(|_| { + .map_err(|e| { Error::Proof(ProofError::UnknownContract(format!( - "unknown contract document {} with id {}", + "cannot fetch contract for document {} with id {}: {}", transition.document_type_name(), - transition.data_contract_id() + transition.data_contract_id(), + e ))) })?; diff --git a/packages/rs-sdk/src/platform/transition/broadcast.rs b/packages/rs-sdk/src/platform/transition/broadcast.rs index b8c0089d3f9..5c050ce8cff 100644 --- a/packages/rs-sdk/src/platform/transition/broadcast.rs +++ b/packages/rs-sdk/src/platform/transition/broadcast.rs @@ -5,6 +5,8 @@ use dapi_grpc::platform::VersionedGrpcResponse; use dpp::state_transition::proof_result::StateTransitionProofResult; use dpp::state_transition::StateTransition; use drive::drive::Drive; +use drive_proof_verifier::error::ContextProviderError; +use drive_proof_verifier::DataContractProvider; use rs_dapi_client::{DapiRequest, RequestSettings}; #[async_trait::async_trait] @@ -47,12 +49,17 @@ impl BroadcastStateTransition for StateTransition { let block_info = block_info_from_metadata(response.metadata()?)?; let proof = response.proof_owned()?; + let context_provider = + sdk.context_provider() + .ok_or(Error::from(ContextProviderError::Config( + "Context provider not initialized".to_string(), + )))?; let (_, result) = Drive::verify_state_transition_was_executed_with_proof( self, &block_info, proof.grovedb_proof.as_slice(), - &|_| Ok(None), + &context_provider.as_contract_lookup_fn(), sdk.version(), )?; diff --git a/packages/rs-sdk/src/platform/transition/put_contract.rs b/packages/rs-sdk/src/platform/transition/put_contract.rs index 79d8e87d5ac..fb7e55b5bc0 100644 --- a/packages/rs-sdk/src/platform/transition/put_contract.rs +++ b/packages/rs-sdk/src/platform/transition/put_contract.rs @@ -16,6 +16,8 @@ use dpp::state_transition::data_contract_create_transition::DataContractCreateTr use dpp::state_transition::proof_result::StateTransitionProofResult; use dpp::state_transition::StateTransition; use drive::drive::Drive; +use drive_proof_verifier::error::ContextProviderError; +use drive_proof_verifier::DataContractProvider; use rs_dapi_client::{DapiRequest, RequestSettings}; #[async_trait::async_trait] @@ -103,12 +105,17 @@ impl PutContract for DataContract { let block_info = block_info_from_metadata(response.metadata()?)?; let proof = response.proof_owned()?; + let context_provider = + sdk.context_provider() + .ok_or(Error::from(ContextProviderError::Config( + "Context provider not initialized".to_string(), + )))?; let (_, result) = Drive::verify_state_transition_was_executed_with_proof( &state_transition, &block_info, proof.grovedb_proof.as_slice(), - &|_| Ok(None), + &context_provider.as_contract_lookup_fn(), sdk.version(), )?; diff --git a/packages/rs-sdk/src/platform/transition/put_identity.rs b/packages/rs-sdk/src/platform/transition/put_identity.rs index 6e4283c26a4..59422aa6b2b 100644 --- a/packages/rs-sdk/src/platform/transition/put_identity.rs +++ b/packages/rs-sdk/src/platform/transition/put_identity.rs @@ -8,6 +8,8 @@ use dapi_grpc::tonic::Code; use dpp::dashcore::PrivateKey; use dpp::identity::signer::Signer; use dpp::prelude::{AssetLockProof, Identity}; +use drive_proof_verifier::error::ContextProviderError; +use drive_proof_verifier::DataContractProvider; use crate::platform::block_info_from_metadata::block_info_from_metadata; use dpp::state_transition::proof_result::StateTransitionProofResult; @@ -103,12 +105,17 @@ impl PutIdentity for Identity { let block_info = block_info_from_metadata(response.metadata()?)?; let proof = response.proof_owned()?; + let context_provider = + sdk.context_provider() + .ok_or(Error::from(ContextProviderError::Config( + "Context provider not initialized".to_string(), + )))?; let (_, result) = Drive::verify_state_transition_was_executed_with_proof( &state_transition, &block_info, proof.grovedb_proof.as_slice(), - &|_| Ok(None), + &context_provider.as_contract_lookup_fn(), sdk.version(), )?; diff --git a/packages/rs-sdk/src/platform/transition/top_up_identity.rs b/packages/rs-sdk/src/platform/transition/top_up_identity.rs index 59b776df4a0..48145234f49 100644 --- a/packages/rs-sdk/src/platform/transition/top_up_identity.rs +++ b/packages/rs-sdk/src/platform/transition/top_up_identity.rs @@ -9,6 +9,8 @@ use dpp::state_transition::identity_topup_transition::methods::IdentityTopUpTran use dpp::state_transition::identity_topup_transition::IdentityTopUpTransition; use dpp::state_transition::proof_result::StateTransitionProofResult; use drive::drive::Drive; +use drive_proof_verifier::error::ContextProviderError; +use drive_proof_verifier::DataContractProvider; use rs_dapi_client::{DapiRequest, RequestSettings}; #[async_trait::async_trait] @@ -54,12 +56,17 @@ impl TopUpIdentity for Identity { let block_info = block_info_from_metadata(response.metadata()?)?; let proof = response.proof_owned()?; + let context_provider = + sdk.context_provider() + .ok_or(Error::from(ContextProviderError::Config( + "Context provider not initialized".to_string(), + )))?; let (_, result) = Drive::verify_state_transition_was_executed_with_proof( &state_transition, &block_info, proof.grovedb_proof.as_slice(), - &|_| Ok(None), + &context_provider.as_contract_lookup_fn(), sdk.version(), )?; diff --git a/packages/rs-sdk/src/platform/transition/vote.rs b/packages/rs-sdk/src/platform/transition/vote.rs index b21a16c281b..3dbae7310d5 100644 --- a/packages/rs-sdk/src/platform/transition/vote.rs +++ b/packages/rs-sdk/src/platform/transition/vote.rs @@ -15,6 +15,7 @@ use dpp::state_transition::proof_result::StateTransitionProofResult; use dpp::voting::votes::resource_vote::accessors::v0::ResourceVoteGettersV0; use dpp::voting::votes::Vote; use drive::drive::Drive; +use drive_proof_verifier::{error::ContextProviderError, DataContractProvider}; use rs_dapi_client::DapiRequest; use sha2::{Digest, Sha256}; @@ -128,12 +129,17 @@ impl PutVote for Vote { let block_info = block_info_from_metadata(response.metadata()?)?; let proof = response.proof_owned()?; + let context_provider = + sdk.context_provider() + .ok_or(Error::from(ContextProviderError::Config( + "Context provider not initialized".to_string(), + )))?; let (_, result) = Drive::verify_state_transition_was_executed_with_proof( &masternode_vote_transition, &block_info, proof.grovedb_proof.as_slice(), - &|_| Ok(None), + &context_provider.as_contract_lookup_fn(), sdk.version(), )?; diff --git a/packages/rs-sdk/src/platform/transition/withdraw_from_identity.rs b/packages/rs-sdk/src/platform/transition/withdraw_from_identity.rs index 5e64ed1afb9..8e9020a5f3d 100644 --- a/packages/rs-sdk/src/platform/transition/withdraw_from_identity.rs +++ b/packages/rs-sdk/src/platform/transition/withdraw_from_identity.rs @@ -8,6 +8,8 @@ use dpp::identity::Identity; use dpp::prelude::UserFeeIncrease; use dpp::state_transition::identity_credit_withdrawal_transition::IdentityCreditWithdrawalTransition; +use drive_proof_verifier::error::ContextProviderError; +use drive_proof_verifier::DataContractProvider; use crate::platform::block_info_from_metadata::block_info_from_metadata; use crate::platform::transition::broadcast_request::BroadcastRequestForStateTransition; @@ -74,12 +76,17 @@ impl WithdrawFromIdentity for Identity { let block_info = block_info_from_metadata(response.metadata()?)?; let proof = response.proof_owned()?; + let context_provider = + sdk.context_provider() + .ok_or(Error::from(ContextProviderError::Config( + "Context provider not initialized".to_string(), + )))?; let (_, result) = Drive::verify_state_transition_was_executed_with_proof( &state_transition, &block_info, proof.grovedb_proof.as_slice(), - &|_| Ok(None), + &context_provider.as_contract_lookup_fn(), sdk.version(), )?; diff --git a/packages/rs-sdk/src/sdk.rs b/packages/rs-sdk/src/sdk.rs index 3976ee7c544..50558b2c151 100644 --- a/packages/rs-sdk/src/sdk.rs +++ b/packages/rs-sdk/src/sdk.rs @@ -212,6 +212,9 @@ impl Sdk { } } } + pub fn context_provider(&self) -> Option { + self.context_provider.as_ref().map(Arc::clone) + } /// Returns a mutable reference to the `MockDashPlatformSdk` instance. /// From 13ac443214d2f271156a1cc55b625569edc0709f Mon Sep 17 00:00:00 2001 From: Lukasz Klimek <842586+lklimek@users.noreply.github.com> Date: Tue, 2 Jul 2024 12:06:33 +0200 Subject: [PATCH 41/55] chore: cargo update --- Cargo.lock | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9c4b5a0dd9d..35ddc651d80 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1370,6 +1370,7 @@ dependencies = [ "sanitize-filename", "serde", "serde_json", + "sha2", "thiserror", "tokio", "tokio-test", @@ -5075,8 +5076,8 @@ dependencies = [ [[package]] name = "tenderdash-abci" -version = "1.0.0" -source = "git+https://github.com/dashpay/rs-tenderdash-abci#1f29dbc549dc1abe5de295e55728576b1a0c8a6b" +version = "0.14.0-dev.12" +source = "git+https://github.com/dashpay/rs-tenderdash-abci?tag=v0.14.0-dev.12#17e57f509c2bb7015042d69976bd1f056fef923d" dependencies = [ "bytes", "futures", @@ -5097,8 +5098,8 @@ dependencies = [ [[package]] name = "tenderdash-proto" -version = "1.0.0" -source = "git+https://github.com/dashpay/rs-tenderdash-abci#1f29dbc549dc1abe5de295e55728576b1a0c8a6b" +version = "0.14.0-dev.12" +source = "git+https://github.com/dashpay/rs-tenderdash-abci?tag=v0.14.0-dev.12#17e57f509c2bb7015042d69976bd1f056fef923d" dependencies = [ "bytes", "chrono", @@ -5117,8 +5118,8 @@ dependencies = [ [[package]] name = "tenderdash-proto-compiler" -version = "1.0.0" -source = "git+https://github.com/dashpay/rs-tenderdash-abci#1f29dbc549dc1abe5de295e55728576b1a0c8a6b" +version = "0.14.0-dev.12" +source = "git+https://github.com/dashpay/rs-tenderdash-abci?tag=v0.14.0-dev.12#17e57f509c2bb7015042d69976bd1f056fef923d" dependencies = [ "fs_extra", "prost-build 0.12.6", From 7beda50bec9e1e4ba205a68e0f57f4fecba0ec6c Mon Sep 17 00:00:00 2001 From: Lukasz Klimek <842586+lklimek@users.noreply.github.com> Date: Tue, 2 Jul 2024 14:24:44 +0200 Subject: [PATCH 42/55] chore: self review --- packages/rs-sdk/tests/.env.example | 3 ++ packages/rs-sdk/tests/fetch/common.rs | 3 ++ packages/rs-sdk/tests/fetch/config.rs | 23 +++++++++- .../rs-sdk/tests/fetch/contested_resource.rs | 43 ++++++++++--------- .../contested_resource_identity_votes.rs | 24 ++++------- .../fetch/contested_resource_vote_state.rs | 23 ++++++---- .../tests/fetch/contested_resource_voters.rs | 13 ++++-- 7 files changed, 83 insertions(+), 49 deletions(-) diff --git a/packages/rs-sdk/tests/.env.example b/packages/rs-sdk/tests/.env.example index 23b48e84df8..1a9222032eb 100644 --- a/packages/rs-sdk/tests/.env.example +++ b/packages/rs-sdk/tests/.env.example @@ -4,6 +4,9 @@ DASH_SDK_PLATFORM_HOST="127.0.0.1" DASH_SDK_PLATFORM_PORT=2443 DASH_SDK_PLATFORM_SSL=false +# ProTxHash of masternode that has at least 1 vote casted for DPNS name `testname` +DASH_SDK_MASTERNODE_OWNER_PRO_REG_TX_HASH="6ac88f64622d9bc0cb79ad0f69657aa9488b213157d20ae0ca371fa5f04fb222" + DASH_SDK_CORE_PORT=20002 DASH_SDK_CORE_USER="someuser" DASH_SDK_CORE_PASSWORD="verysecretpassword" diff --git a/packages/rs-sdk/tests/fetch/common.rs b/packages/rs-sdk/tests/fetch/common.rs index 12bfeb77617..edbe4d2fc77 100644 --- a/packages/rs-sdk/tests/fetch/common.rs +++ b/packages/rs-sdk/tests/fetch/common.rs @@ -1,5 +1,8 @@ use dpp::{data_contract::DataContractFactory, prelude::Identifier}; +/// Test DPNS name for testing of the Sdk; at least 3 identities should request this name to be reserved +pub(crate) const TEST_DPNS_NAME: &str = "testname"; + /// Create a mock document type for testing of mock API pub fn mock_document_type() -> dpp::data_contract::document_type::DocumentType { use dpp::{ diff --git a/packages/rs-sdk/tests/fetch/config.rs b/packages/rs-sdk/tests/fetch/config.rs index 839f3dec9d2..4757c31d607 100644 --- a/packages/rs-sdk/tests/fetch/config.rs +++ b/packages/rs-sdk/tests/fetch/config.rs @@ -3,7 +3,10 @@ //! This module contains [Config] struct that can be used to configure dash-platform-sdk. //! It's mainly used for testing. -use dpp::prelude::Identifier; +use dpp::{ + dashcore::{hashes::Hash, ProTxHash}, + prelude::Identifier, +}; use rs_dapi_client::AddressList; use serde::Deserialize; use std::{path::PathBuf, str::FromStr}; @@ -68,6 +71,9 @@ pub struct Config { /// in [`existing_data_contract_id`](Config::existing_data_contract_id). #[serde(default = "Config::default_document_id")] pub existing_document_id: Identifier, + // Hex-encoded ProTxHash of the existing HP masternode + #[serde(default)] + pub masternode_owner_pro_reg_tx_hash: String, } impl Config { @@ -231,6 +237,21 @@ impl Config { .join("tests") .join("vectors") } + + /// Return ProTxHash of an existing evo node, or None if not set + pub fn existing_protxhash(&self) -> Result { + hex::decode(&self.masternode_owner_pro_reg_tx_hash) + .map_err(|e| e.to_string()) + .and_then(|b| ProTxHash::from_slice(&b).map_err(|e| e.to_string())) + .map_err(|e| { + format!( + "Invalid {}MASTERNODE_OWNER_PRO_REG_TX_HASH {}: {}", + Self::CONFIG_PREFIX, + self.masternode_owner_pro_reg_tx_hash, + e + ) + }) + } } impl Default for Config { diff --git a/packages/rs-sdk/tests/fetch/contested_resource.rs b/packages/rs-sdk/tests/fetch/contested_resource.rs index a391b7b2a50..330ea04a9c0 100644 --- a/packages/rs-sdk/tests/fetch/contested_resource.rs +++ b/packages/rs-sdk/tests/fetch/contested_resource.rs @@ -1,6 +1,9 @@ //! Tests of ContestedResource object -use crate::fetch::{common::setup_logs, config::Config}; +use crate::fetch::{ + common::{setup_logs, TEST_DPNS_NAME}, + config::Config, +}; use core::panic; use dash_sdk::platform::FetchMany; use dpp::{ @@ -19,8 +22,6 @@ use drive::query::{ use drive_proof_verifier::types::ContestedResource; use std::panic::catch_unwind; -pub(crate) const INDEX_VALUE: &str = "dada"; - /// Test that we can fetch contested resources /// /// ## Preconditions @@ -238,19 +239,19 @@ async fn contested_resources_fields() { struct TestCase { name: &'static str, query_mut_fn: MutFn, - expect: Result<&'static str, &'static str>, + expect: Result, } let test_cases: Vec = vec![ TestCase { name: "unmodified base query is Ok", query_mut_fn: |_q| {}, - expect: Ok("ContestedResources([Value(Text("), + expect: Ok("ContestedResources([Value(Text(".into()), }, TestCase { name: "index value empty string is Ok", query_mut_fn: |q| q.start_index_values = vec![Value::Text("".to_string())], - expect: Ok(""), + expect: Ok("".into()), }, TestCase { name: "non existing document type returns InvalidArgument", @@ -281,19 +282,19 @@ async fn contested_resources_fields() { TestCase { name: "start_index_values empty vec returns top-level keys", query_mut_fn: |q| q.start_index_values = vec![], - expect: Ok(r#"ContestedResources([Value(Text("dash"))])"#), + expect: Ok(r#"ContestedResources([Value(Text("dash"))])"#.into()), }, TestCase { name: "start_index_values empty string returns zero results", query_mut_fn: |q| q.start_index_values = vec![Value::Text("".to_string())], - expect: Ok(r#"ContestedResources([])"#), + expect: Ok(r#"ContestedResources([])"#.into()), }, TestCase { name: "start_index_values with two values returns error", query_mut_fn: |q| { q.start_index_values = vec![ Value::Text("dash".to_string()), - Value::Text("dada".to_string()), + Value::Text(TEST_DPNS_NAME.to_string()), ] }, expect: Err("incorrect index values error: too many start index values were provided, since no end index values were provided, the start index values must be less than the amount of properties in the contested index"), @@ -302,15 +303,15 @@ async fn contested_resources_fields() { name: "end_index_values one value with empty start_index_values returns 'dash'", query_mut_fn: |q| { q.start_index_values = vec![]; - q.end_index_values = vec![Value::Text("dada".to_string())]; + q.end_index_values = vec![Value::Text(TEST_DPNS_NAME.to_string())]; }, - expect:Ok(r#"ContestedResources([Value(Text("dash"))])"#), + expect:Ok(r#"ContestedResources([Value(Text("dash"))])"#.into()), }, TestCase { name: "end_index_values two values (1 nx) with empty start_index_values returns error", query_mut_fn: |q| { q.start_index_values = vec![]; - q.end_index_values = vec![Value::Text("dada".to_string()), Value::Text("non existing".to_string())]; + q.end_index_values = vec![Value::Text(TEST_DPNS_NAME.to_string()), Value::Text("non existing".to_string())]; }, expect:Err("too many end index values were provided"), }, @@ -320,7 +321,7 @@ async fn contested_resources_fields() { q.start_index_values = vec![]; q.end_index_values = vec![Value::Text("aaa non existing".to_string())]; }, - expect:Ok(r#"ContestedResources([])"#), + expect:Ok(r#"ContestedResources([])"#.into()), }, TestCase { name: "end_index_values with 1 nx value 'zzz*' and empty start_index_values returns zero objects", @@ -328,7 +329,7 @@ async fn contested_resources_fields() { q.start_index_values = vec![]; q.end_index_values = vec![Value::Text("zzz non existing".to_string())]; }, - expect:Ok(r#"ContestedResources([])"#), + expect:Ok(r#"ContestedResources([])"#.into()), }, TestCase { // fails due to PLAN-662 @@ -336,7 +337,7 @@ async fn contested_resources_fields() { query_mut_fn: |q| { q.start_index_values = vec![ Value::Text("dash".to_string()), - Value::Text("dada".to_string()), + Value::Text(TEST_DPNS_NAME.to_string()), Value::Text("eee".to_string()), ] }, @@ -355,7 +356,7 @@ async fn contested_resources_fields() { q.start_index_values = vec![]; q.end_index_values = vec![Value::Text("zzz non existing".to_string())] }, - expect:Ok("ContestedResources([])"), + expect:Ok("ContestedResources([])".into()), }, TestCase { name: "wrong type of end_index_values should return InvalidArgument", @@ -376,10 +377,10 @@ async fn contested_resources_fields() { name: "exact match query returns one object PLAN-656", query_mut_fn: |q| { q.start_index_values = vec![Value::Text("dash".to_string())]; - q.start_at_value = Some((Value::Text("dada".to_string()), true)); + q.start_at_value = Some((Value::Text(TEST_DPNS_NAME.to_string()), true)); q.limit = Some(1); }, - expect: Ok(r#"ContestedResources([Value(Text("dada"))])"#), + expect: Ok(format!(r#"ContestedResources([Value(Text({}))])"#, TEST_DPNS_NAME)), } // start index + start at + limit 1 @@ -449,7 +450,7 @@ async fn contested_resources_fields() { match test_case.expect { Ok(expected) if result.is_ok() => { let result_string = format!("{:?}", result.as_ref().expect("result")); - if !result_string.contains(expected) { + if !result_string.contains(&expected) { failures.push(( test_case.name, format!("EXPECTED: {} GOT: {:?}\n", expected, result), @@ -535,7 +536,7 @@ pub async fn check_mn_voting_prerequisities(cfg: &Config) -> Result<(), Vec Result<(), Vec `s - Fetch system contract` -> `n - Fetch DPNS contract` -> `q - Back to Contracts ` /// * press ENTER to enter the fetched contract, then select `domain` -> `c - Query Contested Resources` -/// * Select `string dada`, use `v - Vote`, select some identity. +/// * Select one of displayed names, use `v - Vote`, select some identity. /// /// Now, vote should be casted and you can run this test. /// @@ -83,13 +80,10 @@ async fn contested_resource_identity_votes_ok() { let cfg = Config::new(); let sdk = cfg.setup_api("contested_resource_identity_votes_ok").await; - // Given some existing identity ID, that is, proTxHash of some Validator - - // TODO: Fetch proTxHash from the network instead of hardcoding; it's not so trivial as it must support our mocking - // mechanisms - let protx_hex = "53fe73c78179e69a2e9dbe6c04ca0b6d4da596e5e8df0b5dc41a121bf5bda5a3"; - let protx = ProTxHash::from_slice(&hex::decode(protx_hex).expect("ProTxHash from hex")) - .expect("ProTxHash from slice"); + // Given some existing proTxHash of some Validator that alreday voted + let protx = cfg.existing_protxhash().expect( + "contested_resource_identity_votes_ok requires existing_protxhash to be set in config", + ); // When I query for votes given by this identity let votes = ResourceVote::fetch_many(&sdk, protx) diff --git a/packages/rs-sdk/tests/fetch/contested_resource_vote_state.rs b/packages/rs-sdk/tests/fetch/contested_resource_vote_state.rs index a2666a2f113..9c6d339023b 100644 --- a/packages/rs-sdk/tests/fetch/contested_resource_vote_state.rs +++ b/packages/rs-sdk/tests/fetch/contested_resource_vote_state.rs @@ -1,6 +1,8 @@ //! Tests for SDK requests that return one or more [Contender] objects. use crate::fetch::{ - common::setup_logs, config::Config, contested_resource::check_mn_voting_prerequisities, + common::{setup_logs, TEST_DPNS_NAME}, + config::Config, + contested_resource::check_mn_voting_prerequisities, }; use dash_sdk::platform::{Fetch, FetchMany}; use dpp::{ @@ -117,7 +119,7 @@ async fn contested_resource_vote_states_nx_contract() { /// /// ## Preconditions /// -/// 1. There must be at least one contender for name "dash" and value "dada". +/// 1. There must be at least one contender for name "dash" and value "[TEST_DPNS_NAME]". #[tokio::test(flavor = "multi_thread", worker_threads = 1)] async fn contested_resource_vote_states_ok() { setup_logs(); @@ -126,7 +128,7 @@ async fn contested_resource_vote_states_ok() { let sdk = cfg.setup_api("contested_resource_vote_states_ok").await; // Given some existing data contract and existing label let data_contract_id = cfg.existing_data_contract_id; - let label = Value::Text(convert_to_homograph_safe_chars("dada")); + let label = Value::Text(convert_to_homograph_safe_chars(TEST_DPNS_NAME)); let document_type_name = "domain".to_string(); let data_contract = DataContract::fetch_by_identifier(&sdk, data_contract_id) @@ -176,7 +178,7 @@ async fn contested_resource_vote_states_ok() { assert!(seen.insert(doc.id()), "duplicate contender"); let properties = doc.properties(); assert_eq!(properties["parentDomainName"], Value::Text("dash".into())); - assert_eq!(properties["label"], Value::Text("dada".into())); + assert_eq!(properties["label"], Value::Text(TEST_DPNS_NAME.into())); tracing::debug!(?properties, "document properties"); } } @@ -185,7 +187,7 @@ async fn contested_resource_vote_states_ok() { /// /// ## Preconditions /// -/// 1. There must be at least 3 condenders for name "dash" and value "dada". +/// 1. There must be at least 3 condenders for name "dash" and value [TEST_DPNS_NAME]. /// #[tokio::test(flavor = "multi_thread", worker_threads = 1)] #[allow(non_snake_case)] @@ -203,7 +205,7 @@ async fn contested_resource_vote_states_with_limit_PLAN_674() { // Given more contenders for some `label` than the limit let data_contract_id = cfg.existing_data_contract_id; let limit: u16 = 2; - let label = Value::Text("dada".into()); + let label = Value::Text(TEST_DPNS_NAME.into()); // ensure we have enough contenders let query_all = ContestedDocumentVotePollDriveQuery { @@ -341,7 +343,7 @@ async fn contested_resource_vote_states_fields() { query_mut_fn: |q| { q.vote_poll.index_values = vec![ Value::Text("dash".to_string()), - Value::Text("dada".to_string()), + Value::Text(TEST_DPNS_NAME.to_string()), ] }, expect: Ok("contenders: {Identifier("), @@ -351,7 +353,7 @@ async fn contested_resource_vote_states_fields() { query_mut_fn: |q| { q.vote_poll.index_values = vec![ Value::Text("dash".to_string()), - Value::Text("dada".to_string()), + Value::Text(TEST_DPNS_NAME.to_string()), Value::Text("eee".to_string()), ] }, @@ -402,7 +404,10 @@ async fn contested_resource_vote_states_fields() { start_at: None, vote_poll: ContestedDocumentResourceVotePoll { index_name: "parentNameAndLabel".to_string(), - index_values: vec![Value::Text("dash".into()), Value::Text("dada".into())], + index_values: vec![ + Value::Text("dash".into()), + Value::Text(TEST_DPNS_NAME.into()), + ], document_type_name: cfg.existing_document_type_name.clone(), contract_id: cfg.existing_data_contract_id, }, diff --git a/packages/rs-sdk/tests/fetch/contested_resource_voters.rs b/packages/rs-sdk/tests/fetch/contested_resource_voters.rs index bb153d1057f..b7b374f9256 100644 --- a/packages/rs-sdk/tests/fetch/contested_resource_voters.rs +++ b/packages/rs-sdk/tests/fetch/contested_resource_voters.rs @@ -14,7 +14,10 @@ use drive::query::{ }; use drive_proof_verifier::types::Voter; -use crate::fetch::{common::setup_logs, config::Config}; +use crate::fetch::{ + common::{setup_logs, TEST_DPNS_NAME}, + config::Config, +}; /// When we request votes for a non-existing identity, we should get no votes. #[cfg_attr( @@ -59,7 +62,7 @@ async fn test_contested_resource_voters_for_identity_not_found() { /// /// ## Preconditions /// -/// 1. Votes exist for the given contestant. +/// 1. Votes exist for DPNS name [TEST_DPNS_NAME]. #[tokio::test(flavor = "multi_thread", worker_threads = 1)] async fn contested_resource_voters_for_existing_contestant() { setup_logs(); @@ -69,8 +72,12 @@ async fn contested_resource_voters_for_existing_contestant() { .setup_api("contested_resource_voters_for_existing_contestant") .await; + super::contested_resource::check_mn_voting_prerequisities(&cfg) + .await + .expect("prerequisites"); + let index_name = "parentNameAndLabel".to_string(); - let index_value = Value::Text("dada".to_string()); + let index_value = Value::Text(TEST_DPNS_NAME.to_string()); // fetch contestant let contestants_query = ContestedDocumentVotePollDriveQuery { From 7e7a96869f7a4a21925988e6043670c6662e4260 Mon Sep 17 00:00:00 2001 From: Lukasz Klimek <842586+lklimek@users.noreply.github.com> Date: Tue, 2 Jul 2024 14:50:00 +0200 Subject: [PATCH 43/55] test(sdk): fix vote_polls_by_ts_limit test non-determinism --- .../rs-sdk/tests/fetch/contested_resource_polls_by_ts.rs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/packages/rs-sdk/tests/fetch/contested_resource_polls_by_ts.rs b/packages/rs-sdk/tests/fetch/contested_resource_polls_by_ts.rs index 3cb4006678e..07cc4992dce 100644 --- a/packages/rs-sdk/tests/fetch/contested_resource_polls_by_ts.rs +++ b/packages/rs-sdk/tests/fetch/contested_resource_polls_by_ts.rs @@ -1,7 +1,7 @@ //! Test VotePollsByEndDateDriveQuery use crate::fetch::{common::setup_logs, config::Config}; -use chrono::Days; +use chrono::{DateTime, Days, TimeZone, Utc}; use dash_sdk::platform::FetchMany; use dpp::{identity::TimestampMillis, voting::vote_polls::VotePoll}; use drive::query::VotePollsByEndDateDriveQuery; @@ -134,10 +134,7 @@ async fn vote_polls_by_ts_limit() { const LIMIT: usize = 2; const LIMIT_ALL: usize = 100; - let _test_start_time: TimestampMillis = chrono::Utc::now().timestamp_millis() as u64; - let end_time = chrono::Utc::now() - .checked_add_days(Days::new(30)) - .expect("30 days in future"); + let end_time: DateTime = Utc.with_ymd_and_hms(2035, 12, 24, 13, 59, 30).unwrap(); let query_all = VotePollsByEndDateDriveQuery { limit: Some(LIMIT_ALL as u16), From 3bc081c89e7d4a7be65acbdfcb92a76a1fc8720e Mon Sep 17 00:00:00 2001 From: Lukasz Klimek <842586+lklimek@users.noreply.github.com> Date: Tue, 2 Jul 2024 14:56:54 +0200 Subject: [PATCH 44/55] chore(sdk): support passing --include-ignored and similar flags --- packages/rs-sdk/scripts/generate_test_vectors.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/rs-sdk/scripts/generate_test_vectors.sh b/packages/rs-sdk/scripts/generate_test_vectors.sh index d02f193687e..3e0a321ef7b 100755 --- a/packages/rs-sdk/scripts/generate_test_vectors.sh +++ b/packages/rs-sdk/scripts/generate_test_vectors.sh @@ -19,10 +19,10 @@ CARGO_DIR="$(realpath "$(dirname "$0")/..")" pushd "$CARGO_DIR" - +set -ex cargo test -p dash-sdk \ --no-default-features \ --features generate-test-vectors \ - "$1" + "$@" popd From 257db65eadc7dabc4ea12de59adf7ec072b9b6a1 Mon Sep 17 00:00:00 2001 From: Lukasz Klimek <842586+lklimek@users.noreply.github.com> Date: Tue, 2 Jul 2024 15:07:41 +0200 Subject: [PATCH 45/55] chore: minor fix in rs-sdk fetch config --- packages/rs-sdk/tests/fetch/config.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/packages/rs-sdk/tests/fetch/config.rs b/packages/rs-sdk/tests/fetch/config.rs index 4757c31d607..ace89d130f3 100644 --- a/packages/rs-sdk/tests/fetch/config.rs +++ b/packages/rs-sdk/tests/fetch/config.rs @@ -186,9 +186,12 @@ impl Config { if let Err(err) = std::fs::remove_dir_all(&dump_dir) { tracing::warn!(?err, ?dump_dir, "failed to remove dump dir"); } - std::fs::create_dir_all(&dump_dir).expect("create dump dir"); + std::fs::create_dir_all(&dump_dir) + .expect(format!("create dump dir {}", dump_dir.display()).as_str()); // ensure dump dir is committed to git - std::fs::write(dump_dir.join(".gitkeep"), "").expect("create .gitkeep file") + let gitkeep = dump_dir.join(".gitkeep"); + std::fs::write(&gitkeep, "") + .expect(format!("create {} file", gitkeep.display()).as_str()); } builder.with_dump_dir(&dump_dir) From 37a627ad96b29e4cd100b3cc47a6a44d88b156a3 Mon Sep 17 00:00:00 2001 From: Lukasz Klimek <842586+lklimek@users.noreply.github.com> Date: Tue, 2 Jul 2024 18:51:37 +0200 Subject: [PATCH 46/55] test(sdk): refactor contested_rss_vote_state_fields to use test_case macro --- Cargo.lock | 38 ++- packages/rs-sdk/Cargo.toml | 1 + packages/rs-sdk/tests/fetch/config.rs | 6 +- .../fetch/contested_resource_vote_state.rs | 277 +++++------------- 4 files changed, 115 insertions(+), 207 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 35ddc651d80..e1724b3f6dc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1371,6 +1371,7 @@ dependencies = [ "serde", "serde_json", "sha2", + "test-case 3.3.1", "thiserror", "tokio", "tokio-test", @@ -1632,7 +1633,7 @@ dependencies = [ "serde_repr", "sha2", "strum 0.25.0", - "test-case", + "test-case 2.2.2", "thiserror", "tokio", ] @@ -5152,7 +5153,28 @@ version = "2.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "21d6cf5a7dffb3f9dceec8e6b8ca528d9bd71d36c9f074defb548ce161f598c0" dependencies = [ - "test-case-macros", + "test-case-macros 2.2.2", +] + +[[package]] +name = "test-case" +version = "3.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb2550dd13afcd286853192af8601920d959b14c401fcece38071d53bf0768a8" +dependencies = [ + "test-case-macros 3.3.1", +] + +[[package]] +name = "test-case-core" +version = "3.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adcb7fd841cd518e279be3d5a3eb0636409487998a4aff22f3de87b81e88384f" +dependencies = [ + "cfg-if", + "proc-macro2", + "quote", + "syn 2.0.68", ] [[package]] @@ -5168,6 +5190,18 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "test-case-macros" +version = "3.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c89e72a01ed4c579669add59014b9a524d609c0c88c6a585ce37485879f6ffb" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.68", + "test-case-core", +] + [[package]] name = "textwrap" version = "0.11.0" diff --git a/packages/rs-sdk/Cargo.toml b/packages/rs-sdk/Cargo.toml index 87550d31a3c..b37f5848a70 100644 --- a/packages/rs-sdk/Cargo.toml +++ b/packages/rs-sdk/Cargo.toml @@ -53,6 +53,7 @@ tokio-test = { version = "0.4.4" } clap = { version = "4.5.4", features = ["derive"] } sanitize-filename = { version = "0.5.0" } chrono = { version = "0.4.38" } +test-case = { version = "3.3.1" } [features] default = ["mocks", "offline-testing"] diff --git a/packages/rs-sdk/tests/fetch/config.rs b/packages/rs-sdk/tests/fetch/config.rs index ace89d130f3..27738cb552a 100644 --- a/packages/rs-sdk/tests/fetch/config.rs +++ b/packages/rs-sdk/tests/fetch/config.rs @@ -153,7 +153,11 @@ impl Config { pub async fn setup_api(&self, namespace: &str) -> dash_sdk::Sdk { let dump_dir = match namespace.is_empty() { true => self.dump_dir.clone(), - false => self.dump_dir.join(sanitize_filename::sanitize(namespace)), + false => { + // looks like spaces are not replaced by sanitize_filename, and we don't want them as they are confusing + let namespace = namespace.replace(' ', "_"); + self.dump_dir.join(sanitize_filename::sanitize(namespace)) + } }; if dump_dir.is_relative() { diff --git a/packages/rs-sdk/tests/fetch/contested_resource_vote_state.rs b/packages/rs-sdk/tests/fetch/contested_resource_vote_state.rs index 9c6d339023b..cf8576dc2be 100644 --- a/packages/rs-sdk/tests/fetch/contested_resource_vote_state.rs +++ b/packages/rs-sdk/tests/fetch/contested_resource_vote_state.rs @@ -21,6 +21,8 @@ use dpp::{ use drive::query::vote_poll_vote_state_query::{ ContestedDocumentVotePollDriveQuery, ContestedDocumentVotePollDriveQueryResultType, }; +use sha2::Digest; +use test_case::test_case; /// Ensure we get proof of non-existence when querying for a non-existing index value. #[tokio::test(flavor = "multi_thread", worker_threads = 1)] @@ -256,143 +258,50 @@ async fn contested_resource_vote_states_with_limit_PLAN_674() { ); } -/// Check various queries for [ContenderWithSerializedDocument] that contain invalid field values -/// -/// ## Preconditions -/// -/// None +type MutFn = fn(&mut ContestedDocumentVotePollDriveQuery); + +#[test_case(|q| q.limit = Some(0), Err("limit 0 out of bounds of [1, 100]"); "limit 0")] +#[test_case(|q| q.limit = Some(std::u16::MAX), Err("limit 65535 out of bounds of [1, 100]"); "limit std::u16::MAX")] +#[test_case(|q| q.offset = Some(1), Err("ContestedDocumentVotePollDriveQuery.offset field is internal and must be set to None"); "offset not None")] +#[test_case(|q| q.start_at = Some(([0x11; 32], true)), Ok("Contenders { contenders: {Identifier("); "start_at does not exist should return next contenders")] +#[test_case(|q| q.start_at = Some(([0xff; 32], true)), Ok("Contenders { contenders: {}, abstain_vote_tally: None, lock_vote_tally: None }"); "start_at 0xff;32 should return zero contenders")] +#[test_case(|q| q.vote_poll.document_type_name = "nx doctype".to_string(), Err(r#"code: InvalidArgument, message: "document type nx doctype not found"#); "non existing document type returns InvalidArgument")] +#[test_case(|q| q.vote_poll.index_name = "nx index".to_string(), Err(r#"code: InvalidArgument, message: "index with name nx index is not the contested index"#); "non existing index returns InvalidArgument")] +#[test_case(|q| q.vote_poll.index_name = "dashIdentityId".to_string(), Err(r#"code: InvalidArgument, message: "index with name dashIdentityId is not the contested index"#); "existing non-contested index returns InvalidArgument")] +#[test_case(|q| q.vote_poll.index_values = vec![], Err("query uses index parentNameAndLabel, this index has 2 properties, but the query provided 0 index values instead"); "index_values empty vec returns error")] +#[test_case(|q| q.vote_poll.index_values = vec![Value::Text("".to_string())], Err("query uses index parentNameAndLabel, this index has 2 properties, but the query provided 1 index values instead"); "index_values empty string returns error")] +#[test_case(|q| q.vote_poll.index_values = vec![Value::Text("dash".to_string())], Err("query uses index parentNameAndLabel, this index has 2 properties, but the query provided 1 index values instead"); "index_values with one value returns error")] +#[test_case(|q| { + q.vote_poll.index_values = vec![ + Value::Text("dash".to_string()), + Value::Text(TEST_DPNS_NAME.to_string()), + ] +}, Ok("contenders: {Identifier("); "index_values with two values returns contenders")] +#[test_case(|q| { + q.vote_poll.index_values = vec![ + Value::Text("dash".to_string()), + Value::Text(TEST_DPNS_NAME.to_string()), + Value::Text("eee".to_string()), + ] +}, Err("query uses index parentNameAndLabel, this index has 2 properties, but the query provided 3 index values instead"); "index_values too many items should return error")] +#[test_case(|q| q.vote_poll.contract_id = Identifier::from([0xff; 32]), Err(r#"InvalidArgument, message: "contract not found error"#); "invalid contract id should cause InvalidArgument error")] +#[test_case(|q| q.allow_include_locked_and_abstaining_vote_tally = false, Ok(r#"contenders: {Identifier(IdentifierBytes32"#); "allow_include_locked_and_abstaining_vote_tally false should return some contenders")] +#[test_case(|q| { + q.result_type = ContestedDocumentVotePollDriveQueryResultType::Documents +}, Ok(r#"]), vote_tally: None })"#); "result_type Documents")] +#[test_case(|q| { + q.result_type = ContestedDocumentVotePollDriveQueryResultType::DocumentsAndVoteTally +}, Ok(r#"]), vote_tally: Some("#); "result_type DocumentsAndVoteTally")] +#[test_case(|q| { + q.result_type = ContestedDocumentVotePollDriveQueryResultType::VoteTally +}, Ok(r#"serialized_document: None, vote_tally: Some"#); "result_type VoteTally")] #[tokio::test(flavor = "multi_thread", worker_threads = 1)] -async fn contested_resource_vote_states_fields() { +async fn contested_rss_vote_state_fields( + query_mut_fn: MutFn, + expect: Result<&'static str, &'static str>, +) -> Result<(), String> { setup_logs(); - type MutFn = fn(&mut ContestedDocumentVotePollDriveQuery); - struct TestCase { - name: &'static str, - query_mut_fn: MutFn, - expect: Result<&'static str, &'static str>, - } - - let test_cases: Vec = vec![ - TestCase { - name: "limit 0", - query_mut_fn: |q| q.limit = Some(0), - expect:Err("limit 0 out of bounds of [1, 100]"), - }, - TestCase { - name: "limit std::u16::MAX", - query_mut_fn: |q| q.limit = Some(std::u16::MAX), - expect: Err("limit 65535 out of bounds of [1, 100]"), - }, - TestCase { - name: "offset not None", - query_mut_fn: |q| q.offset = Some(1), - expect: Err( - "ContestedDocumentVotePollDriveQuery.offset field is internal and must be set to None", - ), - }, - TestCase { - // TODO: pagination test - name: "start_at does not exist should return next contenders", - query_mut_fn: |q| q.start_at = Some(([0x11; 32], true)), - expect: Ok("Contenders { contenders: {Identifier("), - }, - TestCase { - name: "start_at 0xff;32 should return zero contenders", - query_mut_fn: |q| q.start_at = Some(([0xff; 32], true)), - expect: Ok("Contenders { contenders: {}, abstain_vote_tally: None, lock_vote_tally: None }"), - }, - TestCase { - name: "non existing document type returns InvalidArgument", - query_mut_fn: |q| q.vote_poll.document_type_name = "nx doctype".to_string(), - expect: Err(r#"code: InvalidArgument, message: "document type nx doctype not found"#), - }, - TestCase { - name: "non existing index returns InvalidArgument", - query_mut_fn: |q| q.vote_poll.index_name = "nx index".to_string(), - expect: Err( - r#"code: InvalidArgument, message: "index with name nx index is not the contested index"#, - ), - }, - TestCase { - name: "existing non-contested index returns InvalidArgument", - query_mut_fn: |q| q.vote_poll.index_name = "dashIdentityId".to_string(), - expect: Err( - r#"code: InvalidArgument, message: "index with name dashIdentityId is not the contested index"#, - ), - }, - TestCase { - // todo maybe this should fail? or return everything? - name: "index_values empty vec returns error", - query_mut_fn: |q| q.vote_poll.index_values = vec![], - expect: Err( - "query uses index parentNameAndLabel, this index has 2 properties, but the query provided 0 index values instead", - ), - }, - TestCase { - name: "index_values empty string returns error", - query_mut_fn: |q| q.vote_poll.index_values = vec![Value::Text("".to_string())], - expect: Err("query uses index parentNameAndLabel, this index has 2 properties, but the query provided 1 index values instead"), - }, - TestCase { - name: "index_values with one value returns error", - query_mut_fn: |q| q.vote_poll.index_values = vec![Value::Text("dash".to_string())], - expect: Err("query uses index parentNameAndLabel, this index has 2 properties, but the query provided 1 index values instead"), - }, - TestCase { - name: "index_values with two values returns contenders", - query_mut_fn: |q| { - q.vote_poll.index_values = vec![ - Value::Text("dash".to_string()), - Value::Text(TEST_DPNS_NAME.to_string()), - ] - }, - expect: Ok("contenders: {Identifier("), - }, - TestCase { - name: "index_values too many items should return error", - query_mut_fn: |q| { - q.vote_poll.index_values = vec![ - Value::Text("dash".to_string()), - Value::Text(TEST_DPNS_NAME.to_string()), - Value::Text("eee".to_string()), - ] - }, - expect:Err("query uses index parentNameAndLabel, this index has 2 properties, but the query provided 3 index values instead"), - }, - TestCase { - name: "invalid contract id should cause InvalidArgument error", - query_mut_fn: |q| q.vote_poll.contract_id = Identifier::from([0xff; 32]), - expect: Err(r#"InvalidArgument, message: "contract not found error"#), - }, - TestCase { - name: - "allow_include_locked_and_abstaining_vote_tally false should return some contenders", - query_mut_fn: |q| q.allow_include_locked_and_abstaining_vote_tally = false, - expect: Ok(r#"contenders: {Identifier(IdentifierBytes32"#), - }, - TestCase { - name: "result_type Documents", - query_mut_fn: |q| { - q.result_type = ContestedDocumentVotePollDriveQueryResultType::Documents - }, - expect: Ok(r#"]), vote_tally: None })"#), - }, - TestCase { - name: "result_type DocumentsAndVoteTally", - query_mut_fn: |q| { - q.result_type = ContestedDocumentVotePollDriveQueryResultType::DocumentsAndVoteTally - }, - expect: Ok(r#"]), vote_tally: Some("#), - }, - TestCase { - name: "result_type VoteTally", - query_mut_fn: |q| { - q.result_type = ContestedDocumentVotePollDriveQueryResultType::VoteTally - }, - expect: Ok(r#"serialized_document: None, vote_tally: Some"#), - }, - ]; - let cfg = Config::new(); check_mn_voting_prerequisities(&cfg) .await @@ -416,8 +325,9 @@ async fn contested_resource_vote_states_fields() { }; // check if the base query works + // TODO: maybe move to another test let base_query_sdk = cfg - .setup_api("contested_resource_vote_states_fields_base_query") + .setup_api("contested_rss_vote_state_fields_base_query") .await; let result = ContenderWithSerializedDocument::fetch_many(&base_query_sdk, base_query.clone()).await; @@ -426,78 +336,37 @@ async fn contested_resource_vote_states_fields() { "base query should return some results" ); - let mut failures: Vec<(&'static str, String)> = Default::default(); + // we need some unique identifier for test vector - for test_case in test_cases { - tracing::debug!( - test_case = test_case.name, - "Running test case: {}", - test_case.name - ); - // create new sdk to ensure that test cases don't interfere with each other - let sdk = cfg - .setup_api(&format!( - "contested_resources_vote_states_fields_{}", - test_case.name - )) - .await; - - let mut query = base_query.clone(); - (test_case.query_mut_fn)(&mut query); - - let result = ContenderWithSerializedDocument::fetch_many(&sdk, query).await; - tracing::debug!( - test_case = test_case.name, - ?result, - "Result of test case {}", - test_case.name - ); - match test_case.expect { - Ok(expected) if result.is_ok() => { - let result_string = format!("{:?}", result.as_ref().expect("result")); - if !result_string.contains(expected) { - failures.push(( - test_case.name, - format!("expected: {:#?}\ngot: {:?}\n", expected, result), - )); - } - } - Err(expected) if result.is_err() => { - let result = result.expect_err("error"); - if !result.to_string().contains(expected) { - failures.push(( - test_case.name, - format!("expected: {:#?}\ngot {:?}\n", expected, result), - )); - } - } - expected => { - failures.push(( - test_case.name, - format!("expected: {:#?}\ngot: {:?}\n", expected, result), - )); + let mut hasher = sha2::Sha256::new(); + hasher.update(format!("{:?}", &expect).as_bytes()); + let ns = format!("contested_rss_vote_state_fields_{:x}", hasher.finalize()); + + let sdk = cfg.setup_api(&ns).await; + + let mut query = base_query.clone(); + query_mut_fn(&mut query); + tracing::debug!(?query, ?ns, "Executing test case query"); + + let result = ContenderWithSerializedDocument::fetch_many(&sdk, query).await; + tracing::debug!(?result, "Result of test case"); + match expect { + Ok(expected) if result.is_ok() => { + let result_string = format!("{:?}", result.as_ref().expect("result")); + if !result_string.contains(expected) { + Err(format!("expected: {:#?}\ngot: {:?}\n", expected, result)) + } else { + Ok(()) } } - } - if !failures.is_empty() { - for failure in &failures { - tracing::error!(?failure, "Failed: {}", failure.0); + Err(expected) if result.is_err() => { + let result = result.expect_err("error"); + if !result.to_string().contains(expected) { + Err(format!("expected: {:#?}\ngot {:?}\n", expected, result)) + } else { + Ok(()) + } } - let failed_cases = failures - .iter() - .map(|(name, _)| name.to_string()) - .collect::>() - .join("\n* "); - - panic!( - "{} test cases failed:\n* {}\n\n{}\n", - failures.len(), - failed_cases, - failures - .iter() - .map(|(name, msg)| format!("===========================\n{}:\n\n{:?}", name, msg)) - .collect::>() - .join("\n") - ); + expected => Err(format!("expected: {:#?}\ngot: {:?}\n", expected, result)), } } From 34391e4cb51c1d13277d78971ce20c02f25eb2bd Mon Sep 17 00:00:00 2001 From: Lukasz Klimek <842586+lklimek@users.noreply.github.com> Date: Wed, 3 Jul 2024 12:25:02 +0200 Subject: [PATCH 47/55] test(sdk): refactor contested resource test to use #test_case --- .../rs-sdk/tests/fetch/contested_resource.rs | 384 ++++++------------ 1 file changed, 122 insertions(+), 262 deletions(-) diff --git a/packages/rs-sdk/tests/fetch/contested_resource.rs b/packages/rs-sdk/tests/fetch/contested_resource.rs index 330ea04a9c0..8ceacfba3aa 100644 --- a/packages/rs-sdk/tests/fetch/contested_resource.rs +++ b/packages/rs-sdk/tests/fetch/contested_resource.rs @@ -4,8 +4,10 @@ use crate::fetch::{ common::{setup_logs, TEST_DPNS_NAME}, config::Config, }; -use core::panic; -use dash_sdk::platform::FetchMany; +use dash_sdk::{ + platform::{FetchMany, Query}, + Error, +}; use dpp::{ platform_value::Value, voting::{ @@ -20,6 +22,7 @@ use drive::query::{ vote_polls_by_document_type_query::VotePollsByDocumentTypeQuery, }; use drive_proof_verifier::types::ContestedResource; +use hex::ToHex; use std::panic::catch_unwind; /// Test that we can fetch contested resources @@ -42,24 +45,26 @@ async fn test_contested_resources_ok() { .await .expect("prerequisities"); - let index_name = "parentNameAndLabel"; + let query = base_query(&cfg); + + let rss = ContestedResource::fetch_many(&sdk, query) + .await + .expect("fetch contested resources"); + tracing::debug!(contested_resources=?rss, "Contested resources"); + assert!(!rss.0.is_empty()); +} - let query = VotePollsByDocumentTypeQuery { +fn base_query(cfg: &Config) -> VotePollsByDocumentTypeQuery { + VotePollsByDocumentTypeQuery { contract_id: cfg.existing_data_contract_id, document_type_name: cfg.existing_document_type_name.clone(), - index_name: index_name.to_string(), + index_name: "parentNameAndLabel".to_string(), start_at_value: None, - start_index_values: vec![Value::Text("dash".into())], + start_index_values: vec![Value::Text("dash".to_string())], end_index_values: vec![], limit: None, order_ascending: false, - }; - - let rss = ContestedResource::fetch_many(&sdk, query) - .await - .expect("fetch contested resources"); - tracing::debug!(contested_resources=?rss, "Contested resources"); - assert!(!rss.0.is_empty()); + } } #[tokio::test(flavor = "multi_thread", worker_threads = 1)] @@ -225,275 +230,130 @@ async fn contested_resources_limit_PLAN_656() { assert_eq!(i, count_all, "all contested resources fetched"); } } - /// Check various queries for [ContestedResource] that contain invalid field values /// /// ## Preconditions /// /// None +#[test_case::test_case(|_q| {}, Ok("ContestedResources([Value(Text(".into()); "unmodified base query is Ok")] +#[test_case::test_case(|q| q.start_index_values = vec![Value::Text("".to_string())], Ok("".into()); "index value empty string is Ok")] +#[test_case::test_case(|q| q.document_type_name = "some random non-existing name".to_string(), Err(r#"code: InvalidArgument, message: "document type some random non-existing name not found"#); "non existing document type returns InvalidArgument")] +#[test_case::test_case(|q| q.index_name = "nx index".to_string(), Err(r#"code: InvalidArgument, message: "index with name nx index is not the contested index"#); "non existing index returns InvalidArgument")] +#[test_case::test_case(|q| q.index_name = "dashIdentityId".to_string(), Err(r#"code: InvalidArgument, message: "index with name dashIdentityId is not the contested index"#); "existing non-contested index returns InvalidArgument")] +#[test_case::test_case(|q| q.start_at_value = Some((Value::Array(vec![]), true)), Err(r#"code: InvalidArgument"#); "start_at_value wrong index type returns InvalidArgument PLAN-653")] +#[test_case::test_case(|q| q.start_index_values = vec![], Ok(r#"ContestedResources([Value(Text("dash"))])"#.into()); "start_index_values empty vec returns top-level keys")] +#[test_case::test_case(|q| q.start_index_values = vec![Value::Text("".to_string())], Ok(r#"ContestedResources([])"#.into()); "start_index_values empty string returns zero results")] +#[test_case::test_case(|q| { + q.start_index_values = vec![ + Value::Text("dash".to_string()), + Value::Text(TEST_DPNS_NAME.to_string()), + ] +}, Err("incorrect index values error: too many start index values were provided, since no end index values were provided, the start index values must be less than the amount of properties in the contested index"); "start_index_values with two values returns error")] +#[test_case::test_case(|q| { + q.start_index_values = vec![]; + q.end_index_values = vec![Value::Text(TEST_DPNS_NAME.to_string())]; +}, Ok(r#"ContestedResources([Value(Text("dash"))])"#.into()); "end_index_values one value with empty start_index_values returns 'dash'")] +#[test_case::test_case(|q| { + q.start_index_values = vec![]; + q.end_index_values = vec![Value::Text(TEST_DPNS_NAME.to_string()), Value::Text("non existing".to_string())]; +}, Err("too many end index values were provided"); "end_index_values two values (1 nx) with empty start_index_values returns error")] +#[test_case::test_case(|q| { + q.start_index_values = vec![]; + q.end_index_values = vec![Value::Text("aaa non existing".to_string())]; +}, Ok(r#"ContestedResources([])"#.into()); "end_index_values with 1 nx value 'aaa*' and empty start_index_values returns zero objects")] +#[test_case::test_case(|q| { + q.start_index_values = vec![]; + q.end_index_values = vec![Value::Text("zzz non existing".to_string())]; +}, Ok(r#"ContestedResources([])"#.into()); "end_index_values with 1 nx value 'zzz*' and empty start_index_values returns zero objects")] +#[test_case::test_case(|q| { + q.start_index_values = vec![ + Value::Text("dash".to_string()), + Value::Text(TEST_DPNS_NAME.to_string()), + Value::Text("eee".to_string()), + ] +}, Err("incorrect index values error: too many start index values were provided, since no end index values were provided, the start index values must be less than the amount of properties in the contested index"); "too many items in start_index_values returns error")] +#[test_case::test_case(|q| { + q.end_index_values = vec![Value::Text("zzz non existing".to_string())] +}, Err("incorrect index values error: too many end index values were provided"); "Both start_ and end_index_values returns error")] +#[test_case::test_case(|q| { + q.start_index_values = vec![]; + q.end_index_values = vec![Value::Text("zzz non existing".to_string())] +}, Ok("ContestedResources([])".into()); "Non-existing end_index_values returns error")] +#[test_case::test_case(|q| q.end_index_values = vec![Value::Array(vec![0.into(), 1.into()])], Err("incorrect index values error: too many end index values were provided"); "wrong type of end_index_values should return InvalidArgument")] +#[test_case::test_case(|q| q.limit = Some(0), Err(r#"code: InvalidArgument"#); "limit 0 returns InvalidArgument")] +#[test_case::test_case(|q| q.limit = Some(std::u16::MAX), Err(r#"code: InvalidArgument"#); "limit std::u16::MAX returns InvalidArgument")] +#[test_case::test_case(|q| { + q.start_index_values = vec![Value::Text("dash".to_string())]; + q.start_at_value = Some((Value::Text(TEST_DPNS_NAME.to_string()), true)); + q.limit = Some(1); +}, Ok(format!(r#"ContestedResources([Value(Text({}))])"#, TEST_DPNS_NAME)); "exact match query returns one object PLAN-656")] #[tokio::test(flavor = "multi_thread", worker_threads = 1)] -async fn contested_resources_fields() { +async fn contested_resources_fields( + query_mut_fn: fn(&mut VotePollsByDocumentTypeQuery), + expect: Result, +) -> Result<(), String> { setup_logs(); - type MutFn = fn(&mut VotePollsByDocumentTypeQuery); - struct TestCase { - name: &'static str, - query_mut_fn: MutFn, - expect: Result, - } - - let test_cases: Vec = vec![ - TestCase { - name: "unmodified base query is Ok", - query_mut_fn: |_q| {}, - expect: Ok("ContestedResources([Value(Text(".into()), - }, - TestCase { - name: "index value empty string is Ok", - query_mut_fn: |q| q.start_index_values = vec![Value::Text("".to_string())], - expect: Ok("".into()), - }, - TestCase { - name: "non existing document type returns InvalidArgument", - query_mut_fn: |q| q.document_type_name = "some random non-existing name".to_string(), - expect: Err( - r#"code: InvalidArgument, message: "document type some random non-existing name not found"#, - ), - }, - TestCase { - name: "non existing index returns InvalidArgument", - query_mut_fn: |q| q.index_name = "nx index".to_string(), - expect: Err( - r#"code: InvalidArgument, message: "index with name nx index is not the contested index"#, - ), - }, - TestCase { - name: "existing non-contested index returns InvalidArgument", - query_mut_fn: |q| q.index_name = "dashIdentityId".to_string(), - expect: Err( - r#"code: InvalidArgument, message: "index with name dashIdentityId is not the contested index"#, - ), - }, - TestCase { - name: "start_at_value wrong index type returns InvalidArgument PLAN-653", - query_mut_fn: |q| q.start_at_value = Some((Value::Array(vec![]), true)), - expect: Err(r#"code: InvalidArgument"#), - }, - TestCase { - name: "start_index_values empty vec returns top-level keys", - query_mut_fn: |q| q.start_index_values = vec![], - expect: Ok(r#"ContestedResources([Value(Text("dash"))])"#.into()), - }, - TestCase { - name: "start_index_values empty string returns zero results", - query_mut_fn: |q| q.start_index_values = vec![Value::Text("".to_string())], - expect: Ok(r#"ContestedResources([])"#.into()), - }, - TestCase { - name: "start_index_values with two values returns error", - query_mut_fn: |q| { - q.start_index_values = vec![ - Value::Text("dash".to_string()), - Value::Text(TEST_DPNS_NAME.to_string()), - ] - }, - expect: Err("incorrect index values error: too many start index values were provided, since no end index values were provided, the start index values must be less than the amount of properties in the contested index"), - }, - TestCase { - name: "end_index_values one value with empty start_index_values returns 'dash'", - query_mut_fn: |q| { - q.start_index_values = vec![]; - q.end_index_values = vec![Value::Text(TEST_DPNS_NAME.to_string())]; - }, - expect:Ok(r#"ContestedResources([Value(Text("dash"))])"#.into()), - }, - TestCase { - name: "end_index_values two values (1 nx) with empty start_index_values returns error", - query_mut_fn: |q| { - q.start_index_values = vec![]; - q.end_index_values = vec![Value::Text(TEST_DPNS_NAME.to_string()), Value::Text("non existing".to_string())]; - }, - expect:Err("too many end index values were provided"), - }, - TestCase { - name: "end_index_values with 1 nx value 'aaa*' and empty start_index_values returns zero objects", - query_mut_fn: |q| { - q.start_index_values = vec![]; - q.end_index_values = vec![Value::Text("aaa non existing".to_string())]; - }, - expect:Ok(r#"ContestedResources([])"#.into()), - }, - TestCase { - name: "end_index_values with 1 nx value 'zzz*' and empty start_index_values returns zero objects", - query_mut_fn: |q| { - q.start_index_values = vec![]; - q.end_index_values = vec![Value::Text("zzz non existing".to_string())]; - }, - expect:Ok(r#"ContestedResources([])"#.into()), - }, - TestCase { - // fails due to PLAN-662 - name: "too many items in start_index_values returns error", - query_mut_fn: |q| { - q.start_index_values = vec![ - Value::Text("dash".to_string()), - Value::Text(TEST_DPNS_NAME.to_string()), - Value::Text("eee".to_string()), - ] - }, - expect: Err("incorrect index values error: too many start index values were provided, since no end index values were provided, the start index values must be less than the amount of properties in the contested index"), - }, - TestCase { - name: "Both start_ and end_index_values returns error", - query_mut_fn: |q| { - q.end_index_values = vec![Value::Text("zzz non existing".to_string())] - }, - expect: Err("incorrect index values error: too many end index values were provided"), - }, - TestCase { - name: "Non-existing end_index_values returns error", - query_mut_fn: |q| { - q.start_index_values = vec![]; - q.end_index_values = vec![Value::Text("zzz non existing".to_string())] - }, - expect:Ok("ContestedResources([])".into()), - }, - TestCase { - name: "wrong type of end_index_values should return InvalidArgument", - query_mut_fn: |q| q.end_index_values = vec![Value::Array(vec![0.into(), 1.into()])], - expect: Err("incorrect index values error: too many end index values were provided"), - }, - TestCase { - name: "limit 0 returns InvalidArgument", - query_mut_fn: |q| q.limit = Some(0), - expect: Err(r#"code: InvalidArgument"#), - }, - TestCase { - name: "limit std::u16::MAX returns InvalidArgument", - query_mut_fn: |q| q.limit = Some(std::u16::MAX), - expect: Err(r#"code: InvalidArgument"#), - }, - TestCase{ - name: "exact match query returns one object PLAN-656", - query_mut_fn: |q| { - q.start_index_values = vec![Value::Text("dash".to_string())]; - q.start_at_value = Some((Value::Text(TEST_DPNS_NAME.to_string()), true)); - q.limit = Some(1); - }, - expect: Ok(format!(r#"ContestedResources([Value(Text({}))])"#, TEST_DPNS_NAME)), - - } - // start index + start at + limit 1 - ]; - let cfg = Config::new(); check_mn_voting_prerequisities(&cfg) .await .expect("prerequisities"); - let base_query = VotePollsByDocumentTypeQuery { - contract_id: cfg.existing_data_contract_id, - document_type_name: cfg.existing_document_type_name.clone(), - index_name: "parentNameAndLabel".to_string(), - start_at_value: None, - start_index_values: vec![Value::Text("dash".to_string())], - end_index_values: vec![], - limit: None, - order_ascending: false, - }; + tracing::debug!(?expect, "Running test case"); + // handle panics to not stop other test cases from running + let unwinded = catch_unwind(|| { + { + pollster::block_on(async { + let mut query = base_query(&cfg); + query_mut_fn(&mut query); + let key = rs_dapi_client::mock::Key::new( + &query.clone().query(true).expect("valid query"), + ); + let test_case_id = + format!("contested_resources_fields_{}", key.encode_hex::()); - // check if the base query works - let base_query_sdk = cfg.setup_api("contested_resources_fields_base_query").await; - let result = ContestedResource::fetch_many(&base_query_sdk, base_query.clone()).await; - assert!( - result.is_ok_and(|v| !v.0.is_empty()), - "base query should return some results" - ); - - let mut failures: Vec<(&'static str, String)> = Default::default(); - - for test_case in test_cases { - tracing::debug!("Running test case: {}", test_case.name); - // handle panics to not stop other test cases from running - let unwinded = catch_unwind(|| { - { - pollster::block_on(async { - // create new sdk to ensure that test cases don't interfere with each other - let sdk = cfg - .setup_api(&format!("contested_resources_fields_{}", test_case.name)) - .await; - - let mut query = base_query.clone(); - (test_case.query_mut_fn)(&mut query); - - ContestedResource::fetch_many(&sdk, query).await - }) - } - }); - let result = match unwinded { - Ok(r) => r, - Err(e) => { - let msg = if let Some(s) = e.downcast_ref::<&str>() { - s.to_string() - } else if let Some(s) = e.downcast_ref::() { - s.to_string() - } else { - format!("unknown panic type: {:?}", std::any::type_name_of_val(&e)) - }; + // create new sdk to ensure that test cases don't interfere with each other + let sdk = cfg.setup_api(&test_case_id).await; - failures.push((test_case.name, format!("PANIC: {}", msg))); - continue; // continue to next test case - } - }; + ContestedResource::fetch_many(&sdk, query).await + }) + } + }); + let result = match unwinded { + Ok(r) => r, + Err(e) => { + let msg = if let Some(s) = e.downcast_ref::<&str>() { + s.to_string() + } else if let Some(s) = e.downcast_ref::() { + s.to_string() + } else { + format!("unknown panic type: {:?}", std::any::type_name_of_val(&e)) + }; - match test_case.expect { - Ok(expected) if result.is_ok() => { - let result_string = format!("{:?}", result.as_ref().expect("result")); - if !result_string.contains(&expected) { - failures.push(( - test_case.name, - format!("EXPECTED: {} GOT: {:?}\n", expected, result), - )); - } - } - Err(expected) if result.is_err() => { - let result = result.expect_err("error"); - if !result.to_string().contains(expected) { - failures.push(( - test_case.name, - format!("EXPECTED: {} GOT: {:?}\n", expected, result), - )); - } - } - expected => { - failures.push(( - test_case.name, - format!("EXPECTED: {:?} GOT: {:?}\n", expected, result), - )); + tracing::error!("PANIC: {}", msg); + Err(Error::Generic(msg)) + } + }; + + match expect { + Ok(expected) if result.is_ok() => { + let result_string = format!("{:?}", result.as_ref().expect("result")); + if !result_string.contains(&expected) { + Err(format!("EXPECTED: {} GOT: {:?}\n", expected, result)) + } else { + Ok(()) } } - } - if !failures.is_empty() { - for failure in &failures { - tracing::error!(?failure, "Failed: {}", failure.0); + Err(expected) if result.is_err() => { + let result = result.expect_err("error"); + if !result.to_string().contains(expected) { + Err(format!("EXPECTED: {} GOT: {:?}\n", expected, result)) + } else { + Ok(()) + } } - let failed_cases = failures - .iter() - .map(|(name, _)| name.to_string()) - .collect::>() - .join("\n* "); - - panic!( - "{} test cases failed:\n* {}\n\n{}\n", - failures.len(), - failed_cases, - failures - .iter() - .map(|(name, msg)| format!("===========================\n{}:\n\n{:?}", name, msg)) - .collect::>() - .join("\n") - ); + expected => Err(format!("EXPECTED: {:?} GOT: {:?}\n", expected, result)), } } From 19d203a0dcbd2cb42dba0004e13fbdc1caad5162 Mon Sep 17 00:00:00 2001 From: Lukasz Klimek <842586+lklimek@users.noreply.github.com> Date: Wed, 3 Jul 2024 14:50:28 +0200 Subject: [PATCH 48/55] chore: self review --- .../rs-sdk/scripts/generate_test_vectors.sh | 2 +- .../rs-sdk/src/platform/transition/vote.rs | 13 ++- packages/rs-sdk/tests/fetch/common.rs | 26 ++++++ .../rs-sdk/tests/fetch/contested_resource.rs | 18 ++-- .../fetch/contested_resource_polls_by_ts.rs | 4 +- .../fetch/contested_resource_vote_state.rs | 88 +++++++------------ 6 files changed, 69 insertions(+), 82 deletions(-) diff --git a/packages/rs-sdk/scripts/generate_test_vectors.sh b/packages/rs-sdk/scripts/generate_test_vectors.sh index 3e0a321ef7b..a5530e7d93e 100755 --- a/packages/rs-sdk/scripts/generate_test_vectors.sh +++ b/packages/rs-sdk/scripts/generate_test_vectors.sh @@ -19,7 +19,7 @@ CARGO_DIR="$(realpath "$(dirname "$0")/..")" pushd "$CARGO_DIR" -set -ex + cargo test -p dash-sdk \ --no-default-features \ --features generate-test-vectors \ diff --git a/packages/rs-sdk/src/platform/transition/vote.rs b/packages/rs-sdk/src/platform/transition/vote.rs index 3dbae7310d5..56864a760ca 100644 --- a/packages/rs-sdk/src/platform/transition/vote.rs +++ b/packages/rs-sdk/src/platform/transition/vote.rs @@ -5,6 +5,7 @@ use crate::platform::transition::put_settings::PutSettings; use crate::platform::Fetch; use crate::{Error, Sdk}; use dapi_grpc::platform::VersionedGrpcResponse; +use dpp::identifier::MasternodeIdentifiers; use dpp::identity::hash::IdentityPublicKeyHashMethodsV0; use dpp::identity::signer::Signer; use dpp::identity::IdentityPublicKey; @@ -17,7 +18,6 @@ use dpp::voting::votes::Vote; use drive::drive::Drive; use drive_proof_verifier::{error::ContextProviderError, DataContractProvider}; use rs_dapi_client::DapiRequest; -use sha2::{Digest, Sha256}; #[async_trait::async_trait] /// A trait for putting a vote on platform @@ -160,11 +160,8 @@ fn get_voting_identity_id( ) -> Result { let pub_key_hash = voting_public_key.public_key_hash()?; - let mut hasher = Sha256::new(); - hasher.update(voter_pro_tx_hash.as_bytes()); - hasher.update(pub_key_hash); - let voting_identity_id_hashed = hasher.finalize(); - - Identifier::from_bytes(&voting_identity_id_hashed) - .map_err(|e| Error::Generic(format!("Couldn't convert id string to Identifier: {}", e))) + Ok(Identifier::create_voter_identifier( + voter_pro_tx_hash.as_bytes(), + &pub_key_hash, + )) } diff --git a/packages/rs-sdk/tests/fetch/common.rs b/packages/rs-sdk/tests/fetch/common.rs index edbe4d2fc77..da109c4da0b 100644 --- a/packages/rs-sdk/tests/fetch/common.rs +++ b/packages/rs-sdk/tests/fetch/common.rs @@ -1,4 +1,9 @@ +use dash_sdk::{mock::Mockable, platform::Query, Sdk}; use dpp::{data_contract::DataContractFactory, prelude::Identifier}; +use hex::ToHex; +use rs_dapi_client::transport::TransportRequest; + +use super::config::Config; /// Test DPNS name for testing of the Sdk; at least 3 identities should request this name to be reserved pub(crate) const TEST_DPNS_NAME: &str = "testname"; @@ -83,3 +88,24 @@ pub fn setup_logs() { .try_init() .ok(); } + +/// Configure test case generated with [::test_case] crate. +/// +/// This function is intended to use with multiple test cases in a single function. +/// As a test case shares function body, we need to generate unique name for each of them to isolate generated +/// test vectors. It is done by hashing query and using it as a suffix for test case name. +/// +/// ## Returns +/// +/// Returns unique name of test case (generated from `name_prefix` and hash of query) and configured SDK. +pub(crate) async fn setup_sdk_for_test_case>( + cfg: Config, + query: Q, + name_prefix: &str, +) -> (String, Sdk) { + let key = rs_dapi_client::mock::Key::new(&query.query(true).expect("valid query")); + let test_case_id = format!("{}_{}", name_prefix, key.encode_hex::()); + + // create new sdk to ensure that test cases don't interfere with each other + (test_case_id.clone(), cfg.setup_api(&test_case_id).await) +} diff --git a/packages/rs-sdk/tests/fetch/contested_resource.rs b/packages/rs-sdk/tests/fetch/contested_resource.rs index 8ceacfba3aa..2fd3550cc2f 100644 --- a/packages/rs-sdk/tests/fetch/contested_resource.rs +++ b/packages/rs-sdk/tests/fetch/contested_resource.rs @@ -1,13 +1,10 @@ //! Tests of ContestedResource object use crate::fetch::{ - common::{setup_logs, TEST_DPNS_NAME}, + common::{setup_logs, setup_sdk_for_test_case, TEST_DPNS_NAME}, config::Config, }; -use dash_sdk::{ - platform::{FetchMany, Query}, - Error, -}; +use dash_sdk::{platform::FetchMany, Error}; use dpp::{ platform_value::Value, voting::{ @@ -22,7 +19,6 @@ use drive::query::{ vote_polls_by_document_type_query::VotePollsByDocumentTypeQuery, }; use drive_proof_verifier::types::ContestedResource; -use hex::ToHex; use std::panic::catch_unwind; /// Test that we can fetch contested resources @@ -307,14 +303,10 @@ async fn contested_resources_fields( pollster::block_on(async { let mut query = base_query(&cfg); query_mut_fn(&mut query); - let key = rs_dapi_client::mock::Key::new( - &query.clone().query(true).expect("valid query"), - ); - let test_case_id = - format!("contested_resources_fields_{}", key.encode_hex::()); - // create new sdk to ensure that test cases don't interfere with each other - let sdk = cfg.setup_api(&test_case_id).await; + let (test_case_id, sdk) = + setup_sdk_for_test_case(cfg, query.clone(), "contested_resources_fields").await; + tracing::debug!(test_case_id, ?query, "Executing query"); ContestedResource::fetch_many(&sdk, query).await }) diff --git a/packages/rs-sdk/tests/fetch/contested_resource_polls_by_ts.rs b/packages/rs-sdk/tests/fetch/contested_resource_polls_by_ts.rs index 07cc4992dce..7554af5ddc3 100644 --- a/packages/rs-sdk/tests/fetch/contested_resource_polls_by_ts.rs +++ b/packages/rs-sdk/tests/fetch/contested_resource_polls_by_ts.rs @@ -1,9 +1,9 @@ //! Test VotePollsByEndDateDriveQuery use crate::fetch::{common::setup_logs, config::Config}; -use chrono::{DateTime, Days, TimeZone, Utc}; +use chrono::{DateTime, TimeZone, Utc}; use dash_sdk::platform::FetchMany; -use dpp::{identity::TimestampMillis, voting::vote_polls::VotePoll}; +use dpp::voting::vote_polls::VotePoll; use drive::query::VotePollsByEndDateDriveQuery; use std::collections::BTreeMap; diff --git a/packages/rs-sdk/tests/fetch/contested_resource_vote_state.rs b/packages/rs-sdk/tests/fetch/contested_resource_vote_state.rs index cf8576dc2be..55af219801c 100644 --- a/packages/rs-sdk/tests/fetch/contested_resource_vote_state.rs +++ b/packages/rs-sdk/tests/fetch/contested_resource_vote_state.rs @@ -1,6 +1,6 @@ //! Tests for SDK requests that return one or more [Contender] objects. use crate::fetch::{ - common::{setup_logs, TEST_DPNS_NAME}, + common::{setup_logs, setup_sdk_for_test_case, TEST_DPNS_NAME}, config::Config, contested_resource::check_mn_voting_prerequisities, }; @@ -21,7 +21,6 @@ use dpp::{ use drive::query::vote_poll_vote_state_query::{ ContestedDocumentVotePollDriveQuery, ContestedDocumentVotePollDriveQueryResultType, }; -use sha2::Digest; use test_case::test_case; /// Ensure we get proof of non-existence when querying for a non-existing index value. @@ -129,32 +128,21 @@ async fn contested_resource_vote_states_ok() { let cfg = Config::new(); let sdk = cfg.setup_api("contested_resource_vote_states_ok").await; // Given some existing data contract and existing label - let data_contract_id = cfg.existing_data_contract_id; - let label = Value::Text(convert_to_homograph_safe_chars(TEST_DPNS_NAME)); - let document_type_name = "domain".to_string(); + + let query = base_query(&cfg); + + let data_contract_id = query.vote_poll.contract_id; + let document_type_name = &query.vote_poll.document_type_name; let data_contract = DataContract::fetch_by_identifier(&sdk, data_contract_id) .await .expect("fetch data contract") .expect("found data contract"); let document_type = data_contract - .document_type_for_name(&document_type_name) + .document_type_for_name(document_type_name) .expect("found document type"); // When I query for vote poll states with existing index values - let query = ContestedDocumentVotePollDriveQuery { - limit: None, - offset: None, - start_at: None, - vote_poll: ContestedDocumentResourceVotePoll { - index_name: "parentNameAndLabel".to_string(), - index_values: vec![Value::Text("dash".into()), label], - document_type_name, - contract_id: data_contract_id, - }, - allow_include_locked_and_abstaining_vote_tally: true, - result_type: ContestedDocumentVotePollDriveQueryResultType::DocumentsAndVoteTally, - }; let contenders = ContenderWithSerializedDocument::fetch_many(&sdk, query) .await @@ -185,6 +173,24 @@ async fn contested_resource_vote_states_ok() { } } +fn base_query(cfg: &Config) -> ContestedDocumentVotePollDriveQuery { + let index_value_2 = Value::Text(convert_to_homograph_safe_chars(TEST_DPNS_NAME)); + + ContestedDocumentVotePollDriveQuery { + limit: None, + offset: None, + start_at: None, + vote_poll: ContestedDocumentResourceVotePoll { + index_name: "parentNameAndLabel".to_string(), + index_values: vec![Value::Text("dash".into()), index_value_2], + document_type_name: cfg.existing_document_type_name.clone(), + contract_id: cfg.existing_data_contract_id, + }, + allow_include_locked_and_abstaining_vote_tally: true, + result_type: ContestedDocumentVotePollDriveQueryResultType::DocumentsAndVoteTally, + } +} + /// Ensure we can limit the number of returned contenders. /// /// ## Preconditions @@ -307,46 +313,12 @@ async fn contested_rss_vote_state_fields( .await .expect("prerequisities"); - let base_query = ContestedDocumentVotePollDriveQuery { - limit: None, - offset: None, - start_at: None, - vote_poll: ContestedDocumentResourceVotePoll { - index_name: "parentNameAndLabel".to_string(), - index_values: vec![ - Value::Text("dash".into()), - Value::Text(TEST_DPNS_NAME.into()), - ], - document_type_name: cfg.existing_document_type_name.clone(), - contract_id: cfg.existing_data_contract_id, - }, - allow_include_locked_and_abstaining_vote_tally: true, - result_type: ContestedDocumentVotePollDriveQueryResultType::DocumentsAndVoteTally, - }; - - // check if the base query works - // TODO: maybe move to another test - let base_query_sdk = cfg - .setup_api("contested_rss_vote_state_fields_base_query") - .await; - let result = - ContenderWithSerializedDocument::fetch_many(&base_query_sdk, base_query.clone()).await; - assert!( - result.is_ok_and(|v| !v.contenders.is_empty()), - "base query should return some results" - ); - - // we need some unique identifier for test vector - - let mut hasher = sha2::Sha256::new(); - hasher.update(format!("{:?}", &expect).as_bytes()); - let ns = format!("contested_rss_vote_state_fields_{:x}", hasher.finalize()); - - let sdk = cfg.setup_api(&ns).await; - - let mut query = base_query.clone(); + let mut query = base_query(&cfg); query_mut_fn(&mut query); - tracing::debug!(?query, ?ns, "Executing test case query"); + let (test_case_id, sdk) = + setup_sdk_for_test_case(cfg, query.clone(), "contested_rss_vote_state_fields_").await; + + tracing::debug!(test_case_id, ?query, "Executing test case query"); let result = ContenderWithSerializedDocument::fetch_many(&sdk, query).await; tracing::debug!(?result, "Result of test case"); From 4b0d3805db3c2f2781c0de4edf0c440581fd96ca Mon Sep 17 00:00:00 2001 From: Lukasz Klimek <842586+lklimek@users.noreply.github.com> Date: Wed, 3 Jul 2024 15:04:23 +0200 Subject: [PATCH 49/55] chore: ignore some tests --- packages/rs-sdk/tests/fetch/contested_resource.rs | 4 ++++ .../tests/fetch/contested_resource_vote_state.rs | 13 +++++++++++++ .../rs-sdk/tests/fetch/contested_resource_voters.rs | 4 ++++ .../tests/fetch/prefunded_specialized_balance.rs | 7 +++++-- 4 files changed, 26 insertions(+), 2 deletions(-) diff --git a/packages/rs-sdk/tests/fetch/contested_resource.rs b/packages/rs-sdk/tests/fetch/contested_resource.rs index 2fd3550cc2f..9faf4b41461 100644 --- a/packages/rs-sdk/tests/fetch/contested_resource.rs +++ b/packages/rs-sdk/tests/fetch/contested_resource.rs @@ -284,6 +284,10 @@ async fn contested_resources_limit_PLAN_656() { q.limit = Some(1); }, Ok(format!(r#"ContestedResources([Value(Text({}))])"#, TEST_DPNS_NAME)); "exact match query returns one object PLAN-656")] #[tokio::test(flavor = "multi_thread", worker_threads = 1)] +#[cfg_attr( + feature = "network-testing", + ignore = "requires manual DPNS names setup for masternode voting tests; see fn check_mn_voting_prerequisities()" +)] async fn contested_resources_fields( query_mut_fn: fn(&mut VotePollsByDocumentTypeQuery), expect: Result, diff --git a/packages/rs-sdk/tests/fetch/contested_resource_vote_state.rs b/packages/rs-sdk/tests/fetch/contested_resource_vote_state.rs index 55af219801c..82e4a8b18d5 100644 --- a/packages/rs-sdk/tests/fetch/contested_resource_vote_state.rs +++ b/packages/rs-sdk/tests/fetch/contested_resource_vote_state.rs @@ -121,6 +121,11 @@ async fn contested_resource_vote_states_nx_contract() { /// ## Preconditions /// /// 1. There must be at least one contender for name "dash" and value "[TEST_DPNS_NAME]". +/// +#[cfg_attr( + feature = "network-testing", + ignore = "equires manual DPNS names setup for masternode voting tests; see fn check_mn_voting_prerequisities()" +)] #[tokio::test(flavor = "multi_thread", worker_threads = 1)] async fn contested_resource_vote_states_ok() { setup_logs(); @@ -198,6 +203,10 @@ fn base_query(cfg: &Config) -> ContestedDocumentVotePollDriveQuery { /// 1. There must be at least 3 condenders for name "dash" and value [TEST_DPNS_NAME]. /// #[tokio::test(flavor = "multi_thread", worker_threads = 1)] +#[cfg_attr( + feature = "network-testing", + ignore = "equires manual DPNS names setup for masternode voting tests; see fn check_mn_voting_prerequisities()" +)] #[allow(non_snake_case)] async fn contested_resource_vote_states_with_limit_PLAN_674() { setup_logs(); @@ -302,6 +311,10 @@ type MutFn = fn(&mut ContestedDocumentVotePollDriveQuery); q.result_type = ContestedDocumentVotePollDriveQueryResultType::VoteTally }, Ok(r#"serialized_document: None, vote_tally: Some"#); "result_type VoteTally")] #[tokio::test(flavor = "multi_thread", worker_threads = 1)] +#[cfg_attr( + feature = "network-testing", + ignore = "equires manual DPNS names setup for masternode voting tests; see fn check_mn_voting_prerequisities()" +)] async fn contested_rss_vote_state_fields( query_mut_fn: MutFn, expect: Result<&'static str, &'static str>, diff --git a/packages/rs-sdk/tests/fetch/contested_resource_voters.rs b/packages/rs-sdk/tests/fetch/contested_resource_voters.rs index b7b374f9256..8bf8f1badd4 100644 --- a/packages/rs-sdk/tests/fetch/contested_resource_voters.rs +++ b/packages/rs-sdk/tests/fetch/contested_resource_voters.rs @@ -64,6 +64,10 @@ async fn test_contested_resource_voters_for_identity_not_found() { /// /// 1. Votes exist for DPNS name [TEST_DPNS_NAME]. #[tokio::test(flavor = "multi_thread", worker_threads = 1)] +#[cfg_attr( + feature = "network-testing", + ignore = "requires manual DPNS names setup for masternode voting tests; see fn check_mn_voting_prerequisities()" +)] async fn contested_resource_voters_for_existing_contestant() { setup_logs(); diff --git a/packages/rs-sdk/tests/fetch/prefunded_specialized_balance.rs b/packages/rs-sdk/tests/fetch/prefunded_specialized_balance.rs index d2db8aa5f94..2355a932aba 100644 --- a/packages/rs-sdk/tests/fetch/prefunded_specialized_balance.rs +++ b/packages/rs-sdk/tests/fetch/prefunded_specialized_balance.rs @@ -26,6 +26,10 @@ async fn test_prefunded_specialized_balance_not_found() { } #[tokio::test(flavor = "multi_thread", worker_threads = 1)] +#[cfg_attr( + feature = "network-testing", + ignore = "requires manual DPNS names setup for masternode voting tests; see fn check_mn_voting_prerequisities()" +)] async fn test_prefunded_specialized_balance_ok() { setup_logs(); @@ -49,8 +53,7 @@ async fn test_prefunded_specialized_balance_ok() { let poll = polls .0 - .iter() - .next() + .first() .expect("need at least one vote poll timestamp") .1 .first() From 2b4a9770233af9231b4d1dea26d9ffa1dd7b2bf4 Mon Sep 17 00:00:00 2001 From: Lukasz Klimek <842586+lklimek@users.noreply.github.com> Date: Wed, 3 Jul 2024 15:10:56 +0200 Subject: [PATCH 50/55] chore: remove invalid test case --- packages/rs-sdk/tests/fetch/contested_resource_vote_state.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/rs-sdk/tests/fetch/contested_resource_vote_state.rs b/packages/rs-sdk/tests/fetch/contested_resource_vote_state.rs index 82e4a8b18d5..f792a9b5ba3 100644 --- a/packages/rs-sdk/tests/fetch/contested_resource_vote_state.rs +++ b/packages/rs-sdk/tests/fetch/contested_resource_vote_state.rs @@ -277,7 +277,6 @@ type MutFn = fn(&mut ContestedDocumentVotePollDriveQuery); #[test_case(|q| q.limit = Some(0), Err("limit 0 out of bounds of [1, 100]"); "limit 0")] #[test_case(|q| q.limit = Some(std::u16::MAX), Err("limit 65535 out of bounds of [1, 100]"); "limit std::u16::MAX")] -#[test_case(|q| q.offset = Some(1), Err("ContestedDocumentVotePollDriveQuery.offset field is internal and must be set to None"); "offset not None")] #[test_case(|q| q.start_at = Some(([0x11; 32], true)), Ok("Contenders { contenders: {Identifier("); "start_at does not exist should return next contenders")] #[test_case(|q| q.start_at = Some(([0xff; 32], true)), Ok("Contenders { contenders: {}, abstain_vote_tally: None, lock_vote_tally: None }"); "start_at 0xff;32 should return zero contenders")] #[test_case(|q| q.vote_poll.document_type_name = "nx doctype".to_string(), Err(r#"code: InvalidArgument, message: "document type nx doctype not found"#); "non existing document type returns InvalidArgument")] From f8720f4674d2d2929bfff7ed30ad2925ed1ac145 Mon Sep 17 00:00:00 2001 From: Quantum Explorer Date: Thu, 4 Jul 2024 00:12:59 +0700 Subject: [PATCH 51/55] added validation that we are not already a contestant --- packages/rs-dpp/src/errors/consensus/codes.rs | 1 + ...ent_contest_identity_already_contestant.rs | 49 +++ .../errors/consensus/state/document/mod.rs | 1 + .../src/errors/consensus/state/state_error.rs | 4 + .../state_v0/mod.rs | 23 +- .../state_v0/mod.rs | 9 +- .../state_transitions/documents_batch/mod.rs | 90 +++- .../state/v0/fetch_contender.rs | 53 +++ .../state/v0/fetch_documents.rs | 15 +- .../documents_batch/state/v0/mod.rs | 1 + .../state_transition/state_transitions/mod.rs | 146 ++++++- .../v0/mod.rs | 2 +- .../v0/mod.rs | 4 +- .../mod.rs | 6 +- .../v0/mod.rs | 4 +- .../drive/object_size_info/contract_info.rs | 13 + .../mod.rs | 19 + .../src/query/vote_poll_vote_state_query.rs | 394 +++++++----------- .../src/errors/consensus/consensus_error.rs | 4 + 19 files changed, 563 insertions(+), 275 deletions(-) create mode 100644 packages/rs-dpp/src/errors/consensus/state/document/document_contest_identity_already_contestant.rs create mode 100644 packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/documents_batch/state/v0/fetch_contender.rs diff --git a/packages/rs-dpp/src/errors/consensus/codes.rs b/packages/rs-dpp/src/errors/consensus/codes.rs index 1b278f50f5d..4e271ebadd4 100644 --- a/packages/rs-dpp/src/errors/consensus/codes.rs +++ b/packages/rs-dpp/src/errors/consensus/codes.rs @@ -209,6 +209,7 @@ impl ErrorWithCode for StateError { Self::DocumentIncorrectPurchasePriceError(_) => 40109, Self::DocumentContestCurrentlyLockedError(_) => 40110, Self::DocumentContestNotJoinableError(_) => 40111, + Self::DocumentContestIdentityAlreadyContestantError(_) => 40112, // Identity Errors: 40200-40299 Self::IdentityAlreadyExistsError(_) => 40200, diff --git a/packages/rs-dpp/src/errors/consensus/state/document/document_contest_identity_already_contestant.rs b/packages/rs-dpp/src/errors/consensus/state/document/document_contest_identity_already_contestant.rs new file mode 100644 index 00000000000..1f2cf0a14dc --- /dev/null +++ b/packages/rs-dpp/src/errors/consensus/state/document/document_contest_identity_already_contestant.rs @@ -0,0 +1,49 @@ +use crate::consensus::state::state_error::StateError; +use crate::consensus::ConsensusError; +use crate::errors::ProtocolError; +use crate::voting::vote_polls::contested_document_resource_vote_poll::ContestedDocumentResourceVotePoll; +use bincode::{Decode, Encode}; +use platform_serialization_derive::{PlatformDeserialize, PlatformSerialize}; +use platform_value::Identifier; +use thiserror::Error; + +#[derive( + Error, Debug, Clone, PartialEq, Encode, Decode, PlatformSerialize, PlatformDeserialize, +)] +#[error( + "An Identity with the id {identity_id} is already a contestant for the vote_poll {vote_poll}" +)] +#[platform_serialize(unversioned)] +pub struct DocumentContestIdentityAlreadyContestantError { + /* + + DO NOT CHANGE ORDER OF FIELDS WITHOUT INTRODUCING OF NEW VERSION + + */ + vote_poll: ContestedDocumentResourceVotePoll, + identity_id: Identifier, +} + +impl DocumentContestIdentityAlreadyContestantError { + pub fn new(vote_poll: ContestedDocumentResourceVotePoll, identity_id: Identifier) -> Self { + Self { + vote_poll, + identity_id, + } + } + + pub fn vote_poll(&self) -> &ContestedDocumentResourceVotePoll { + &self.vote_poll + } + pub fn identity_id(&self) -> &Identifier { + &self.identity_id + } +} + +impl From for ConsensusError { + fn from(err: DocumentContestIdentityAlreadyContestantError) -> Self { + Self::StateError(StateError::DocumentContestIdentityAlreadyContestantError( + err, + )) + } +} diff --git a/packages/rs-dpp/src/errors/consensus/state/document/mod.rs b/packages/rs-dpp/src/errors/consensus/state/document/mod.rs index e18c91dad63..9a3071065e4 100644 --- a/packages/rs-dpp/src/errors/consensus/state/document/mod.rs +++ b/packages/rs-dpp/src/errors/consensus/state/document/mod.rs @@ -1,5 +1,6 @@ pub mod document_already_present_error; pub mod document_contest_currently_locked_error; +pub mod document_contest_identity_already_contestant; pub mod document_contest_not_joinable_error; pub mod document_incorrect_purchase_price_error; pub mod document_not_for_sale_error; diff --git a/packages/rs-dpp/src/errors/consensus/state/state_error.rs b/packages/rs-dpp/src/errors/consensus/state/state_error.rs index 05dad1b09db..cf5736fd88d 100644 --- a/packages/rs-dpp/src/errors/consensus/state/state_error.rs +++ b/packages/rs-dpp/src/errors/consensus/state/state_error.rs @@ -30,6 +30,7 @@ use crate::consensus::ConsensusError; use crate::consensus::state::data_contract::data_contract_update_permission_error::DataContractUpdatePermissionError; use crate::consensus::state::data_contract::document_type_update_error::DocumentTypeUpdateError; use crate::consensus::state::document::document_contest_currently_locked_error::DocumentContestCurrentlyLockedError; +use crate::consensus::state::document::document_contest_identity_already_contestant::DocumentContestIdentityAlreadyContestantError; use crate::consensus::state::document::document_contest_not_joinable_error::DocumentContestNotJoinableError; use crate::consensus::state::document::document_incorrect_purchase_price_error::DocumentIncorrectPurchasePriceError; use crate::consensus::state::document::document_not_for_sale_error::DocumentNotForSaleError; @@ -74,6 +75,9 @@ pub enum StateError { #[error(transparent)] DocumentContestNotJoinableError(DocumentContestNotJoinableError), + #[error(transparent)] + DocumentContestIdentityAlreadyContestantError(DocumentContestIdentityAlreadyContestantError), + #[error(transparent)] DocumentNotFoundError(DocumentNotFoundError), diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/documents_batch/action_validation/document_create_transition_action/state_v0/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/documents_batch/action_validation/document_create_transition_action/state_v0/mod.rs index 7c28e0df76e..29368d7c99c 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/documents_batch/action_validation/document_create_transition_action/state_v0/mod.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/documents_batch/action_validation/document_create_transition_action/state_v0/mod.rs @@ -3,6 +3,7 @@ use dpp::consensus::basic::document::InvalidDocumentTypeError; use dpp::consensus::ConsensusError; use dpp::consensus::state::document::document_already_present_error::DocumentAlreadyPresentError; use dpp::consensus::state::document::document_contest_currently_locked_error::DocumentContestCurrentlyLockedError; +use dpp::consensus::state::document::document_contest_identity_already_contestant::DocumentContestIdentityAlreadyContestantError; use dpp::consensus::state::document::document_contest_not_joinable_error::DocumentContestNotJoinableError; use dpp::consensus::state::state_error::StateError; use dpp::data_contract::accessors::v0::DataContractV0Getters; @@ -16,7 +17,9 @@ use dpp::voting::vote_info_storage::contested_document_vote_poll_stored_info::{C use drive::error::drive::DriveError; use drive::query::TransactionArg; use crate::error::Error; -use crate::execution::types::state_transition_execution_context::{StateTransitionExecutionContext}; +use crate::execution::types::execution_operation::ValidationOperation; +use crate::execution::types::state_transition_execution_context::{StateTransitionExecutionContext, StateTransitionExecutionContextMethodsV0}; +use crate::execution::validation::state_transition::documents_batch::state::v0::fetch_contender::fetch_contender; use crate::execution::validation::state_transition::documents_batch::state::v0::fetch_documents::fetch_document_with_id; use crate::platform_types::platform::PlatformStateRef; @@ -37,7 +40,7 @@ impl DocumentCreateTransitionActionStateValidationV0 for DocumentCreateTransitio platform: &PlatformStateRef, owner_id: Identifier, block_info: &BlockInfo, - _execution_context: &mut StateTransitionExecutionContext, + execution_context: &mut StateTransitionExecutionContext, transaction: TransactionArg, platform_version: &PlatformVersion, ) -> Result { @@ -56,7 +59,7 @@ impl DocumentCreateTransitionActionStateValidationV0 for DocumentCreateTransitio // TODO: Use multi get https://github.com/facebook/rocksdb/wiki/MultiGet-Performance // We should check to see if a document already exists in the state - let already_existing_document = fetch_document_with_id( + let (already_existing_document, fee_result) = fetch_document_with_id( platform.drive, contract, document_type, @@ -65,6 +68,8 @@ impl DocumentCreateTransitionActionStateValidationV0 for DocumentCreateTransitio platform_version, )?; + execution_context.add_operation(ValidationOperation::PrecalculatedOperation(fee_result)); + if already_existing_document.is_some() { return Ok(ConsensusValidationResult::new_with_error( ConsensusError::StateError(StateError::DocumentAlreadyPresentError( @@ -126,7 +131,7 @@ impl DocumentCreateTransitionActionStateValidationV0 for DocumentCreateTransitio let time_ms_since_start = block_info.time_ms.checked_sub(start_block.time_ms).ok_or(Error::Drive(drive::error::Error::Drive(DriveError::CorruptedDriveState(format!("it makes no sense that the start block time {} is before our current block time {}", start_block.time_ms, block_info.time_ms)))))?; let join_time_allowed = platform_version.dpp.validation.voting.allow_other_contenders_time_ms; if time_ms_since_start > join_time_allowed { - Ok(SimpleConsensusValidationResult::new_with_error(ConsensusError::StateError(StateError::DocumentContestNotJoinableError( + return Ok(SimpleConsensusValidationResult::new_with_error(ConsensusError::StateError(StateError::DocumentContestNotJoinableError( DocumentContestNotJoinableError::new( contested_document_resource_vote_poll.into(), stored_info.clone(), @@ -134,6 +139,16 @@ impl DocumentCreateTransitionActionStateValidationV0 for DocumentCreateTransitio block_info.time_ms, join_time_allowed, ))))) + } + + // we need to also make sure that we are not already a contestant + + let (maybe_existing_contender, fee_result) = fetch_contender(platform.drive, contested_document_resource_vote_poll, owner_id, block_info, transaction, platform_version)?; + + execution_context.add_operation(ValidationOperation::PrecalculatedOperation(fee_result)); + + if maybe_existing_contender.is_some() { + Ok(SimpleConsensusValidationResult::new_with_error(ConsensusError::StateError(StateError::DocumentContestIdentityAlreadyContestantError(DocumentContestIdentityAlreadyContestantError::new(contested_document_resource_vote_poll.into(), owner_id))))) } else { Ok(SimpleConsensusValidationResult::new()) } diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/documents_batch/action_validation/document_delete_transition_action/state_v0/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/documents_batch/action_validation/document_delete_transition_action/state_v0/mod.rs index ae90496472b..98ce7ed92b8 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/documents_batch/action_validation/document_delete_transition_action/state_v0/mod.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/documents_batch/action_validation/document_delete_transition_action/state_v0/mod.rs @@ -15,7 +15,8 @@ use drive::grovedb::TransactionArg; use drive::state_transition_action::document::documents_batch::document_transition::document_base_transition_action::DocumentBaseTransitionActionAccessorsV0; use drive::state_transition_action::document::documents_batch::document_transition::document_delete_transition_action::v0::DocumentDeleteTransitionActionAccessorsV0; use crate::error::Error; -use crate::execution::types::state_transition_execution_context::StateTransitionExecutionContext; +use crate::execution::types::execution_operation::ValidationOperation; +use crate::execution::types::state_transition_execution_context::{StateTransitionExecutionContext, StateTransitionExecutionContextMethodsV0}; use crate::execution::validation::state_transition::documents_batch::state::v0::fetch_documents::fetch_document_with_id; use crate::platform_types::platform::PlatformStateRef; @@ -36,7 +37,7 @@ impl DocumentDeleteTransitionActionStateValidationV0 for DocumentDeleteTransitio platform: &PlatformStateRef, owner_id: Identifier, _block_info: &BlockInfo, - _execution_context: &mut StateTransitionExecutionContext, + execution_context: &mut StateTransitionExecutionContext, transaction: TransactionArg, platform_version: &PlatformVersion, ) -> Result { @@ -54,7 +55,7 @@ impl DocumentDeleteTransitionActionStateValidationV0 for DocumentDeleteTransitio }; // TODO: Use multi get https://github.com/facebook/rocksdb/wiki/MultiGet-Performance - let original_document = fetch_document_with_id( + let (original_document, fee) = fetch_document_with_id( platform.drive, contract, document_type, @@ -63,6 +64,8 @@ impl DocumentDeleteTransitionActionStateValidationV0 for DocumentDeleteTransitio platform_version, )?; + execution_context.add_operation(ValidationOperation::PrecalculatedOperation(fee)); + let Some(document) = original_document else { return Ok(ConsensusValidationResult::new_with_error( ConsensusError::StateError(StateError::DocumentNotFoundError( diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/documents_batch/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/documents_batch/mod.rs index abc066b643d..fc56ebe512b 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/documents_batch/mod.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/documents_batch/mod.rs @@ -276,13 +276,15 @@ mod tests { use dpp::document::Document; use dpp::document::serialization_traits::DocumentPlatformConversionMethodsV0; use dpp::util::hash::hash_double; + use dpp::util::strings::convert_to_homograph_safe_chars; use dpp::voting::vote_choices::resource_vote_choice::ResourceVoteChoice; use dpp::voting::vote_choices::resource_vote_choice::ResourceVoteChoice::TowardsIdentity; use drive::drive::object_size_info::DataContractResolvedInfo; use drive::drive::votes::resolved::vote_polls::contested_document_resource_vote_poll::ContestedDocumentResourceVotePollWithContractInfoAllowBorrowed; use drive::query::vote_poll_vote_state_query::ContestedDocumentVotePollDriveQueryResultType::DocumentsAndVoteTally; use drive::query::vote_poll_vote_state_query::ResolvedContestedDocumentVotePollDriveQuery; - use crate::execution::validation::state_transition::state_transitions::tests::{add_contender_to_dpns_name_contest, create_dpns_name_contest, fast_forward_to_block, perform_votes_multi}; + use crate::execution::validation::state_transition::state_transitions::tests::{add_contender_to_dpns_name_contest, create_dpns_name_contest, create_dpns_name_contest_give_key_info, fast_forward_to_block, perform_votes_multi}; + use crate::platform_types::platform_state::v0::PlatformStateV0Methods; #[test] fn test_document_creation() { @@ -883,6 +885,92 @@ mod tests { ); } + #[test] + fn test_that_a_contested_document_can_not_be_added_twice_by_the_same_identity() { + let platform_version = PlatformVersion::latest(); + let mut platform = TestPlatformBuilder::new() + .build_with_mock_rpc() + .set_genesis_state(); + + let platform_state = platform.state.load(); + + let ( + ( + _contender_1, + contender_1_signer, + contender_1_key, + _preorder_document_1, + (document_1, entropy), + ), + (_contender_2, _, _, _, _), + dpns_contract, + ) = create_dpns_name_contest_give_key_info( + &mut platform, + &platform_state, + 7, + "quantum", + platform_version, + ); + + let domain = dpns_contract + .document_type_for_name("domain") + .expect("expected a profile document type"); + + let documents_batch_create_transition_1 = + DocumentsBatchTransition::new_document_creation_transition_from_document( + document_1, + domain, + entropy.0, + &contender_1_key, + 4, + 0, + &contender_1_signer, + platform_version, + None, + None, + None, + ) + .expect("expect to create documents batch transition"); + + let documents_batch_create_serialized_transition_1 = + documents_batch_create_transition_1 + .serialize_to_bytes() + .expect("expected documents batch serialized state transition"); + + let transaction = platform.drive.grove.start_transaction(); + + let processing_result = platform + .platform + .process_raw_state_transitions( + &vec![documents_batch_create_serialized_transition_1.clone()], + &platform_state, + &BlockInfo::default_with_time( + &platform_state + .last_committed_block_time_ms() + .unwrap_or_default() + + 3000, + ), + &transaction, + platform_version, + ) + .expect("expected to process state transition"); + + platform + .drive + .grove + .commit_transaction(transaction) + .unwrap() + .expect("expected to commit transaction"); + + let result = processing_result.into_execution_results().remove(0); + + let StateTransitionExecutionResult::PaidConsensusError(consensus_error, _) = result + else { + panic!("expected a paid consensus error"); + }; + assert_eq!(consensus_error.to_string(), "An Identity with the id Fv8S6kTbNrRqKC7PR7XcRUoPR59bxNhhggg5mRaNN6ow is already a contestant for the vote_poll ContestedDocumentResourceVotePoll { contract_id: GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec, document_type_name: domain, index_name: parentNameAndLabel, index_values: [string dash, string quantum] }"); + } + #[test] fn test_that_a_contested_document_can_not_be_added_if_we_are_locked() { let platform_version = PlatformVersion::latest(); diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/documents_batch/state/v0/fetch_contender.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/documents_batch/state/v0/fetch_contender.rs new file mode 100644 index 00000000000..afafbe85b18 --- /dev/null +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/documents_batch/state/v0/fetch_contender.rs @@ -0,0 +1,53 @@ +use crate::error::Error; +use dpp::block::block_info::BlockInfo; +use dpp::fee::fee_result::FeeResult; +use dpp::identifier::Identifier; +use dpp::version::PlatformVersion; +use dpp::voting::contender_structs::ContenderWithSerializedDocument; +use drive::drive::votes::resolved::vote_polls::contested_document_resource_vote_poll::ContestedDocumentResourceVotePollWithContractInfo; +use drive::drive::Drive; +use drive::grovedb::TransactionArg; +use drive::query::vote_poll_vote_state_query::{ + ContestedDocumentVotePollDriveQueryResultType, ResolvedContestedDocumentVotePollDriveQuery, +}; + +pub(crate) fn fetch_contender( + drive: &Drive, + vote_poll: &ContestedDocumentResourceVotePollWithContractInfo, + contender_id: Identifier, + block_info: &BlockInfo, + transaction: TransactionArg, + platform_version: &PlatformVersion, +) -> Result<(Option, FeeResult), Error> { + let contender_query = ResolvedContestedDocumentVotePollDriveQuery { + vote_poll: vote_poll.into(), + result_type: ContestedDocumentVotePollDriveQueryResultType::VoteTally, // Cheaper than anything else + offset: None, + limit: Some(1), + start_at: Some((contender_id.0 .0, true)), + allow_include_locked_and_abstaining_vote_tally: false, + }; + + let mut drive_operations = vec![]; + + let mut result = + contender_query.execute(drive, transaction, &mut drive_operations, platform_version)?; + + let fee = Drive::calculate_fee( + None, + Some(drive_operations), + &block_info.epoch, + drive.config.epochs_per_era, + platform_version, + )?; + match result.contenders.pop() { + None => Ok((None, fee)), + Some(contender) => { + if contender.identity_id() == contender_id { + Ok((Some(contender), fee)) + } else { + Ok((None, fee)) + } + } + } +} diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/documents_batch/state/v0/fetch_documents.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/documents_batch/state/v0/fetch_documents.rs index e61e0bdc37e..73fe085eab7 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/documents_batch/state/v0/fetch_documents.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/documents_batch/state/v0/fetch_documents.rs @@ -12,6 +12,7 @@ use dpp::data_contract::DataContract; use crate::platform_types::platform_state::v0::PlatformStateV0Methods; use dpp::document::Document; +use dpp::fee::fee_result::FeeResult; use dpp::platform_value::{Identifier, Value}; use dpp::state_transition::documents_batch_transition::document_base_transition::v0::v0_methods::DocumentBaseTransitionV0Methods; use dpp::state_transition::documents_batch_transition::document_transition::{ @@ -179,7 +180,7 @@ pub(crate) fn fetch_document_with_id( id: Identifier, transaction: TransactionArg, platform_version: &PlatformVersion, -) -> Result, Error> { +) -> Result<(Option, FeeResult), Error> { let drive_query = DriveQuery { contract, document_type, @@ -202,7 +203,6 @@ pub(crate) fn fetch_document_with_id( block_time_ms: None, }; - //todo: deal with cost of this operation let documents_outcome = drive.query_documents( drive_query, None, @@ -211,11 +211,18 @@ pub(crate) fn fetch_document_with_id( Some(platform_version.protocol_version), )?; + let fee = documents_outcome.cost(); + let fee_result = FeeResult { + storage_fee: 0, + processing_fee: fee, + fee_refunds: Default::default(), + removed_bytes_from_system: 0, + }; let mut documents = documents_outcome.documents_owned(); if documents.is_empty() { - Ok(None) + Ok((None, fee_result)) } else { - Ok(Some(documents.remove(0))) + Ok((Some(documents.remove(0)), fee_result)) } } diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/documents_batch/state/v0/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/documents_batch/state/v0/mod.rs index 408139d6ac6..6844113300e 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/documents_batch/state/v0/mod.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/documents_batch/state/v0/mod.rs @@ -25,6 +25,7 @@ use crate::execution::validation::state_transition::state_transitions::documents use crate::execution::validation::state_transition::ValidationMode; mod data_triggers; +pub mod fetch_contender; pub mod fetch_documents; pub(in crate::execution::validation::state_transition::state_transitions::documents_batch) trait DocumentsBatchStateTransitionStateValidationV0 diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/mod.rs index 6966ee0ae40..31a1f3fe9e6 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/mod.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/mod.rs @@ -276,6 +276,69 @@ mod tests { platform.state.store(Arc::new(platform_state)); } + pub(in crate::execution::validation::state_transition::state_transitions) fn create_dpns_name_contest_give_key_info( + platform: &mut TempPlatform, + platform_state: &PlatformState, + seed: u64, + name: &str, + platform_version: &PlatformVersion, + ) -> ( + ( + Identity, + SimpleSigner, + IdentityPublicKey, + (Document, Bytes32), + (Document, Bytes32), + ), + ( + Identity, + SimpleSigner, + IdentityPublicKey, + (Document, Bytes32), + (Document, Bytes32), + ), + Arc, + ) { + let mut rng = StdRng::seed_from_u64(seed); + + let identity_1_info = setup_identity(platform, rng.gen(), dash_to_credits!(0.5)); + + let identity_2_info = setup_identity(platform, rng.gen(), dash_to_credits!(0.5)); + + let ((preorder_document_1, document_1), (preorder_document_2, document_2), dpns_contract) = + create_dpns_name_contest_on_identities( + platform, + &identity_1_info, + &identity_2_info, + platform_state, + rng, + name, + platform_version, + ); + + let (identity_1, signer_1, identity_key_1) = identity_1_info; + + let (identity_2, signer_2, identity_key_2) = identity_2_info; + + ( + ( + identity_1, + signer_1, + identity_key_1, + preorder_document_1, + document_1, + ), + ( + identity_2, + signer_2, + identity_key_2, + preorder_document_2, + document_2, + ), + dpns_contract, + ) + } + pub(in crate::execution::validation::state_transition::state_transitions) fn create_dpns_name_contest( platform: &mut TempPlatform, platform_state: &PlatformState, @@ -285,18 +348,49 @@ mod tests { ) -> (Identity, Identity, Arc) { let mut rng = StdRng::seed_from_u64(seed); - let (identity_1, signer_1, key_1) = - setup_identity(platform, rng.gen(), dash_to_credits!(0.5)); + let identity_1_info = setup_identity(platform, rng.gen(), dash_to_credits!(0.5)); - let (identity_2, signer_2, key_2) = - setup_identity(platform, rng.gen(), dash_to_credits!(0.5)); + let identity_2_info = setup_identity(platform, rng.gen(), dash_to_credits!(0.5)); + + let (_, _, dpns_contract) = create_dpns_name_contest_on_identities( + platform, + &identity_1_info, + &identity_2_info, + platform_state, + rng, + name, + platform_version, + ); + (identity_1_info.0, identity_2_info.0, dpns_contract) + } + + fn create_dpns_name_contest_on_identities( + platform: &mut TempPlatform, + identity_1: &(Identity, SimpleSigner, IdentityPublicKey), + identity_2: &(Identity, SimpleSigner, IdentityPublicKey), + platform_state: &PlatformState, + mut rng: StdRng, + name: &str, + platform_version: &PlatformVersion, + ) -> ( + ((Document, Bytes32), (Document, Bytes32)), + ((Document, Bytes32), (Document, Bytes32)), + Arc, + ) { + let (identity_1, signer_1, key_1) = identity_1; + + let (identity_2, signer_2, key_2) = identity_2; // Flip them if needed so identity 1 id is always smaller than identity 2 id - let (identity_1, identity_2, signer_1, signer_2, key_1, key_2) = + let (identity_1, identity_2, signer_1, signer_2, key_1, key_2, flipped) = if identity_1.id() < identity_2.id() { - (identity_1, identity_2, signer_1, signer_2, key_1, key_2) + ( + identity_1, identity_2, signer_1, signer_2, key_1, key_2, false, + ) } else { - (identity_2, identity_1, signer_2, signer_1, key_2, key_1) + ( + identity_2, identity_1, signer_2, signer_1, key_2, key_1, true, + ) }; let dpns = platform.drive.cache.system_data_contracts.load_dpns(); @@ -407,13 +501,13 @@ mod tests { let documents_batch_create_preorder_transition_1 = DocumentsBatchTransition::new_document_creation_transition_from_document( - preorder_document_1, + preorder_document_1.clone(), preorder, entropy.0, - &key_1, + key_1, 2, 0, - &signer_1, + signer_1, platform_version, None, None, @@ -428,13 +522,13 @@ mod tests { let documents_batch_create_preorder_transition_2 = DocumentsBatchTransition::new_document_creation_transition_from_document( - preorder_document_2, + preorder_document_2.clone(), preorder, entropy.0, - &key_2, + key_2, 2, 0, - &signer_2, + signer_2, platform_version, None, None, @@ -449,13 +543,13 @@ mod tests { let documents_batch_create_transition_1 = DocumentsBatchTransition::new_document_creation_transition_from_document( - document_1, + document_1.clone(), domain, entropy.0, - &key_1, + key_1, 3, 0, - &signer_1, + signer_1, platform_version, None, None, @@ -469,13 +563,13 @@ mod tests { let documents_batch_create_transition_2 = DocumentsBatchTransition::new_document_creation_transition_from_document( - document_2, + document_2.clone(), domain, entropy.0, - &key_2, + key_2, 3, 0, - &signer_2, + signer_2, platform_version, None, None, @@ -546,7 +640,19 @@ mod tests { .expect("expected to commit transaction"); assert_eq!(processing_result.valid_count(), 2); - (identity_1, identity_2, dpns_contract) + if flipped { + ( + ((preorder_document_2, entropy), (document_2, entropy)), + ((preorder_document_1, entropy), (document_1, entropy)), + dpns_contract, + ) + } else { + ( + ((preorder_document_1, entropy), (document_1, entropy)), + ((preorder_document_2, entropy), (document_2, entropy)), + dpns_contract, + ) + } } pub(in crate::execution::validation::state_transition::state_transitions) fn add_contender_to_dpns_name_contest( diff --git a/packages/rs-drive/src/drive/document/insert_contested/add_contested_document_to_primary_storage/v0/mod.rs b/packages/rs-drive/src/drive/document/insert_contested/add_contested_document_to_primary_storage/v0/mod.rs index 3e86457d2e4..1319199511c 100644 --- a/packages/rs-drive/src/drive/document/insert_contested/add_contested_document_to_primary_storage/v0/mod.rs +++ b/packages/rs-drive/src/drive/document/insert_contested/add_contested_document_to_primary_storage/v0/mod.rs @@ -208,7 +208,7 @@ impl Drive { )?; if !inserted { return Err(Error::Drive(DriveError::CorruptedDocumentAlreadyExists( - "item already exists", + "item already exists in insert contested", ))); } } diff --git a/packages/rs-drive/src/drive/document/insert_contested/add_contested_indices_for_contract_operations/v0/mod.rs b/packages/rs-drive/src/drive/document/insert_contested/add_contested_indices_for_contract_operations/v0/mod.rs index 3acbc353f19..b616b4ade04 100644 --- a/packages/rs-drive/src/drive/document/insert_contested/add_contested_indices_for_contract_operations/v0/mod.rs +++ b/packages/rs-drive/src/drive/document/insert_contested/add_contested_indices_for_contract_operations/v0/mod.rs @@ -261,7 +261,7 @@ impl Drive { RESOURCE_ABSTAIN_VOTE_TREE_KEY_U8_32.to_vec(), ))?; - self.add_contested_vote_subtree_operations( + self.add_contested_vote_subtree_for_non_identities_operations( towards_abstain_index_path_info, storage_flags, estimated_costs_only_with_layer_info, @@ -277,7 +277,7 @@ impl Drive { RESOURCE_LOCK_VOTE_TREE_KEY_U8_32.to_vec(), ))?; - self.add_contested_vote_subtree_operations( + self.add_contested_vote_subtree_for_non_identities_operations( towards_lock_index_path_info, storage_flags, estimated_costs_only_with_layer_info, diff --git a/packages/rs-drive/src/drive/document/insert_contested/add_contested_vote_subtrees_for_non_identities_operations/mod.rs b/packages/rs-drive/src/drive/document/insert_contested/add_contested_vote_subtrees_for_non_identities_operations/mod.rs index 473652ee3fe..957bdcf334e 100644 --- a/packages/rs-drive/src/drive/document/insert_contested/add_contested_vote_subtrees_for_non_identities_operations/mod.rs +++ b/packages/rs-drive/src/drive/document/insert_contested/add_contested_vote_subtrees_for_non_identities_operations/mod.rs @@ -16,7 +16,7 @@ use std::collections::HashMap; impl Drive { /// Adds the contested vote subtree - pub fn add_contested_vote_subtree_operations( + pub fn add_contested_vote_subtree_for_non_identities_operations( &self, index_path_info: PathInfo<0>, storage_flags: Option<&StorageFlags>, @@ -33,7 +33,7 @@ impl Drive { .insert_contested .add_contested_vote_subtree_for_non_identities_operations { - 0 => self.add_contested_vote_subtree_operations_v0( + 0 => self.add_contested_vote_subtree_for_non_identities_operations_v0( index_path_info, storage_flags, estimated_costs_only_with_layer_info, @@ -42,7 +42,7 @@ impl Drive { drive_version, ), version => Err(Error::Drive(DriveError::UnknownVersionMismatch { - method: "add_contested_vote_subtree_operations".to_string(), + method: "add_contested_vote_subtree_for_non_identities_operations".to_string(), known_versions: vec![0], received: version, })), diff --git a/packages/rs-drive/src/drive/document/insert_contested/add_contested_vote_subtrees_for_non_identities_operations/v0/mod.rs b/packages/rs-drive/src/drive/document/insert_contested/add_contested_vote_subtrees_for_non_identities_operations/v0/mod.rs index 7760aa845ce..f0ec958e8a4 100644 --- a/packages/rs-drive/src/drive/document/insert_contested/add_contested_vote_subtrees_for_non_identities_operations/v0/mod.rs +++ b/packages/rs-drive/src/drive/document/insert_contested/add_contested_vote_subtrees_for_non_identities_operations/v0/mod.rs @@ -18,7 +18,7 @@ use std::collections::HashMap; impl Drive { /// Adds the contested vote subtree #[inline(always)] - pub(super) fn add_contested_vote_subtree_operations_v0( + pub(super) fn add_contested_vote_subtree_for_non_identities_operations_v0( &self, index_path_info: PathInfo<0>, storage_flags: Option<&StorageFlags>, @@ -104,7 +104,7 @@ impl Drive { if !inserted { return Err(Error::Drive(DriveError::CorruptedContractIndexes( - "contested votes tree already exists", + "contested votes tree already exists for a non identity (abstain or lock)", ))); } diff --git a/packages/rs-drive/src/drive/object_size_info/contract_info.rs b/packages/rs-drive/src/drive/object_size_info/contract_info.rs index 148706687dc..94ab35b066d 100644 --- a/packages/rs-drive/src/drive/object_size_info/contract_info.rs +++ b/packages/rs-drive/src/drive/object_size_info/contract_info.rs @@ -158,6 +158,19 @@ pub enum DataContractResolvedInfo<'a> { OwnedDataContract(DataContract), } +impl<'a> From<&'a DataContractOwnedResolvedInfo> for DataContractResolvedInfo<'a> { + fn from(value: &'a DataContractOwnedResolvedInfo) -> Self { + match value { + DataContractOwnedResolvedInfo::DataContractFetchInfo(fetch_info) => { + DataContractResolvedInfo::ArcDataContractFetchInfo(fetch_info.clone()) + } + DataContractOwnedResolvedInfo::OwnedDataContract(data_contract) => { + DataContractResolvedInfo::BorrowedDataContract(data_contract) + } + } + } +} + impl<'a> DataContractResolvedInfo<'a> { /// The id of the contract pub fn id(&self) -> Identifier { diff --git a/packages/rs-drive/src/drive/votes/resolved/vote_polls/contested_document_resource_vote_poll/mod.rs b/packages/rs-drive/src/drive/votes/resolved/vote_polls/contested_document_resource_vote_poll/mod.rs index b7f38145654..4722abed8e6 100644 --- a/packages/rs-drive/src/drive/votes/resolved/vote_polls/contested_document_resource_vote_poll/mod.rs +++ b/packages/rs-drive/src/drive/votes/resolved/vote_polls/contested_document_resource_vote_poll/mod.rs @@ -84,6 +84,25 @@ pub struct ContestedDocumentResourceVotePollWithContractInfoAllowBorrowed<'a> { pub index_values: Vec, } +impl<'a> From<&'a ContestedDocumentResourceVotePollWithContractInfo> + for ContestedDocumentResourceVotePollWithContractInfoAllowBorrowed<'a> +{ + fn from(value: &'a ContestedDocumentResourceVotePollWithContractInfo) -> Self { + let ContestedDocumentResourceVotePollWithContractInfo { + contract, + document_type_name, + index_name, + index_values, + } = value; + ContestedDocumentResourceVotePollWithContractInfoAllowBorrowed { + contract: contract.into(), + document_type_name: document_type_name.clone(), + index_name: index_name.clone(), + index_values: index_values.clone(), + } + } +} + impl<'a> From> for ContestedDocumentResourceVotePoll { diff --git a/packages/rs-drive/src/query/vote_poll_vote_state_query.rs b/packages/rs-drive/src/query/vote_poll_vote_state_query.rs index 5056c9ca93b..be47513ecb8 100644 --- a/packages/rs-drive/src/query/vote_poll_vote_state_query.rs +++ b/packages/rs-drive/src/query/vote_poll_vote_state_query.rs @@ -319,58 +319,6 @@ impl ContestedDocumentVotePollDriveQuery { &platform_version.drive, ) } - // - // #[cfg(all(feature = "server", feature = "verify"))] - // /// Executes a query with proof and returns the root hash, items, and fee. - // pub fn execute_with_proof_only_get_elements( - // self, - // drive: &Drive, - // block_info: Option, - // transaction: TransactionArg, - // platform_version: &PlatformVersion, - // ) -> Result<(RootHash, Vec>, u64), Error> { - // let mut drive_operations = vec![]; - // let (root_hash, items) = self.execute_with_proof_only_get_elements_internal( - // drive, - // transaction, - // &mut drive_operations, - // platform_version, - // )?; - // let cost = if let Some(block_info) = block_info { - // let fee_result = Drive::calculate_fee( - // None, - // Some(drive_operations), - // &block_info.epoch, - // drive.config.epochs_per_era, - // platform_version, - // )?; - // fee_result.processing_fee - // } else { - // 0 - // }; - // Ok((root_hash, items, cost)) - // } - // - // #[cfg(all(feature = "server", feature = "verify"))] - // /// Executes an internal query with proof and returns the root hash and values. - // pub(crate) fn execute_with_proof_only_get_elements_internal( - // self, - // drive: &Drive, - // transaction: TransactionArg, - // drive_operations: &mut Vec, - // platform_version: &PlatformVersion, - // ) -> Result<(RootHash, Vec>), Error> { - // let resolved = self.resolve(drive, transaction, platform_version)?; - // let path_query = resolved.construct_path_query(platform_version)?; - // let proof = drive.grove_get_proved_path_query( - // &path_query, - // self.start_at.is_some(), - // transaction, - // drive_operations, - // &platform_version.drive, - // )?; - // self.verify_proof_keep_serialized(proof.as_slice(), platform_version) - // } #[cfg(feature = "server")] /// Executes a query with no proof and returns the items, skipped items, and fee. @@ -409,7 +357,150 @@ impl ContestedDocumentVotePollDriveQuery { platform_version: &PlatformVersion, ) -> Result { let resolved = self.resolve(drive, transaction, platform_version)?; - let path_query = resolved.construct_path_query(platform_version)?; + resolved.execute(drive, transaction, drive_operations, platform_version) + } +} + +/// Vote Poll Drive Query struct +#[derive(Debug, PartialEq, Clone)] +pub struct ResolvedContestedDocumentVotePollDriveQuery<'a> { + /// What vote poll are we asking for? + pub vote_poll: ContestedDocumentResourceVotePollWithContractInfoAllowBorrowed<'a>, + /// What result type are we interested in + pub result_type: ContestedDocumentVotePollDriveQueryResultType, + /// Offset + pub offset: Option, + /// Limit + pub limit: Option, + /// Start at identity id, the bool is if it is also included + pub start_at: Option<([u8; 32], bool)>, + /// Include locked and abstaining vote tally + pub allow_include_locked_and_abstaining_vote_tally: bool, +} + +impl<'a> ResolvedContestedDocumentVotePollDriveQuery<'a> { + /// Operations to construct a path query. + pub fn construct_path_query( + &self, + platform_version: &PlatformVersion, + ) -> Result { + let path = self.vote_poll.contenders_path(platform_version)?; + + let mut query = Query::new(); + + let allow_include_locked_and_abstaining_vote_tally = self + .allow_include_locked_and_abstaining_vote_tally + && self.result_type.has_vote_tally(); + + // We have the following + // Stored Info [[0;31],0] Abstain votes [[0;31],1] Lock Votes [[0;31],2] + + // this is a range on all elements + let limit = + match &self.start_at { + None => { + if allow_include_locked_and_abstaining_vote_tally { + match &self.result_type { + ContestedDocumentVotePollDriveQueryResultType::Documents => { + // Documents don't care about the vote tallies + query.insert_range_after(RESOURCE_LOCK_VOTE_TREE_KEY_U8_32.to_vec()..); + self.limit + } + ContestedDocumentVotePollDriveQueryResultType::VoteTally => { + query.insert_all(); + self.limit.map(|limit| limit.saturating_add(3)) + } + ContestedDocumentVotePollDriveQueryResultType::DocumentsAndVoteTally => { + query.insert_all(); + self.limit.map(|limit| limit.saturating_mul(2).saturating_add(3)) + } + } + } else { + match &self.result_type { + ContestedDocumentVotePollDriveQueryResultType::Documents => { + query.insert_range_after(RESOURCE_LOCK_VOTE_TREE_KEY_U8_32.to_vec()..); + self.limit + } + ContestedDocumentVotePollDriveQueryResultType::VoteTally => { + query.insert_key(RESOURCE_STORED_INFO_KEY_U8_32.to_vec()); + query.insert_range_after(RESOURCE_LOCK_VOTE_TREE_KEY_U8_32.to_vec()..); + self.limit.map(|limit| limit.saturating_add(1)) + } + ContestedDocumentVotePollDriveQueryResultType::DocumentsAndVoteTally => { + query.insert_key(RESOURCE_STORED_INFO_KEY_U8_32.to_vec()); + query.insert_range_after(RESOURCE_LOCK_VOTE_TREE_KEY_U8_32.to_vec()..); + self.limit.map(|limit| limit.saturating_mul(2).saturating_add(1)) + } + } + } + } + Some((starts_at_key_bytes, start_at_included)) => { + let starts_at_key = starts_at_key_bytes.to_vec(); + match start_at_included { + true => query.insert_range_from(starts_at_key..), + false => query.insert_range_after(starts_at_key..), + } + match &self.result_type { + ContestedDocumentVotePollDriveQueryResultType::Documents + | ContestedDocumentVotePollDriveQueryResultType::VoteTally => self.limit, + ContestedDocumentVotePollDriveQueryResultType::DocumentsAndVoteTally => { + self.limit.map(|limit| limit.saturating_mul(2)) + } + } + } + }; + + let (subquery_path, subquery) = match self.result_type { + ContestedDocumentVotePollDriveQueryResultType::Documents => (Some(vec![vec![0]]), None), + ContestedDocumentVotePollDriveQueryResultType::VoteTally => (Some(vec![vec![1]]), None), + ContestedDocumentVotePollDriveQueryResultType::DocumentsAndVoteTally => { + let mut query = Query::new(); + query.insert_keys(vec![vec![0], vec![1]]); + (None, Some(query.into())) + } + }; + + query.default_subquery_branch.subquery_path = subquery_path; + query.default_subquery_branch.subquery = subquery; + + if allow_include_locked_and_abstaining_vote_tally { + query.add_conditional_subquery( + QueryItem::Key(RESOURCE_LOCK_VOTE_TREE_KEY_U8_32.to_vec()), + Some(vec![vec![1]]), + None, + ); + query.add_conditional_subquery( + QueryItem::Key(RESOURCE_ABSTAIN_VOTE_TREE_KEY_U8_32.to_vec()), + Some(vec![vec![1]]), + None, + ); + } + + query.add_conditional_subquery( + QueryItem::Key(RESOURCE_STORED_INFO_KEY_U8_32.to_vec()), + None, + None, + ); + + Ok(PathQuery { + path, + query: SizedQuery { + query, + limit, + offset: self.offset, + }, + }) + } + + /// Executes the query with no proof + pub fn execute( + &self, + drive: &Drive, + transaction: TransactionArg, + drive_operations: &mut Vec, + platform_version: &PlatformVersion, + ) -> Result { + let path_query = self.construct_path_query(platform_version)?; // println!("path_query {:?}", &path_query); let query_result = drive.grove_get_path_query( &path_query, @@ -581,9 +672,9 @@ impl ContestedDocumentVotePollDriveQuery { Element::SumTree(_, sum_tree_value, _) => { if sum_tree_value < 0 || sum_tree_value > u32::MAX as i64 { return Err(Error::Drive(DriveError::CorruptedDriveState(format!( - "sum tree value for vote tally must be between 0 and u32::Max, received {} from state", - sum_tree_value - )))); + "sum tree value for vote tally must be between 0 and u32::Max, received {} from state", + sum_tree_value + )))); } if identity_bytes.as_slice() @@ -629,16 +720,16 @@ impl ContestedDocumentVotePollDriveQuery { ))?, ); winner = Some(( - finalized_contested_document_vote_poll_stored_info.winner(), - finalized_contested_document_vote_poll_stored_info - .last_finalization_block().ok_or(Error::Drive(DriveError::CorruptedDriveState( - "we should have a last finalization block".to_string(), - )))?, - )); + finalized_contested_document_vote_poll_stored_info.winner(), + finalized_contested_document_vote_poll_stored_info + .last_finalization_block().ok_or(Error::Drive(DriveError::CorruptedDriveState( + "we should have a last finalization block".to_string(), + )))?, + )); contenders = finalized_contested_document_vote_poll_stored_info - .contender_votes_in_vec_of_contender_with_serialized_document().ok_or(Error::Drive(DriveError::CorruptedDriveState( - "we should have a last contender votes".to_string(), - )))?; + .contender_votes_in_vec_of_contender_with_serialized_document().ok_or(Error::Drive(DriveError::CorruptedDriveState( + "we should have a last contender votes".to_string(), + )))?; } } else { // We should find a sum tree paired with this document @@ -656,9 +747,9 @@ impl ContestedDocumentVotePollDriveQuery { || sum_tree_value > u32::MAX as i64 { return Err(Error::Drive(DriveError::CorruptedDriveState(format!( - "sum tree value for vote tally must be between 0 and u32::Max, received {} from state", - sum_tree_value - )))); + "sum tree value for vote tally must be between 0 and u32::Max, received {} from state", + sum_tree_value + )))); } let identity_id = @@ -700,171 +791,4 @@ impl ContestedDocumentVotePollDriveQuery { } } } - - #[cfg(feature = "server")] - #[allow(unused)] - /// Executes an internal query with no proof and returns the values and skipped items. - pub(crate) fn execute_no_proof_internal( - &self, - drive: &Drive, - result_type: QueryResultType, - transaction: TransactionArg, - drive_operations: &mut Vec, - platform_version: &PlatformVersion, - ) -> Result<(QueryResultElements, u16), Error> { - let resolved = self.resolve(drive, transaction, platform_version)?; - let path_query = resolved.construct_path_query(platform_version)?; - let query_result = drive.grove_get_path_query( - &path_query, - transaction, - result_type, - drive_operations, - &platform_version.drive, - ); - match query_result { - Err(Error::GroveDB(GroveError::PathKeyNotFound(_))) - | Err(Error::GroveDB(GroveError::PathNotFound(_))) - | Err(Error::GroveDB(GroveError::PathParentLayerNotFound(_))) => { - Ok((QueryResultElements::new(), 0)) - } - _ => { - let (data, skipped) = query_result?; - { - Ok((data, skipped)) - } - } - } - } -} - -/// Vote Poll Drive Query struct -#[derive(Debug, PartialEq, Clone)] -pub struct ResolvedContestedDocumentVotePollDriveQuery<'a> { - /// What vote poll are we asking for? - pub vote_poll: ContestedDocumentResourceVotePollWithContractInfoAllowBorrowed<'a>, - /// What result type are we interested in - pub result_type: ContestedDocumentVotePollDriveQueryResultType, - /// Offset - pub offset: Option, - /// Limit - pub limit: Option, - /// Start at identity id, the bool is if it is also included - pub start_at: Option<([u8; 32], bool)>, - /// Include locked and abstaining vote tally - pub allow_include_locked_and_abstaining_vote_tally: bool, -} - -impl<'a> ResolvedContestedDocumentVotePollDriveQuery<'a> { - /// Operations to construct a path query. - pub fn construct_path_query( - &self, - platform_version: &PlatformVersion, - ) -> Result { - let path = self.vote_poll.contenders_path(platform_version)?; - - let mut query = Query::new(); - - let allow_include_locked_and_abstaining_vote_tally = self - .allow_include_locked_and_abstaining_vote_tally - && self.result_type.has_vote_tally(); - - // We have the following - // Stored Info [[0;31],0] Abstain votes [[0;31],1] Lock Votes [[0;31],2] - - // this is a range on all elements - let limit = - match &self.start_at { - None => { - if allow_include_locked_and_abstaining_vote_tally { - match &self.result_type { - ContestedDocumentVotePollDriveQueryResultType::Documents => { - // Documents don't care about the vote tallies - query.insert_range_after(RESOURCE_LOCK_VOTE_TREE_KEY_U8_32.to_vec()..); - self.limit - } - ContestedDocumentVotePollDriveQueryResultType::VoteTally => { - query.insert_all(); - self.limit.map(|limit| limit.saturating_add(3)) - } - ContestedDocumentVotePollDriveQueryResultType::DocumentsAndVoteTally => { - query.insert_all(); - self.limit.map(|limit| limit.saturating_mul(2).saturating_add(3)) - } - } - } else { - match &self.result_type { - ContestedDocumentVotePollDriveQueryResultType::Documents => { - query.insert_range_after(RESOURCE_LOCK_VOTE_TREE_KEY_U8_32.to_vec()..); - self.limit - } - ContestedDocumentVotePollDriveQueryResultType::VoteTally => { - query.insert_key(RESOURCE_STORED_INFO_KEY_U8_32.to_vec()); - query.insert_range_after(RESOURCE_LOCK_VOTE_TREE_KEY_U8_32.to_vec()..); - self.limit.map(|limit| limit.saturating_add(1)) - } - ContestedDocumentVotePollDriveQueryResultType::DocumentsAndVoteTally => { - query.insert_key(RESOURCE_STORED_INFO_KEY_U8_32.to_vec()); - query.insert_range_after(RESOURCE_LOCK_VOTE_TREE_KEY_U8_32.to_vec()..); - self.limit.map(|limit| limit.saturating_mul(2).saturating_add(1)) - } - } - } - } - Some((starts_at_key_bytes, start_at_included)) => { - let starts_at_key = starts_at_key_bytes.to_vec(); - match start_at_included { - true => query.insert_range_from(starts_at_key..), - false => query.insert_range_after(starts_at_key..), - } - match &self.result_type { - ContestedDocumentVotePollDriveQueryResultType::Documents - | ContestedDocumentVotePollDriveQueryResultType::VoteTally => self.limit, - ContestedDocumentVotePollDriveQueryResultType::DocumentsAndVoteTally => { - self.limit.map(|limit| limit.saturating_mul(2)) - } - } - } - }; - - let (subquery_path, subquery) = match self.result_type { - ContestedDocumentVotePollDriveQueryResultType::Documents => (Some(vec![vec![0]]), None), - ContestedDocumentVotePollDriveQueryResultType::VoteTally => (Some(vec![vec![1]]), None), - ContestedDocumentVotePollDriveQueryResultType::DocumentsAndVoteTally => { - let mut query = Query::new(); - query.insert_keys(vec![vec![0], vec![1]]); - (None, Some(query.into())) - } - }; - - query.default_subquery_branch.subquery_path = subquery_path; - query.default_subquery_branch.subquery = subquery; - - if allow_include_locked_and_abstaining_vote_tally { - query.add_conditional_subquery( - QueryItem::Key(RESOURCE_LOCK_VOTE_TREE_KEY_U8_32.to_vec()), - Some(vec![vec![1]]), - None, - ); - query.add_conditional_subquery( - QueryItem::Key(RESOURCE_ABSTAIN_VOTE_TREE_KEY_U8_32.to_vec()), - Some(vec![vec![1]]), - None, - ); - } - - query.add_conditional_subquery( - QueryItem::Key(RESOURCE_STORED_INFO_KEY_U8_32.to_vec()), - None, - None, - ); - - Ok(PathQuery { - path, - query: SizedQuery { - query, - limit, - offset: self.offset, - }, - }) - } } diff --git a/packages/wasm-dpp/src/errors/consensus/consensus_error.rs b/packages/wasm-dpp/src/errors/consensus/consensus_error.rs index 39ffb2896df..43ce0566371 100644 --- a/packages/wasm-dpp/src/errors/consensus/consensus_error.rs +++ b/packages/wasm-dpp/src/errors/consensus/consensus_error.rs @@ -67,6 +67,7 @@ use dpp::consensus::basic::identity::{DataContractBoundsNotPresentError, Disabli use dpp::consensus::basic::overflow_error::OverflowError; use dpp::consensus::state::data_contract::document_type_update_error::DocumentTypeUpdateError; use dpp::consensus::state::document::document_contest_currently_locked_error::DocumentContestCurrentlyLockedError; +use dpp::consensus::state::document::document_contest_identity_already_contestant::DocumentContestIdentityAlreadyContestantError; use dpp::consensus::state::document::document_contest_not_joinable_error::DocumentContestNotJoinableError; use dpp::consensus::state::document::document_incorrect_purchase_price_error::DocumentIncorrectPurchasePriceError; use dpp::consensus::state::document::document_not_for_sale_error::DocumentNotForSaleError; @@ -270,6 +271,9 @@ pub fn from_state_error(state_error: &StateError) -> JsValue { StateError::DocumentContestNotJoinableError(e) => { generic_consensus_error!(DocumentContestNotJoinableError, e).into() } + StateError::DocumentContestIdentityAlreadyContestantError(e) => { + generic_consensus_error!(DocumentContestIdentityAlreadyContestantError, e).into() + } StateError::VotePollNotFoundError(e) => { generic_consensus_error!(VotePollNotFoundError, e).into() } From 412fe966c1f671b5db53e544c4d47b82dbff9648 Mon Sep 17 00:00:00 2001 From: Quantum Explorer Date: Thu, 4 Jul 2024 03:33:48 +0700 Subject: [PATCH 52/55] fixes --- .../state_transitions/documents_batch/mod.rs | 4 +- .../state_transition/state_transitions/mod.rs | 54 ++++++++++--------- .../src/query/vote_poll_vote_state_query.rs | 1 + 3 files changed, 32 insertions(+), 27 deletions(-) diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/documents_batch/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/documents_batch/mod.rs index fc56ebe512b..e087c82d800 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/documents_batch/mod.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/documents_batch/mod.rs @@ -968,7 +968,7 @@ mod tests { else { panic!("expected a paid consensus error"); }; - assert_eq!(consensus_error.to_string(), "An Identity with the id Fv8S6kTbNrRqKC7PR7XcRUoPR59bxNhhggg5mRaNN6ow is already a contestant for the vote_poll ContestedDocumentResourceVotePoll { contract_id: GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec, document_type_name: domain, index_name: parentNameAndLabel, index_values: [string dash, string quantum] }"); + assert_eq!(consensus_error.to_string(), "An Identity with the id BjNejy4r9QAvLHpQ9Yq6yRMgNymeGZ46d48fJxJbMrfW is already a contestant for the vote_poll ContestedDocumentResourceVotePoll { contract_id: GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec, document_type_name: domain, index_name: parentNameAndLabel, index_values: [string dash, string quantum] }"); } #[test] @@ -1051,7 +1051,7 @@ mod tests { &platform_state, 9, "quantum", - Some("Document Contest for vote_poll ContestedDocumentResourceVotePoll { contract_id: GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec, document_type_name: domain, index_name: parentNameAndLabel, index_values: [string dash, string quantum] } is currently already locked V0(ContestedDocumentVotePollStoredInfoV0 { finalized_events: [ContestedDocumentVotePollStoredInfoVoteEventV0 { resource_vote_choices: [FinalizedResourceVoteChoicesWithVoterInfo { resource_vote_choice: TowardsIdentity(BjNejy4r9QAvLHpQ9Yq6yRMgNymeGZ46d48fJxJbMrfW), voters: [2oGomAQc47V9h3mkpyHUPbF74gT2AmoYKg1oSb94Rbwm, 4iroeiNBeBYZetCt21kW7FGyczE8WqoqzZ48YAHwyV7R, Cdf8V4KGHHd395x5xPJPPrzTKwmp5MqbuszSE2iMzzeP] }, FinalizedResourceVoteChoicesWithVoterInfo { resource_vote_choice: TowardsIdentity(FiLk5pGtspYtF65PKsQq3YFr1DEiXPHTZeKjusT6DuqN), voters: [] }, FinalizedResourceVoteChoicesWithVoterInfo { resource_vote_choice: TowardsIdentity(Fv8S6kTbNrRqKC7PR7XcRUoPR59bxNhhggg5mRaNN6ow), voters: [4MK8GWEWX1PturUqjZJefdE4WGrUqz1UQZnbK17ENkeA, 5gRudU7b4n8LYkNvhZomv6FtMrP7gvaTvRrHKfaTS22K, AfzQBrdwzDuTVdXrMWqQyVvXRWqPMDVjA76hViuGLh6W, E75wdFZB22P1uW1wJBJGPgXZuZKLotK7YmbH5wUk5msH, G3ZfS2v39x6FuLGnnJ1RNQyy4zn4Wb64KiGAjqj39wUu] }, FinalizedResourceVoteChoicesWithVoterInfo { resource_vote_choice: Abstain, voters: [5Ur8tDxJnatfUd9gcVFDde7ptHydujZzJLNTxa6aMYYy, 93Gsg14oT9K4FLYmC7N26uS4g5b7JcM1GwGEDeJCCBPJ, 96eX4PTjbXRuGHuMzwXdptWFtHcboXbtevk51Jd73pP7, AE9xm2mbemDeMxPUzyt35Agq1axRxggVfV4DRLAZp7Qt, FbLyu5d7JxEsvSsujj7Wopg57Wrvz9HH3UULCusKpBnF, GsubMWb3LH1skUJrcxTmZ7wus1habJcbpb8su8yBVqFY, H9UrL7aWaxDmXhqeGMJy7LrGdT2wWb45mc7kQYsoqwuf, Hv88mzPZVKq2fnjoUqK56vjzkcmqRHpWE1ME4z1MXDrw] }, FinalizedResourceVoteChoicesWithVoterInfo { resource_vote_choice: Lock, voters: [F1oA8iAoyJ8dgCAi2GSPqcNhp9xEuAqhP47yXBDw5QR, 2YSjsJUp74MJpm12rdn8wyPR5MY3c322pV8E8siw989u, 3fQrmN4PWhthUFnCFTaJqbT2PPGf7MytAyik4eY1DP8V, 7r7gnAiZunVLjtSd5ky4yvPpnWTFYbJuQAapg8kDCeNK, 86TUE89xNkBDcmshXRD198xjAvMmKecvHbwo6i83AmqA, 97iYr4cirPdG176kqa5nvJWT9tsnqxHmENfRnZUgM6SC, 99nKfYZL4spsTe9p9pPNhc1JWv9yq4CbPPMPm87a5sgn, BYAqFxCVwMKrw5YAQMCFQGiAF2v3YhKRm2EdGfgkYN9G, CGKeK3AfdZUxXF3qH9zxp5MR7Z4WvDVqMrU5wjMKqT5C, HRPPEX4mdoZAMkg6NLJUgDzN4pSTpiDXEAGcR5JBdiXX] }], start_block: BlockInfo { time_ms: 3000, height: 0, core_height: 0, epoch: 0 }, finalization_block: BlockInfo { time_ms: 2000000000, height: 900, core_height: 42, epoch: 0 }, winner: Locked }], vote_poll_status: Locked, locked_count: 1 }), unlocking is possible by paying 400000000000 credits"), // this should fail, as it is locked + Some("Document Contest for vote_poll ContestedDocumentResourceVotePoll { contract_id: GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec, document_type_name: domain, index_name: parentNameAndLabel, index_values: [string dash, string quantum] } is currently already locked V0(ContestedDocumentVotePollStoredInfoV0 { finalized_events: [ContestedDocumentVotePollStoredInfoVoteEventV0 { resource_vote_choices: [FinalizedResourceVoteChoicesWithVoterInfo { resource_vote_choice: TowardsIdentity(BjNejy4r9QAvLHpQ9Yq6yRMgNymeGZ46d48fJxJbMrfW), voters: [2oGomAQc47V9h3mkpyHUPbF74gT2AmoYKg1oSb94Rbwm:1, 4iroeiNBeBYZetCt21kW7FGyczE8WqoqzZ48YAHwyV7R:1, Cdf8V4KGHHd395x5xPJPPrzTKwmp5MqbuszSE2iMzzeP:1] }, FinalizedResourceVoteChoicesWithVoterInfo { resource_vote_choice: TowardsIdentity(FiLk5pGtspYtF65PKsQq3YFr1DEiXPHTZeKjusT6DuqN), voters: [] }, FinalizedResourceVoteChoicesWithVoterInfo { resource_vote_choice: TowardsIdentity(Fv8S6kTbNrRqKC7PR7XcRUoPR59bxNhhggg5mRaNN6ow), voters: [4MK8GWEWX1PturUqjZJefdE4WGrUqz1UQZnbK17ENkeA:1, 5gRudU7b4n8LYkNvhZomv6FtMrP7gvaTvRrHKfaTS22K:1, AfzQBrdwzDuTVdXrMWqQyVvXRWqPMDVjA76hViuGLh6W:1, E75wdFZB22P1uW1wJBJGPgXZuZKLotK7YmbH5wUk5msH:1, G3ZfS2v39x6FuLGnnJ1RNQyy4zn4Wb64KiGAjqj39wUu:1] }, FinalizedResourceVoteChoicesWithVoterInfo { resource_vote_choice: Abstain, voters: [5Ur8tDxJnatfUd9gcVFDde7ptHydujZzJLNTxa6aMYYy:1, 93Gsg14oT9K4FLYmC7N26uS4g5b7JcM1GwGEDeJCCBPJ:1, 96eX4PTjbXRuGHuMzwXdptWFtHcboXbtevk51Jd73pP7:1, AE9xm2mbemDeMxPUzyt35Agq1axRxggVfV4DRLAZp7Qt:1, FbLyu5d7JxEsvSsujj7Wopg57Wrvz9HH3UULCusKpBnF:1, GsubMWb3LH1skUJrcxTmZ7wus1habJcbpb8su8yBVqFY:1, H9UrL7aWaxDmXhqeGMJy7LrGdT2wWb45mc7kQYsoqwuf:1, Hv88mzPZVKq2fnjoUqK56vjzkcmqRHpWE1ME4z1MXDrw:1] }, FinalizedResourceVoteChoicesWithVoterInfo { resource_vote_choice: Lock, voters: [F1oA8iAoyJ8dgCAi2GSPqcNhp9xEuAqhP47yXBDw5QR:1, 2YSjsJUp74MJpm12rdn8wyPR5MY3c322pV8E8siw989u:1, 3fQrmN4PWhthUFnCFTaJqbT2PPGf7MytAyik4eY1DP8V:1, 7r7gnAiZunVLjtSd5ky4yvPpnWTFYbJuQAapg8kDCeNK:1, 86TUE89xNkBDcmshXRD198xjAvMmKecvHbwo6i83AmqA:1, 97iYr4cirPdG176kqa5nvJWT9tsnqxHmENfRnZUgM6SC:1, 99nKfYZL4spsTe9p9pPNhc1JWv9yq4CbPPMPm87a5sgn:1, BYAqFxCVwMKrw5YAQMCFQGiAF2v3YhKRm2EdGfgkYN9G:1, CGKeK3AfdZUxXF3qH9zxp5MR7Z4WvDVqMrU5wjMKqT5C:1, HRPPEX4mdoZAMkg6NLJUgDzN4pSTpiDXEAGcR5JBdiXX:1] }], start_block: BlockInfo { time_ms: 3000, height: 0, core_height: 0, epoch: 0 }, finalization_block: BlockInfo { time_ms: 2000000000, height: 900, core_height: 42, epoch: 0 }, winner: Locked }], vote_poll_status: Locked, locked_count: 1 }), unlocking is possible by paying 400000000000 credits"), // this should fail, as it is locked platform_version, ); } diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/mod.rs index 31a1f3fe9e6..4abe57681af 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/mod.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/mod.rs @@ -305,6 +305,18 @@ mod tests { let identity_2_info = setup_identity(platform, rng.gen(), dash_to_credits!(0.5)); + // Flip them if needed so identity 1 id is always smaller than identity 2 id + let (identity_1_info, identity_2_info) = + if identity_1_info.0.id() < identity_2_info.0.id() { + ( + identity_1_info, identity_2_info, + ) + } else { + ( + identity_2_info, identity_1_info, + ) + }; + let ((preorder_document_1, document_1), (preorder_document_2, document_2), dpns_contract) = create_dpns_name_contest_on_identities( platform, @@ -352,6 +364,18 @@ mod tests { let identity_2_info = setup_identity(platform, rng.gen(), dash_to_credits!(0.5)); + // Flip them if needed so identity 1 id is always smaller than identity 2 id + let (identity_1_info, identity_2_info) = + if identity_1_info.0.id() < identity_2_info.0.id() { + ( + identity_1_info, identity_2_info, + ) + } else { + ( + identity_2_info, identity_1_info, + ) + }; + let (_, _, dpns_contract) = create_dpns_name_contest_on_identities( platform, &identity_1_info, @@ -381,18 +405,6 @@ mod tests { let (identity_2, signer_2, key_2) = identity_2; - // Flip them if needed so identity 1 id is always smaller than identity 2 id - let (identity_1, identity_2, signer_1, signer_2, key_1, key_2, flipped) = - if identity_1.id() < identity_2.id() { - ( - identity_1, identity_2, signer_1, signer_2, key_1, key_2, false, - ) - } else { - ( - identity_2, identity_1, signer_2, signer_1, key_2, key_1, true, - ) - }; - let dpns = platform.drive.cache.system_data_contracts.load_dpns(); let dpns_contract = dpns.clone(); @@ -640,19 +652,11 @@ mod tests { .expect("expected to commit transaction"); assert_eq!(processing_result.valid_count(), 2); - if flipped { - ( - ((preorder_document_2, entropy), (document_2, entropy)), - ((preorder_document_1, entropy), (document_1, entropy)), - dpns_contract, - ) - } else { - ( - ((preorder_document_1, entropy), (document_1, entropy)), - ((preorder_document_2, entropy), (document_2, entropy)), - dpns_contract, - ) - } + ( + ((preorder_document_1, entropy), (document_1, entropy)), + ((preorder_document_2, entropy), (document_2, entropy)), + dpns_contract, + ) } pub(in crate::execution::validation::state_transition::state_transitions) fn add_contender_to_dpns_name_contest( diff --git a/packages/rs-drive/src/query/vote_poll_vote_state_query.rs b/packages/rs-drive/src/query/vote_poll_vote_state_query.rs index be47513ecb8..2ea75252110 100644 --- a/packages/rs-drive/src/query/vote_poll_vote_state_query.rs +++ b/packages/rs-drive/src/query/vote_poll_vote_state_query.rs @@ -492,6 +492,7 @@ impl<'a> ResolvedContestedDocumentVotePollDriveQuery<'a> { }) } + #[cfg(feature = "server")] /// Executes the query with no proof pub fn execute( &self, From 98513a9526447c9fcc7edbc1648ee424f7fa5629 Mon Sep 17 00:00:00 2001 From: Quantum Explorer Date: Thu, 4 Jul 2024 03:38:13 +0700 Subject: [PATCH 53/55] small fix --- .../state_transition/state_transitions/mod.rs | 32 +++++++------------ .../drive/object_size_info/contract_info.rs | 1 + 2 files changed, 13 insertions(+), 20 deletions(-) diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/mod.rs index 4abe57681af..bd22d4c8956 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/mod.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/mod.rs @@ -306,16 +306,12 @@ mod tests { let identity_2_info = setup_identity(platform, rng.gen(), dash_to_credits!(0.5)); // Flip them if needed so identity 1 id is always smaller than identity 2 id - let (identity_1_info, identity_2_info) = - if identity_1_info.0.id() < identity_2_info.0.id() { - ( - identity_1_info, identity_2_info, - ) - } else { - ( - identity_2_info, identity_1_info, - ) - }; + let (identity_1_info, identity_2_info) = if identity_1_info.0.id() < identity_2_info.0.id() + { + (identity_1_info, identity_2_info) + } else { + (identity_2_info, identity_1_info) + }; let ((preorder_document_1, document_1), (preorder_document_2, document_2), dpns_contract) = create_dpns_name_contest_on_identities( @@ -365,16 +361,12 @@ mod tests { let identity_2_info = setup_identity(platform, rng.gen(), dash_to_credits!(0.5)); // Flip them if needed so identity 1 id is always smaller than identity 2 id - let (identity_1_info, identity_2_info) = - if identity_1_info.0.id() < identity_2_info.0.id() { - ( - identity_1_info, identity_2_info, - ) - } else { - ( - identity_2_info, identity_1_info, - ) - }; + let (identity_1_info, identity_2_info) = if identity_1_info.0.id() < identity_2_info.0.id() + { + (identity_1_info, identity_2_info) + } else { + (identity_2_info, identity_1_info) + }; let (_, _, dpns_contract) = create_dpns_name_contest_on_identities( platform, diff --git a/packages/rs-drive/src/drive/object_size_info/contract_info.rs b/packages/rs-drive/src/drive/object_size_info/contract_info.rs index 94ab35b066d..ca1e72081ac 100644 --- a/packages/rs-drive/src/drive/object_size_info/contract_info.rs +++ b/packages/rs-drive/src/drive/object_size_info/contract_info.rs @@ -161,6 +161,7 @@ pub enum DataContractResolvedInfo<'a> { impl<'a> From<&'a DataContractOwnedResolvedInfo> for DataContractResolvedInfo<'a> { fn from(value: &'a DataContractOwnedResolvedInfo) -> Self { match value { + #[cfg(feature = "server")] DataContractOwnedResolvedInfo::DataContractFetchInfo(fetch_info) => { DataContractResolvedInfo::ArcDataContractFetchInfo(fetch_info.clone()) } From 5629357b5668376171db72c958a46a1a1d196852 Mon Sep 17 00:00:00 2001 From: Quantum Explorer Date: Thu, 4 Jul 2024 03:33:48 +0700 Subject: [PATCH 54/55] fixes --- .../state_transitions/documents_batch/mod.rs | 4 +- .../state_transition/state_transitions/mod.rs | 54 ++++++++++--------- .../src/query/vote_poll_vote_state_query.rs | 1 + 3 files changed, 32 insertions(+), 27 deletions(-) diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/documents_batch/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/documents_batch/mod.rs index fc56ebe512b..e087c82d800 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/documents_batch/mod.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/documents_batch/mod.rs @@ -968,7 +968,7 @@ mod tests { else { panic!("expected a paid consensus error"); }; - assert_eq!(consensus_error.to_string(), "An Identity with the id Fv8S6kTbNrRqKC7PR7XcRUoPR59bxNhhggg5mRaNN6ow is already a contestant for the vote_poll ContestedDocumentResourceVotePoll { contract_id: GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec, document_type_name: domain, index_name: parentNameAndLabel, index_values: [string dash, string quantum] }"); + assert_eq!(consensus_error.to_string(), "An Identity with the id BjNejy4r9QAvLHpQ9Yq6yRMgNymeGZ46d48fJxJbMrfW is already a contestant for the vote_poll ContestedDocumentResourceVotePoll { contract_id: GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec, document_type_name: domain, index_name: parentNameAndLabel, index_values: [string dash, string quantum] }"); } #[test] @@ -1051,7 +1051,7 @@ mod tests { &platform_state, 9, "quantum", - Some("Document Contest for vote_poll ContestedDocumentResourceVotePoll { contract_id: GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec, document_type_name: domain, index_name: parentNameAndLabel, index_values: [string dash, string quantum] } is currently already locked V0(ContestedDocumentVotePollStoredInfoV0 { finalized_events: [ContestedDocumentVotePollStoredInfoVoteEventV0 { resource_vote_choices: [FinalizedResourceVoteChoicesWithVoterInfo { resource_vote_choice: TowardsIdentity(BjNejy4r9QAvLHpQ9Yq6yRMgNymeGZ46d48fJxJbMrfW), voters: [2oGomAQc47V9h3mkpyHUPbF74gT2AmoYKg1oSb94Rbwm, 4iroeiNBeBYZetCt21kW7FGyczE8WqoqzZ48YAHwyV7R, Cdf8V4KGHHd395x5xPJPPrzTKwmp5MqbuszSE2iMzzeP] }, FinalizedResourceVoteChoicesWithVoterInfo { resource_vote_choice: TowardsIdentity(FiLk5pGtspYtF65PKsQq3YFr1DEiXPHTZeKjusT6DuqN), voters: [] }, FinalizedResourceVoteChoicesWithVoterInfo { resource_vote_choice: TowardsIdentity(Fv8S6kTbNrRqKC7PR7XcRUoPR59bxNhhggg5mRaNN6ow), voters: [4MK8GWEWX1PturUqjZJefdE4WGrUqz1UQZnbK17ENkeA, 5gRudU7b4n8LYkNvhZomv6FtMrP7gvaTvRrHKfaTS22K, AfzQBrdwzDuTVdXrMWqQyVvXRWqPMDVjA76hViuGLh6W, E75wdFZB22P1uW1wJBJGPgXZuZKLotK7YmbH5wUk5msH, G3ZfS2v39x6FuLGnnJ1RNQyy4zn4Wb64KiGAjqj39wUu] }, FinalizedResourceVoteChoicesWithVoterInfo { resource_vote_choice: Abstain, voters: [5Ur8tDxJnatfUd9gcVFDde7ptHydujZzJLNTxa6aMYYy, 93Gsg14oT9K4FLYmC7N26uS4g5b7JcM1GwGEDeJCCBPJ, 96eX4PTjbXRuGHuMzwXdptWFtHcboXbtevk51Jd73pP7, AE9xm2mbemDeMxPUzyt35Agq1axRxggVfV4DRLAZp7Qt, FbLyu5d7JxEsvSsujj7Wopg57Wrvz9HH3UULCusKpBnF, GsubMWb3LH1skUJrcxTmZ7wus1habJcbpb8su8yBVqFY, H9UrL7aWaxDmXhqeGMJy7LrGdT2wWb45mc7kQYsoqwuf, Hv88mzPZVKq2fnjoUqK56vjzkcmqRHpWE1ME4z1MXDrw] }, FinalizedResourceVoteChoicesWithVoterInfo { resource_vote_choice: Lock, voters: [F1oA8iAoyJ8dgCAi2GSPqcNhp9xEuAqhP47yXBDw5QR, 2YSjsJUp74MJpm12rdn8wyPR5MY3c322pV8E8siw989u, 3fQrmN4PWhthUFnCFTaJqbT2PPGf7MytAyik4eY1DP8V, 7r7gnAiZunVLjtSd5ky4yvPpnWTFYbJuQAapg8kDCeNK, 86TUE89xNkBDcmshXRD198xjAvMmKecvHbwo6i83AmqA, 97iYr4cirPdG176kqa5nvJWT9tsnqxHmENfRnZUgM6SC, 99nKfYZL4spsTe9p9pPNhc1JWv9yq4CbPPMPm87a5sgn, BYAqFxCVwMKrw5YAQMCFQGiAF2v3YhKRm2EdGfgkYN9G, CGKeK3AfdZUxXF3qH9zxp5MR7Z4WvDVqMrU5wjMKqT5C, HRPPEX4mdoZAMkg6NLJUgDzN4pSTpiDXEAGcR5JBdiXX] }], start_block: BlockInfo { time_ms: 3000, height: 0, core_height: 0, epoch: 0 }, finalization_block: BlockInfo { time_ms: 2000000000, height: 900, core_height: 42, epoch: 0 }, winner: Locked }], vote_poll_status: Locked, locked_count: 1 }), unlocking is possible by paying 400000000000 credits"), // this should fail, as it is locked + Some("Document Contest for vote_poll ContestedDocumentResourceVotePoll { contract_id: GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec, document_type_name: domain, index_name: parentNameAndLabel, index_values: [string dash, string quantum] } is currently already locked V0(ContestedDocumentVotePollStoredInfoV0 { finalized_events: [ContestedDocumentVotePollStoredInfoVoteEventV0 { resource_vote_choices: [FinalizedResourceVoteChoicesWithVoterInfo { resource_vote_choice: TowardsIdentity(BjNejy4r9QAvLHpQ9Yq6yRMgNymeGZ46d48fJxJbMrfW), voters: [2oGomAQc47V9h3mkpyHUPbF74gT2AmoYKg1oSb94Rbwm:1, 4iroeiNBeBYZetCt21kW7FGyczE8WqoqzZ48YAHwyV7R:1, Cdf8V4KGHHd395x5xPJPPrzTKwmp5MqbuszSE2iMzzeP:1] }, FinalizedResourceVoteChoicesWithVoterInfo { resource_vote_choice: TowardsIdentity(FiLk5pGtspYtF65PKsQq3YFr1DEiXPHTZeKjusT6DuqN), voters: [] }, FinalizedResourceVoteChoicesWithVoterInfo { resource_vote_choice: TowardsIdentity(Fv8S6kTbNrRqKC7PR7XcRUoPR59bxNhhggg5mRaNN6ow), voters: [4MK8GWEWX1PturUqjZJefdE4WGrUqz1UQZnbK17ENkeA:1, 5gRudU7b4n8LYkNvhZomv6FtMrP7gvaTvRrHKfaTS22K:1, AfzQBrdwzDuTVdXrMWqQyVvXRWqPMDVjA76hViuGLh6W:1, E75wdFZB22P1uW1wJBJGPgXZuZKLotK7YmbH5wUk5msH:1, G3ZfS2v39x6FuLGnnJ1RNQyy4zn4Wb64KiGAjqj39wUu:1] }, FinalizedResourceVoteChoicesWithVoterInfo { resource_vote_choice: Abstain, voters: [5Ur8tDxJnatfUd9gcVFDde7ptHydujZzJLNTxa6aMYYy:1, 93Gsg14oT9K4FLYmC7N26uS4g5b7JcM1GwGEDeJCCBPJ:1, 96eX4PTjbXRuGHuMzwXdptWFtHcboXbtevk51Jd73pP7:1, AE9xm2mbemDeMxPUzyt35Agq1axRxggVfV4DRLAZp7Qt:1, FbLyu5d7JxEsvSsujj7Wopg57Wrvz9HH3UULCusKpBnF:1, GsubMWb3LH1skUJrcxTmZ7wus1habJcbpb8su8yBVqFY:1, H9UrL7aWaxDmXhqeGMJy7LrGdT2wWb45mc7kQYsoqwuf:1, Hv88mzPZVKq2fnjoUqK56vjzkcmqRHpWE1ME4z1MXDrw:1] }, FinalizedResourceVoteChoicesWithVoterInfo { resource_vote_choice: Lock, voters: [F1oA8iAoyJ8dgCAi2GSPqcNhp9xEuAqhP47yXBDw5QR:1, 2YSjsJUp74MJpm12rdn8wyPR5MY3c322pV8E8siw989u:1, 3fQrmN4PWhthUFnCFTaJqbT2PPGf7MytAyik4eY1DP8V:1, 7r7gnAiZunVLjtSd5ky4yvPpnWTFYbJuQAapg8kDCeNK:1, 86TUE89xNkBDcmshXRD198xjAvMmKecvHbwo6i83AmqA:1, 97iYr4cirPdG176kqa5nvJWT9tsnqxHmENfRnZUgM6SC:1, 99nKfYZL4spsTe9p9pPNhc1JWv9yq4CbPPMPm87a5sgn:1, BYAqFxCVwMKrw5YAQMCFQGiAF2v3YhKRm2EdGfgkYN9G:1, CGKeK3AfdZUxXF3qH9zxp5MR7Z4WvDVqMrU5wjMKqT5C:1, HRPPEX4mdoZAMkg6NLJUgDzN4pSTpiDXEAGcR5JBdiXX:1] }], start_block: BlockInfo { time_ms: 3000, height: 0, core_height: 0, epoch: 0 }, finalization_block: BlockInfo { time_ms: 2000000000, height: 900, core_height: 42, epoch: 0 }, winner: Locked }], vote_poll_status: Locked, locked_count: 1 }), unlocking is possible by paying 400000000000 credits"), // this should fail, as it is locked platform_version, ); } diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/mod.rs index 31a1f3fe9e6..4abe57681af 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/mod.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/mod.rs @@ -305,6 +305,18 @@ mod tests { let identity_2_info = setup_identity(platform, rng.gen(), dash_to_credits!(0.5)); + // Flip them if needed so identity 1 id is always smaller than identity 2 id + let (identity_1_info, identity_2_info) = + if identity_1_info.0.id() < identity_2_info.0.id() { + ( + identity_1_info, identity_2_info, + ) + } else { + ( + identity_2_info, identity_1_info, + ) + }; + let ((preorder_document_1, document_1), (preorder_document_2, document_2), dpns_contract) = create_dpns_name_contest_on_identities( platform, @@ -352,6 +364,18 @@ mod tests { let identity_2_info = setup_identity(platform, rng.gen(), dash_to_credits!(0.5)); + // Flip them if needed so identity 1 id is always smaller than identity 2 id + let (identity_1_info, identity_2_info) = + if identity_1_info.0.id() < identity_2_info.0.id() { + ( + identity_1_info, identity_2_info, + ) + } else { + ( + identity_2_info, identity_1_info, + ) + }; + let (_, _, dpns_contract) = create_dpns_name_contest_on_identities( platform, &identity_1_info, @@ -381,18 +405,6 @@ mod tests { let (identity_2, signer_2, key_2) = identity_2; - // Flip them if needed so identity 1 id is always smaller than identity 2 id - let (identity_1, identity_2, signer_1, signer_2, key_1, key_2, flipped) = - if identity_1.id() < identity_2.id() { - ( - identity_1, identity_2, signer_1, signer_2, key_1, key_2, false, - ) - } else { - ( - identity_2, identity_1, signer_2, signer_1, key_2, key_1, true, - ) - }; - let dpns = platform.drive.cache.system_data_contracts.load_dpns(); let dpns_contract = dpns.clone(); @@ -640,19 +652,11 @@ mod tests { .expect("expected to commit transaction"); assert_eq!(processing_result.valid_count(), 2); - if flipped { - ( - ((preorder_document_2, entropy), (document_2, entropy)), - ((preorder_document_1, entropy), (document_1, entropy)), - dpns_contract, - ) - } else { - ( - ((preorder_document_1, entropy), (document_1, entropy)), - ((preorder_document_2, entropy), (document_2, entropy)), - dpns_contract, - ) - } + ( + ((preorder_document_1, entropy), (document_1, entropy)), + ((preorder_document_2, entropy), (document_2, entropy)), + dpns_contract, + ) } pub(in crate::execution::validation::state_transition::state_transitions) fn add_contender_to_dpns_name_contest( diff --git a/packages/rs-drive/src/query/vote_poll_vote_state_query.rs b/packages/rs-drive/src/query/vote_poll_vote_state_query.rs index be47513ecb8..2ea75252110 100644 --- a/packages/rs-drive/src/query/vote_poll_vote_state_query.rs +++ b/packages/rs-drive/src/query/vote_poll_vote_state_query.rs @@ -492,6 +492,7 @@ impl<'a> ResolvedContestedDocumentVotePollDriveQuery<'a> { }) } + #[cfg(feature = "server")] /// Executes the query with no proof pub fn execute( &self, From 52f43cc78511844f8b83a3e4b49da348c55e6889 Mon Sep 17 00:00:00 2001 From: Quantum Explorer Date: Thu, 4 Jul 2024 03:38:13 +0700 Subject: [PATCH 55/55] small fix --- .../state_transition/state_transitions/mod.rs | 32 +++++++------------ .../drive/object_size_info/contract_info.rs | 1 + 2 files changed, 13 insertions(+), 20 deletions(-) diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/mod.rs index 4abe57681af..bd22d4c8956 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/mod.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/mod.rs @@ -306,16 +306,12 @@ mod tests { let identity_2_info = setup_identity(platform, rng.gen(), dash_to_credits!(0.5)); // Flip them if needed so identity 1 id is always smaller than identity 2 id - let (identity_1_info, identity_2_info) = - if identity_1_info.0.id() < identity_2_info.0.id() { - ( - identity_1_info, identity_2_info, - ) - } else { - ( - identity_2_info, identity_1_info, - ) - }; + let (identity_1_info, identity_2_info) = if identity_1_info.0.id() < identity_2_info.0.id() + { + (identity_1_info, identity_2_info) + } else { + (identity_2_info, identity_1_info) + }; let ((preorder_document_1, document_1), (preorder_document_2, document_2), dpns_contract) = create_dpns_name_contest_on_identities( @@ -365,16 +361,12 @@ mod tests { let identity_2_info = setup_identity(platform, rng.gen(), dash_to_credits!(0.5)); // Flip them if needed so identity 1 id is always smaller than identity 2 id - let (identity_1_info, identity_2_info) = - if identity_1_info.0.id() < identity_2_info.0.id() { - ( - identity_1_info, identity_2_info, - ) - } else { - ( - identity_2_info, identity_1_info, - ) - }; + let (identity_1_info, identity_2_info) = if identity_1_info.0.id() < identity_2_info.0.id() + { + (identity_1_info, identity_2_info) + } else { + (identity_2_info, identity_1_info) + }; let (_, _, dpns_contract) = create_dpns_name_contest_on_identities( platform, diff --git a/packages/rs-drive/src/drive/object_size_info/contract_info.rs b/packages/rs-drive/src/drive/object_size_info/contract_info.rs index 94ab35b066d..ca1e72081ac 100644 --- a/packages/rs-drive/src/drive/object_size_info/contract_info.rs +++ b/packages/rs-drive/src/drive/object_size_info/contract_info.rs @@ -161,6 +161,7 @@ pub enum DataContractResolvedInfo<'a> { impl<'a> From<&'a DataContractOwnedResolvedInfo> for DataContractResolvedInfo<'a> { fn from(value: &'a DataContractOwnedResolvedInfo) -> Self { match value { + #[cfg(feature = "server")] DataContractOwnedResolvedInfo::DataContractFetchInfo(fetch_info) => { DataContractResolvedInfo::ArcDataContractFetchInfo(fetch_info.clone()) }