From ff789f6942b4bcb10745adb2973d92c81cdb334f Mon Sep 17 00:00:00 2001 From: Roman Khimov Date: Tue, 8 Dec 2020 18:28:00 +0300 Subject: [PATCH] native: drop Neo.Native.Deploy, move contract init to management contract The contract is almost a stub at the moment, though it does deploy other contracts. --- cli/testdata/chain50x2.acc | Bin 45771 -> 45734 bytes pkg/core/blockchain.go | 22 ++++---- pkg/core/blockchain_test.go | 17 ++++-- pkg/core/dao/dao.go | 2 +- pkg/core/dao/dao_test.go | 6 +-- pkg/core/interop/interopnames/names.go | 2 - pkg/core/interop_system_test.go | 2 +- pkg/core/interops.go | 1 - pkg/core/native/contract.go | 19 ++++--- pkg/core/native/interop.go | 26 --------- pkg/core/native/management.go | 72 +++++++++++++++++++++++++ pkg/core/util.go | 31 +---------- pkg/core/util_test.go | 2 +- pkg/rpc/server/server_test.go | 23 ++++---- pkg/rpc/server/testdata/testblocks.acc | Bin 7522 -> 7522 bytes 15 files changed, 127 insertions(+), 98 deletions(-) create mode 100644 pkg/core/native/management.go diff --git a/cli/testdata/chain50x2.acc b/cli/testdata/chain50x2.acc index 6c10dabc4bbb20a3ea17a175d596cabfe737091e..43ee863186792eb93b161deaa8e1b707d56bddfc 100644 GIT binary patch literal 45734 zcmd44by!r<-?uw73`2Lfbb}xvLra4+BHc)bbV*2ulz?=1NH<7{lypmov~x(Nx+ipmdwg%(l6OR*2CjdWbZ`R-NkU-*x&+6@A`*V(;EyyZ$tkZmSJzsb)b z-Q!n9mJ-=5V6@y2{yNX;ce&nzJKDGV66X)sP`*|cjjp-%rK_+4|-Tni3YM=TbI0vesq+jAIKH6Y6?wV8?Fdjj< zFRtKqh3x3cIth_mde+6m+T=|-HhyaL4(|X_z)XV>77f>;246?Bpcg3>_leb*=~21s zg(*b7LHa?u_8uEq7%Ti|84N%j_P@&bpIe{!#Q)p}`iTAK9{TPU>W@VMXdy!bmX6^- z*p3Vi)HeRst6Sa%{0I(sXiX~D+92#dJqf!Fgy?9mZ|z`WY!AYwflKXw<}#Y^bWW@^ zxG>5#rmnjnY~cCgIWN>*#jg^`efR1RG`rOIiE_rLU;12Sa)yVAlEPAL=sl$q%ql&E zMstu8Fmmp~l;Q759w#B?eA2UYjbO{B!$Y38ZU6$SF*;JXtaGhfm|9GbYLX2Z_)EmB zsyT}J^jIi%mj?qh>o8yYTk^deo#Kl}`>rC>U9L&!(hN<2Xn!!@u1O*b0uy64i`diZ zw`1cxjzDG4_s+hdmnjYxCSy<5Y3#FsKT2Sdl3;+-=bxnu>`2Sz)rZV9P|DLfD>u=K^3T)j!kbxph z{&%fU!Q<9Vb0~O6U$noYq@8f!L#5m*_%>s;Y2pEf#Ds#$};M$>xbenB$0diBy_ttKclgNWTG zS1B$Gt$ZVejBdp5l;dTht3S=KgiHi}km$H{vI*kLlBwd*jxhmHeh-@M{3mOz`pfNf z>4yAyN})Vrv|Uonuy?VXPOFQhepF>$>ml5y(l(YW0?jG;+AoI&CMsG#9AJq=d`DJa ztr4OWaC>ot_v%Qe{Z|)#-yQr(?0aF&oCHqf6J{r#&jyHS?9JOpeuCNDHxA@P?@mg) z;u>HwuiJ}))v158NV?|_{q#!$;W4q}&4~yAPwV_y9F+AQ2rN63;$<2U^*Cyz4qATe zqDyN4*@+D_@VqQ&E9O=8Y*}citN-?MJzXu&Qr|g#ZNvV72tb#xvIVjz!MZ{7f)fb5 zv>Wd)inno#gnV9ADMagFH6^#VZQXiOlA1zg6DO&kfZhu;R~Ec3vg4gu^k}%=D1y0; zJgDj0++0Kgwj=+>KUqZR|J_BWddBGjR*_Zi>+rj){!bVEr#=_}xZZ$5@q%)vwAQyW zrsSg(bF#7(wXweIfejrgnJD!Q%qjWYDXokh&1{SuDEVIecSBusYja0){a5C0#&_*( zOiUb%9Vz+Pm?&-a?e7-lXl#Gq{3R2my|JT{y|tsO?fv4_Y|M=)J(>P{DYj1cuk!oZ z?EmxW|J}~g*!8a6uZ4)XIvNYx+v~gjpG$Jqf8})lPX6C*{`?;99yNA0ws!o_yYytD zG_|*Jvi;3E}%wfFmwD&xHrMnF63h zKwzK8B_YGkh&tv6oNq-a8I~@*ztZY`o!xys?LT_?9f++Qf4q*&17yc}{e%Ca^klnA zAf<7Mv^3{DZsfxZQc*Yk-L8dSK}ZhH%_A#8b^6qU%K*YELFK}eNtE1)kE+vk2$xvM z!f|3KE}nPWg!`X0lqoW{-KQ?+m?~4%+UO^u$R{M(gb0mcE5z^0*)r|gkZuk96&*A1 zY~{bLc9dgA%m%xU`W0yzUw|~n6jL=jeswJOi+iYJL1Vrc`Eqq^>Jak%C&|jqcU^vH zI_yH3^V`Yo0bY7$=$OZJX}K9(96|;{q7q;zsYv@sWja?&@__H8 zE`m)+CYWf?xALPv6vMQ2KL!)clmZ5sujOpoOS)ns*pZ}I2j2BQ+}+%yUW;5-(+M}Q z*p_)&{z()FOkXwI_dL$X*awYMy&r#&ep<8sQh#-5Xe@}2aP(72@9yrGvx8$%M(MrB zesH?wuJWcQ?988mQu(+<6beu6^bEcCGwYz!-!!bBc+ehh~Ht{GSc} zeNOeqpDIzq1p6TNv-fe26XCf97CcT*=z2^YcC)~2x;ZGSA|H}l-0EePfKyZRh5J35 zv^3in=*)ef!WtRz;T0z2IR)JJj=zC^-~Zpil$h+(zSiK7d!2!RD5rZ_FDDq4h=3*)U z3Dm?SRE!jSHoLn3fE?_%fXeDL*AfKv=xiR14jSnjYE2=ou8 zTqe#nQh;2D#N%=twfW#8fvlpGBbbQT#2jN*Twqk~2KDP%#R_cm^=H$zsUa}xc?0Yq za8`#qHp~;1F_#=8GbP0BTf0Joyw4q!m1zyNd2ka&k4j%X2d9%58%f(^vQ<&epwiXq z2dyJceVZzH)u*=K_5=j}e)g)0=o!3YOAV@cEz#zMfuW1=Q$Yz}gKvB)Knp?it*$5L z2}XI#^{HGM!C3R``*s~o+4hD*`!3ePBHaere_g=;^r!zr!26m!Ea1@^J|SMK#S&~B z2&l>$%c0oo@|Y39x4wvRlQ z%uTSF|JmIyB}J0-2~5P*q3m1*7Rx`$Jk*0cr-1+Lf&LZPGuJ%{_1sFTCNdC^x3d88_Rirr~DoJ%}p!lrN@@#BKt9GgrB zz9r&rqxyIcOa7s<9~mcsX1bn4F^Q#2;R|s9nM{#S96=zCu1~)NydO+?NI;yH8q&^D zr(3e)`gJ%%RpOCl&7EjQO@I0R)T!1?eMMqRjJHEQaWQPkdvy)cr+&9FP{zy0f{ArC zabQ3(aV`j~@F-D%UoPw{KJMN3baqORTOF(uiqpl0eWJ0!>5^z>t&x;_vkb3HYSjvp zTGntOHxwzft-zpnNf7<#G=4@c5V%fXgXz(Ff&sq(;^n9qqDN~uVM?@N3!GG%1$lkj z&6{z(?!XbQ4Mj&LzPYi`PZwcuO(6$$t+O1s@R?7@qYnOc0sk|Y^*?fY|JcI<9-c8f zdeS2rznupGN2dLt);Ub$DDWW5X}fXuI)b8~OdK*%#GCWLPIx#+-&e0r?Z8FjEH*s$xXETdte7DUaZ7L;X$iaRK2uJUW6YKW+mM=cToj&ao zDgJEvM)T{NVO>(LitPN!n`0x!`EGpbcwW;!UAEOCJ@#e%`gi{Dd$nOM-@`tk$9DY^ z@P0i#B%q|u54v{^at7J}zvp>-ecViIH&m3E(I3MtK0?j5itRS`lb8?sWK^+1<((KS z$inTBcqgx4d1%%TD3A6EBNT$b_#+DycJ9S~ud?8pf`sfa8kl4^Mm+@5Z&t;6viYC> zcDBWd68W>7SObCbv_a0jYh|NJ1khGW#>O*I=5o`AOb5pMqvIDLyYj#clbpa9n zkkk8`JS-p+cc8YUcV; z{9qPuo*rDEcCTtio!;rWiIwl%7ah|VGC0!~Ewk!u{PeFFKfdovn<)X|L7r0p;$MTY zy|>inG%u8!KWTr2|1 z$#ELOSgleESyCyINBlbU(=!StC22ho+PT!w)5qx&E{26ok)Y5lEJXGrBZN(&UXZFa zUH2~m?*s6VfEzWWxBe}jXFeNTt(997`JXuT;!u436`TOMVLA@PY_;EPx!Y71-wv{v z%zoHkL@njY+~;ZAw&_ik8Kxu7LIZ($y`0a~&~v(<(R#Of^A4v!-%_AsZMUK~@Khsx z=|lSgS&G!-Ezio%5V7v_>o4r7Ob75=pZIVpuO49{ z=EYfyU5T)RX`h4Lc}a{zpYf%y)i1s$)MGD-=mbgRd_oTLn^QjiWTSrY)bi?2yMhEubYb=9>imZSq4OHTg=M(_^ zYp^jE#e&W<^nP7u5Ks~=+0q*@v^l~F8Q6`SvA-5~+~?8~YJuEH-+2cLhSA3vOw_M@ z3F_KL3KIdG=ejg}8Yk_aZMjz5y-dV7~=q;6wX#W>@~W zTa-7M1vGqtj@8P?C z#G7R4r=wh7gciE4mMhhHjhT@SO|{7yCqUpbAi}A8TYAdE%!Szb7j(z9qIS(AMjSD7 zfk#C*H2uCKPU(2v;aTL)Yjt9TsDZ9;=@PO7KGa|Pd6UKPa+lhGz>31HeY2mkZU;T zP5sveME*lg?`!g~fKR7R-j>IqS%{y4fbDPxuSeEr3W(hx%c+bdG;>X?GHH)pXiJUc zW(0m=-S}vsm^V7ov599vwz-5G?MGpZtt#+n87!bSg65~_6q+RRRVClo@siQ$MO4Uh z3IP2zn97u+C&NTF_A@gOP)%g&;0AW7B0&-|Fmt>1%qpMTCtVxN^Fz_?i=)!VvnV0b z%2Aq;6jPp1Kfjmf*JLgPSJt@x$m@_^0|b*TgpH`8A1LB~$4QYLrGgynw}9dKlH8*? z2UGcsrt8l`5|&Dh^jy4d9Wr$m`VuHq_6xqmkAF?WeeNL30hNjH<2rj~npa`oUj{lR(Ri{JB zk0DpN(|=t+lt1M3z9tU~7?Ja6NM$e;w|NuDq3<})fx3K z;Pwkqg40Bjd8BpSIhY3t_25X+W@vWwkn;HRvjfLwrKlf&Geh847kCmh-KGH^Oo+rM z%Z5Cs0Mx$*yIq>Mex2V5Z(aogBHCLFM z*Z_4-9PeO(GmazOzic-pg$HdgH6i1E^m6-k*y`xr4rHdc7pV%q*n)zl;c2#OELDiH zJc_-yU**n6_QG7fx$982P95|FHk0utb;U2ohJvPokv}pN-1St{$K=HDTh2k?=Wflz zT9IbdYFS7H6|zvClC!rJ$Wc)nG6MB=?=F0?vTaP)E2u*32)AfA!wv0RfQTu|nigW@ zFVYUmZzPUL|8)V;{*crAnmjC^phTL0`GUkV&2bPg@0%uq*kM4BAPrj>${5z-C&^QD*jpMY#`li(EBJvWrI|LS&Ile7m=b!8iQew@Q+%X1Y@#&O@kyWLqJxJnxjO}N>qO)91`l{m1j6wcSa-4M8!H|Rf z7I5Il^jRi)Ic7mvR$I=5#V|P&tX<)HuW?`!fAO#lnxk}TbK>ib73?#$EhOp*!O(r1 z*LsLiSr(WIBJPbw1z0%wJgO`GF=*AATG?Oh9Hl}5CK(q` z$;edZTA!Y*Y$i|Tzb+ugA98wMlZOQydqrSh;w|l!j|~Fqe>TIG=Z-&kv<6vDLoFSi zOh(y3^FNxDx2ncrhf7ZEppx`mM$2d9lt6qH#;kv7p=_d+lRi+7aT~@{YWXTnMscn8 z7|}>>`RnlUUu-ArsF8~7eZIQJihKi<#9zq5NPIzPhKCaJMB|!2` zloJZ0!S2vA+v1Nh82Lu=(Ln|8Yv9uZ?_|NSMSPdi=`7N`L&^Xn_h8B|JSUzTg;^;eE%F4cp=9*wG&?Bm45cMs!Kvo@*<%#h zCIVA5vr;94Cb6b`%k+-^Ujp9msy`&)XZKGUIdjQczLVX)r*`J zcd(+YF&4RJaEHG+l2C>D=OXEs$2QAJ(Y>0wv>BolIq!6KZ4guF_q4t1n{RS|ww{5& zhusK^6~ZBThQ>=eW@(&5mTlBsiq}t-o|OVr&6)AjPpV2#4I5n;BIGHACPPzoiEW|3 z4NHo;A{MQA<`a@3dYx1yw01v_3JYIbw>{}3UZa3j2!$uJMupVSNrFx-s zyLu(gnvgu=G$^RSEPNw}yHl#K<68bcTbV8caOObxq#Uo-!;ek;C(EkQycfN>m@gu8 zPZ!Bm^$c9X6UcK4!2WBnaCLlv9RpoS$+F-6mPa+ zDU)*em0~9A5h}+jc}u>5BX^H&tXQwL1>4NP|wa+m$;XPpWBGp3~JkWaqUSyhZpXYsIcL}gTU2CZ@`buKdHx5 zV%LsBweoiT6u3z3tB_t+ByrgpN9ksTGlAwbw~Qv(zJkLque*smcXv$}87v69imdM2 z_$~(mOPgM_HeW4890dERrTalWEygc-z1RJnq`P1Ab3&3tyi60*PbotdeT^9e>WF3L z??W($saboijjvb;YCDpG!~b;wasH6g`G~@QtI?V{d2-hDVPe z6Y%(@u}A4oPKherBDm>bj_;FC{nWo`*MHs;g7(7A^L_KyVjj&!l|UbDryIlDMy6Z= zk-6NT@fI6n%Wk7lp8Hnn`A<)KCKzcD?Zsfftb;C|C5q-Z>ufUzFfnKi?2Il+3uN_aL-cdNy= zDIqrsGZ6#v}E0@6%O~K0-U0Km8zAL+U1ztItIa zC)t*H4Q`_rR33%?c3QyVKP(RyC%4w~$6w57+K2quQi^~K1Ud~e>(L~y7gV)x0 zvG_lDls!=}FCho}EnxP(zjNF^pQ97?WG`|bShKxq>a$6wcM^}(5^i&cT|NSme5@rM zzdMDnWf)!3K3G^5u7=qiPuAkm%h3ok!Jxrk0^Sb-JS3pE2ElYR#?I{P(AU&_H^z@b z4=(Euh4^aiN4k$gYNquxmwe+tb@Fb1I z3_YjDz|A*c5>d04c#CcgF#pF?&wm zHG6o55D!OaH*

D^`)$j$OHs_P+Yy?`?0a6hN6kq&Q+Z7ZEYCO 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 A`~Uy| literal 45771 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 ZFpDPCmXR}4%n`C382Dc8Zrq_0=6`Y)NgMzG diff --git a/pkg/core/blockchain.go b/pkg/core/blockchain.go index a762830f13..c81f6ba5b6 100644 --- a/pkg/core/blockchain.go +++ b/pkg/core/blockchain.go @@ -600,18 +600,16 @@ func (bc *Blockchain) storeBlock(block *block.Block, txpool *mempool.Pool) error } writeBuf.Reset() - if block.Index > 0 { - aer, err := bc.runPersist(bc.contracts.GetPersistScript(), block, cache, trigger.OnPersist) - if err != nil { - return fmt.Errorf("onPersist failed: %w", err) - } - appExecResults = append(appExecResults, aer) - err = cache.PutAppExecResult(aer, writeBuf) - if err != nil { - return fmt.Errorf("failed to store onPersist exec result: %w", err) - } - writeBuf.Reset() + aer, err := bc.runPersist(bc.contracts.GetPersistScript(), block, cache, trigger.OnPersist) + if err != nil { + return fmt.Errorf("onPersist failed: %w", err) + } + appExecResults = append(appExecResults, aer) + err = cache.PutAppExecResult(aer, writeBuf) + if err != nil { + return fmt.Errorf("failed to store onPersist exec result: %w", err) } + writeBuf.Reset() for _, tx := range block.Transactions { if err := cache.StoreAsTransaction(tx, block.Index, writeBuf); err != nil { @@ -673,7 +671,7 @@ func (bc *Blockchain) storeBlock(block *block.Block, txpool *mempool.Pool) error } } - aer, err := bc.runPersist(bc.contracts.GetPostPersistScript(), block, cache, trigger.PostPersist) + aer, err = bc.runPersist(bc.contracts.GetPostPersistScript(), block, cache, trigger.PostPersist) if err != nil { return fmt.Errorf("postPersist failed: %w", err) } diff --git a/pkg/core/blockchain_test.go b/pkg/core/blockchain_test.go index d63e0a8033..785c18e79d 100644 --- a/pkg/core/blockchain_test.go +++ b/pkg/core/blockchain_test.go @@ -713,11 +713,18 @@ func TestVerifyTx(t *testing.T) { require.True(t, errors.Is(bc.VerifyTx(tx), ErrHasConflicts)) }) t.Run("attribute on-chain conflict", func(t *testing.T) { - b, err := bc.GetBlock(bc.GetHeaderHash(0)) - require.NoError(t, err) - conflictsHash := b.Transactions[0].Hash() - tx := getConflictsTx(conflictsHash) - require.Error(t, bc.VerifyTx(tx)) + tx := transaction.New(netmode.UnitTestNet, []byte{byte(opcode.PUSH1)}, 0) + tx.ValidUntilBlock = 4242 + tx.Signers = []transaction.Signer{{ + Account: testchain.MultisigScriptHash(), + Scopes: transaction.None, + }} + require.NoError(t, testchain.SignTx(bc, tx)) + b := bc.newBlock(tx) + + require.NoError(t, bc.AddBlock(b)) + txConflict := getConflictsTx(tx.Hash()) + require.Error(t, bc.VerifyTx(txConflict)) }) t.Run("positive", func(t *testing.T) { tx := getConflictsTx(random.Uint256()) diff --git a/pkg/core/dao/dao.go b/pkg/core/dao/dao.go index b1fb35a7da..d7af83996b 100644 --- a/pkg/core/dao/dao.go +++ b/pkg/core/dao/dao.go @@ -163,7 +163,7 @@ func (dao *Simple) DeleteContractState(hash util.Uint160) error { // GetAndUpdateNextContractID returns id for the next contract and increases stored ID. func (dao *Simple) GetAndUpdateNextContractID() (int32, error) { - var id int32 + var id = int32(1) key := storage.SYSContractID.Bytes() data, err := dao.Store.Get(key) if err == nil { diff --git a/pkg/core/dao/dao_test.go b/pkg/core/dao/dao_test.go index a1a022eeac..b3971c74c4 100644 --- a/pkg/core/dao/dao_test.go +++ b/pkg/core/dao/dao_test.go @@ -73,13 +73,13 @@ func TestSimple_GetAndUpdateNextContractID(t *testing.T) { dao := NewSimple(storage.NewMemoryStore(), netmode.UnitTestNet, false) id, err := dao.GetAndUpdateNextContractID() require.NoError(t, err) - require.EqualValues(t, 0, id) - id, err = dao.GetAndUpdateNextContractID() - require.NoError(t, err) require.EqualValues(t, 1, id) id, err = dao.GetAndUpdateNextContractID() require.NoError(t, err) require.EqualValues(t, 2, id) + id, err = dao.GetAndUpdateNextContractID() + require.NoError(t, err) + require.EqualValues(t, 3, id) } func TestPutGetAppExecResult(t *testing.T) { diff --git a/pkg/core/interop/interopnames/names.go b/pkg/core/interop/interopnames/names.go index 44536d7063..ac60bca12c 100644 --- a/pkg/core/interop/interopnames/names.go +++ b/pkg/core/interop/interopnames/names.go @@ -69,7 +69,6 @@ const ( NeoCryptoSHA256 = "Neo.Crypto.SHA256" NeoCryptoRIPEMD160 = "Neo.Crypto.RIPEMD160" NeoNativeCall = "Neo.Native.Call" - NeoNativeDeploy = "Neo.Native.Deploy" ) var names = []string{ @@ -140,5 +139,4 @@ var names = []string{ NeoCryptoSHA256, NeoCryptoRIPEMD160, NeoNativeCall, - NeoNativeDeploy, } diff --git a/pkg/core/interop_system_test.go b/pkg/core/interop_system_test.go index faef05bb6c..b8b2ab42cb 100644 --- a/pkg/core/interop_system_test.go +++ b/pkg/core/interop_system_test.go @@ -718,7 +718,7 @@ func TestContractCreate(t *testing.T) { ic.Tx = transaction.New(netmode.UnitTestNet, []byte{1}, 0) ic.Tx.Signers = append(ic.Tx.Signers, transaction.Signer{Account: sender}) - cs.ID = 0 + cs.ID = 1 cs.Hash = state.CreateContractHash(sender, cs.Script) t.Run("missing NEF", func(t *testing.T) { diff --git a/pkg/core/interops.go b/pkg/core/interops.go index 12f4439bff..bb7eda1ed1 100644 --- a/pkg/core/interops.go +++ b/pkg/core/interops.go @@ -126,7 +126,6 @@ var neoInterops = []interop.Function{ {Name: interopnames.NeoCryptoSHA256, Func: crypto.Sha256, Price: 1000000, ParamCount: 1}, {Name: interopnames.NeoCryptoRIPEMD160, Func: crypto.RipeMD160, Price: 1000000, ParamCount: 1}, {Name: interopnames.NeoNativeCall, Func: native.Call, Price: 0, RequiredFlags: smartcontract.AllowCall, ParamCount: 1, DisallowCallback: true}, - {Name: interopnames.NeoNativeDeploy, Func: native.Deploy, Price: 0, RequiredFlags: smartcontract.WriteStates, DisallowCallback: true}, } // initIDinInteropsSlice initializes IDs from names in one given diff --git a/pkg/core/native/contract.go b/pkg/core/native/contract.go index 0e925f450e..7dad9d2e83 100644 --- a/pkg/core/native/contract.go +++ b/pkg/core/native/contract.go @@ -15,13 +15,14 @@ const reservedContractID = -100 // Contracts is a set of registered native contracts. type Contracts struct { - NEO *NEO - GAS *GAS - Policy *Policy - Oracle *Oracle - Designate *Designate - Notary *Notary - Contracts []interop.Contract + Management *Management + NEO *NEO + GAS *GAS + Policy *Policy + Oracle *Oracle + Designate *Designate + Notary *Notary + Contracts []interop.Contract // persistScript is vm script which executes "onPersist" method of every native contract. persistScript []byte // postPersistScript is vm script which executes "postPersist" method of every native contract. @@ -54,6 +55,10 @@ func (cs *Contracts) ByName(name string) interop.Contract { func NewContracts(p2pSigExtensionsEnabled bool) *Contracts { cs := new(Contracts) + mgmt := newManagement() + cs.Management = mgmt + cs.Contracts = append(cs.Contracts, mgmt) + gas := newGAS() neo := newNEO() neo.GAS = gas diff --git a/pkg/core/native/interop.go b/pkg/core/native/interop.go index ecd529fc4c..78737da08e 100644 --- a/pkg/core/native/interop.go +++ b/pkg/core/native/interop.go @@ -5,36 +5,10 @@ import ( "fmt" "github.com/nspcc-dev/neo-go/pkg/core/interop" - "github.com/nspcc-dev/neo-go/pkg/core/state" "github.com/nspcc-dev/neo-go/pkg/smartcontract" "github.com/nspcc-dev/neo-go/pkg/smartcontract/trigger" ) -// Deploy deploys native contract. -func Deploy(ic *interop.Context) error { - if ic.Block == nil || ic.Block.Index != 0 { - return errors.New("native contracts can be deployed only at 0 block") - } - - for _, native := range ic.Natives { - md := native.Metadata() - - cs := &state.Contract{ - ID: md.ContractID, - Hash: md.Hash, - Script: md.Script, - Manifest: md.Manifest, - } - if err := ic.DAO.PutContractState(cs); err != nil { - return err - } - if err := native.Initialize(ic); err != nil { - return fmt.Errorf("initializing %s native contract: %w", md.Name, err) - } - } - return nil -} - // Call calls specified native contract method. func Call(ic *interop.Context) error { name := ic.VM.Estack().Pop().String() diff --git a/pkg/core/native/management.go b/pkg/core/native/management.go new file mode 100644 index 0000000000..a021128257 --- /dev/null +++ b/pkg/core/native/management.go @@ -0,0 +1,72 @@ +package native + +import ( + "fmt" + "sync" + + "github.com/nspcc-dev/neo-go/pkg/core/interop" + "github.com/nspcc-dev/neo-go/pkg/core/state" +) + +// Management is contract-managing native contract. +type Management struct { + interop.ContractMD + + lock sync.RWMutex + isValid bool + nextID int32 +} + +const ( + managementName = "Neo Contract Management" + prefixContract = 8 + prefixNextAvailableId = 15 +) + +// newManagement creates new Management native contract. +func newManagement() *Management { + var m = &Management{ContractMD: *interop.NewContractMD(managementName)} + + return m +} + +// Metadata implements Contract interface. +func (m *Management) Metadata() *interop.ContractMD { + return &m.ContractMD +} + +// OnPersist implements Contract interface. +func (m *Management) OnPersist(ic *interop.Context) error { + if ic.Block.Index != 0 { // We're only deploying at 0 at the moment. + return nil + } + + for _, native := range ic.Natives { + md := native.Metadata() + + cs := &state.Contract{ + ID: md.ContractID, + Hash: md.Hash, + Script: md.Script, + Manifest: md.Manifest, + } + if err := ic.DAO.PutContractState(cs); err != nil { + return err + } + if err := native.Initialize(ic); err != nil { + return fmt.Errorf("initializing %s native contract: %w", md.Name, err) + } + } + + return nil +} + +// PostPersist implements Contract interface. +func (m *Management) PostPersist(_ *interop.Context) error { + return nil +} + +// Initialize implements Contract interface. +func (m *Management) Initialize(_ *interop.Context) error { + return nil +} diff --git a/pkg/core/util.go b/pkg/core/util.go index eb85640b69..283c9d0507 100644 --- a/pkg/core/util.go +++ b/pkg/core/util.go @@ -5,16 +5,12 @@ import ( "time" "github.com/nspcc-dev/neo-go/pkg/config" - "github.com/nspcc-dev/neo-go/pkg/config/netmode" "github.com/nspcc-dev/neo-go/pkg/core/block" - "github.com/nspcc-dev/neo-go/pkg/core/interop/interopnames" "github.com/nspcc-dev/neo-go/pkg/core/transaction" "github.com/nspcc-dev/neo-go/pkg/crypto/hash" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" - "github.com/nspcc-dev/neo-go/pkg/io" "github.com/nspcc-dev/neo-go/pkg/smartcontract" "github.com/nspcc-dev/neo-go/pkg/util" - "github.com/nspcc-dev/neo-go/pkg/vm/emit" "github.com/nspcc-dev/neo-go/pkg/vm/opcode" ) @@ -56,10 +52,8 @@ func createGenesisBlock(cfg config.ProtocolConfiguration) (*block.Block, error) } b := &block.Block{ - Base: base, - Transactions: []*transaction.Transaction{ - deployNativeContracts(cfg.Magic), - }, + Base: base, + Transactions: []*transaction.Transaction{}, ConsensusData: block.ConsensusData{ PrimaryIndex: 0, Nonce: 2083236893, @@ -70,27 +64,6 @@ func createGenesisBlock(cfg config.ProtocolConfiguration) (*block.Block, error) return b, nil } -func deployNativeContracts(magic netmode.Magic) *transaction.Transaction { - buf := io.NewBufBinWriter() - emit.Syscall(buf.BinWriter, interopnames.NeoNativeDeploy) - script := buf.Bytes() - tx := transaction.New(magic, script, 0) - tx.Nonce = 0 - tx.Signers = []transaction.Signer{ - { - Account: hash.Hash160([]byte{byte(opcode.PUSH1)}), - Scopes: transaction.None, - }, - } - tx.Scripts = []transaction.Witness{ - { - InvocationScript: []byte{}, - VerificationScript: []byte{byte(opcode.PUSH1)}, - }, - } - return tx -} - func validatorsFromConfig(cfg config.ProtocolConfiguration) ([]*keys.PublicKey, error) { vs, err := committeeFromConfig(cfg) if err != nil { diff --git a/pkg/core/util_test.go b/pkg/core/util_test.go index dae606d641..ceec4237a7 100644 --- a/pkg/core/util_test.go +++ b/pkg/core/util_test.go @@ -17,7 +17,7 @@ func TestGenesisBlockMainNet(t *testing.T) { block, err := createGenesisBlock(cfg.ProtocolConfiguration) require.NoError(t, err) - expect := "ecaee33262f1bc7c7c28f2b25b54a5d61d50670871f45c0c6fe755a40cbde4a8" + expect := "00c6803707b564153d444bfcdf3a13325fc96dda55cc8a740bbd543a1d752fda" assert.Equal(t, expect, block.Hash().StringLE()) } diff --git a/pkg/rpc/server/server_test.go b/pkg/rpc/server/server_test.go index 8f9e2cc08c..d8cf65ed55 100644 --- a/pkg/rpc/server/server_test.go +++ b/pkg/rpc/server/server_test.go @@ -57,8 +57,8 @@ type rpcTestCase struct { } const testContractHash = "743ed26f78e29ecd595535b74a943b1f9ccbc444" -const deploymentTxHash = "9ecf1273fe0d8868cc024c8270b569a12edd7ea9d675c88554b937134efb03f8" -const genesisBlockHash = "a496577895eb8c227bb866dc44f99f21c0cf06417ca8f2a877cc5d761a50dac0" +const deploymentTxHash = "a72dfaebf9543964d74e803723dae6a86196e0915ae9d76b3cc57c3b2e3e8c49" +const genesisBlockHash = "0542f4350c6e236d0509bcd98188b0034bfbecc1a0c7fcdb8e4295310d468b70" const verifyContractHash = "a2eb22340979804cb10cc1add0b8822c201f4d8a" const verifyContractAVM = "570300412d51083021700c14aa8acf859d4fe402b34e673f2156821796a488ebdb30716813cedb2869db289740" @@ -89,8 +89,9 @@ var rpcTestCases = map[string][]rpcTestCase{ res, ok := acc.(*result.ApplicationLog) require.True(t, ok) assert.Equal(t, genesisBlockHash, res.Container.StringLE()) - assert.Equal(t, 1, len(res.Executions)) - assert.Equal(t, trigger.PostPersist, res.Executions[0].Trigger) // no onPersist for genesis block + assert.Equal(t, 2, len(res.Executions)) + assert.Equal(t, trigger.OnPersist, res.Executions[0].Trigger) + assert.Equal(t, trigger.PostPersist, res.Executions[1].Trigger) assert.Equal(t, vm.HaltState, res.Executions[0].VMState) }, }, @@ -103,7 +104,7 @@ var rpcTestCases = map[string][]rpcTestCase{ require.True(t, ok) assert.Equal(t, genesisBlockHash, res.Container.StringLE()) assert.Equal(t, 1, len(res.Executions)) - assert.Equal(t, trigger.PostPersist, res.Executions[0].Trigger) // no onPersist for genesis block + assert.Equal(t, trigger.PostPersist, res.Executions[0].Trigger) assert.Equal(t, vm.HaltState, res.Executions[0].VMState) }, }, @@ -115,7 +116,9 @@ var rpcTestCases = map[string][]rpcTestCase{ res, ok := acc.(*result.ApplicationLog) require.True(t, ok) assert.Equal(t, genesisBlockHash, res.Container.StringLE()) - assert.Equal(t, 0, len(res.Executions)) // no onPersist for genesis block + assert.Equal(t, 1, len(res.Executions)) + assert.Equal(t, trigger.OnPersist, res.Executions[0].Trigger) + assert.Equal(t, vm.HaltState, res.Executions[0].VMState) }, }, { @@ -1075,7 +1078,7 @@ func testRPCProtocol(t *testing.T, doRPCCall func(string, string, *testing.T) [] }) t.Run("getrawtransaction", func(t *testing.T) { - block, _ := chain.GetBlock(chain.GetHeaderHash(0)) + block, _ := chain.GetBlock(chain.GetHeaderHash(1)) tx := block.Transactions[0] rpc := fmt.Sprintf(`{"jsonrpc": "2.0", "id": 1, "method": "getrawtransaction", "params": ["%s"]}"`, tx.Hash().StringLE()) body := doRPCCall(rpc, httpSrv.URL, t) @@ -1090,7 +1093,7 @@ func testRPCProtocol(t *testing.T, doRPCCall func(string, string, *testing.T) [] }) t.Run("getrawtransaction 2 arguments", func(t *testing.T) { - block, _ := chain.GetBlock(chain.GetHeaderHash(0)) + block, _ := chain.GetBlock(chain.GetHeaderHash(1)) tx := block.Transactions[0] rpc := fmt.Sprintf(`{"jsonrpc": "2.0", "id": 1, "method": "getrawtransaction", "params": ["%s", 0]}"`, tx.Hash().StringLE()) body := doRPCCall(rpc, httpSrv.URL, t) @@ -1105,7 +1108,7 @@ func testRPCProtocol(t *testing.T, doRPCCall func(string, string, *testing.T) [] }) t.Run("getrawtransaction 2 arguments, verbose", func(t *testing.T) { - block, _ := chain.GetBlock(chain.GetHeaderHash(0)) + block, _ := chain.GetBlock(chain.GetHeaderHash(1)) TXHash := block.Transactions[0].Hash() _ = block.Transactions[0].Size() rpc := fmt.Sprintf(`{"jsonrpc": "2.0", "id": 1, "method": "getrawtransaction", "params": ["%s", 1]}"`, TXHash.StringLE()) @@ -1116,7 +1119,7 @@ func testRPCProtocol(t *testing.T, doRPCCall func(string, string, *testing.T) [] require.NoErrorf(t, err, "could not parse response: %s", txOut) assert.Equal(t, *block.Transactions[0], actual.Transaction) - assert.Equal(t, 9, actual.Confirmations) + assert.Equal(t, 8, actual.Confirmations) assert.Equal(t, TXHash, actual.Transaction.Hash()) }) diff --git a/pkg/rpc/server/testdata/testblocks.acc b/pkg/rpc/server/testdata/testblocks.acc index 444446512145627acecfbd90cb2d7782fe79d6bf..1d0bc04ede489d2e417c2f34643f8265cb7f1a7f 100644 GIT binary patch delta 1975 zcmV;o2T1thI^sGk2LJ#7p9KH_00000aEnF_F_l7&+x*9%!R-4>1F(pJ*}Mq_Z6j_B zHS|ISkt`qtk;ddgkx(FiH)ZmhhNg*`f@sf)Yi1W4{;o@W=|3h7l3`6BiiVhx?b*Bx zUlhg>b|H~HCVxeaa`H9Nm*_nD@~3V;XI>Vs3_w=Bmd$9@okYp9omIYk8$JB-Jw8rF z<@)DT!R^(Z2{XWe=m9xnK<^xHRJ{GgexVIg*NVabc$&(@cmf@L#olG9a;jf@& zsI^c;fLCEecY#B#^yE2X_PhPmIFMNCe%daQ#^geF0RR93le`cce=|zz@c)x``fG+Z zMXImIs8S{smPjZL(Nl^V#pmS~ZRZLsiuJeEEFvGnyBXU`=h%YEZOWcV4b@+-bOh$`>-pOX%CPR(;@@60~S8Ee-U=9*hhQc~lxE9|W|i|}b= z$+EVHFj$5C#&jJ{MS3vg3_wRop|+0le7eKCbI{dd#w_kV2?(H<&)d3=w>OCZS`N0P zg0{+o-e#bEtA|ACE3pX;U}V%f!WRcY0Y_Azi@KAs8laPR2db0k3BZ#s2?~>=2}QFZ z2zUXL>l=)-Gz%mGK*gLVROx6b6Hm9OWQ$np=5S|c6!aP(aTwcZp!t^XcXgGue4%Yh zhQHL~LV4|hl3$=4x(QjgjYfN}9(W`om6JgbDk!A_00000004K*F6m{~F-2|=L1aba zPVnAsV_=oQyQ~uQQ_AAt|<=2(1uF?N#6^iY#vCUrPmuCs=EqI!|^nNLZh* zF;C=;X6eA##}9wUM2nGsl%~QQ{jq+qBn0Qh^{4RS(~EedMPUMt{q>Z_R4ocC~h&oC<-E#p-tgvX&vxUl_J6j27=;eenAv0^Os0T*` z8cJ)tRPeLOq9?H9URp{Z;ga-R^E5@W(~Jy2LW&Vsse5&jlEfs<-H7JMU)^qS|J}f~ z%@U#S-}wiLPuIcq8bQ-6;E=~k`RSh{KpOTX1KagRld&40lRFasAm5c; zAf}7Zt`%zle9VkZ`}YCx4Ylsim?ha-q`Q(I(vw;fAOw}hl2zp+Yr&5`v*h6fD$+>@k)Y3|25%UsW0OB$MW*cK$U*j70AF%c3 zG!nK9K)>$eZxXHwP$@@)s5^$GL%9|0Pi`P1T&F7QaiZ-6r)S(ph*Y@LUL1|xSAZ*h z<3_t_imkd!i|t0ZEqMz5(TP zJX~+fmxVE`h=j3LubNF8)?Eh_dOWl5Q9_P?W%s`*0;dsy8dx%!f7O0@jk)5a-fUw$ zAF5=U20)g^i#+YW7hZZqf(RerHLQ)>OdF4PUmIOwQxJA8G6BV7mB* zZYgDKe5ey+ypypSpp%Oj{vhRl^0mZkO%xld_oAchbfms>QYRt!>I`HM?az?f+=iPC3_t`~(4|()z4bA19>>0t8LsDJbJA87cacv> zZzy3et_iy6KTe-lK3tQe-ir(pv&-VS<88vwal;Z?Ju3f2Kf;X+K!|vA8s`nWSv8!) z{7Mj4r9}$Li;eDGAdOj6Z`J`ZV(%8NedV$}dA11!K73*s9a@OO&jAv(?)H+e%JXTo JXS1;yu>x~mvfKaw delta 1975 zcmV;o2T1thI^sGk2LJ#7p9KH_00000z}iq6c3sSOsPd?MK?cvjA)om~+-A6YB8=;m zcvqIBkt`qtp^!Qlkx(FiUaSfiB^J3s?<>y5#Yt7Ot%0J||N6>E5oo51`K>7n^BEBS z?>cLap7sI?42X3w+t-Jjpvd0JBeoyh6i7)+3_xm3j{-&?lKEGwgzC^SXqyHh zO)}UVkM6QQcP-D$^E3kPQ}re&{i7g2M6pUHWdc<&yYv>zMxdKTb_J^pK!l-%W&_qT zSmnYk)GeUot%>*+$pTd~uv=l>-5xJ&%n^4@1)V_`27MMP^x0ggmtfj?Fp zY%CdD8I!RZm9xnK<^xId9Y2Ff+YaA|!GU?twPxQkT>|dtz=7EfRdyd?9;lK8kjMc! z0)*4;F{|S#vV}D{9zF0KVa$iYzl$4@o_OYplsXu80RR93le`cce+K}%fn*~o%yxD> zV7D()XB!fq(&s_vT_;&5qY#xpT)Uk*b1{2Zi;X+T-L_l{>QtWb;~GD5r)@2@UoN>n zI1E5Mo&k{36~E(Wj*`Y zAqc>e>l=)-Gz%mGKzEpNJDIsnsn#BKFzkT*jvS9m0H;4hV%se4Yk#m92|^o05I4Xu zq#a!hXA!eHMOKbXE23?v1|9iuTF8RxR+B*xDk!A_00000002tkS-KexUS*$!*>D=_ z$YPLae~gh8I$oHYrTnNZW@VG=4Il)IlsXub4h|rHNc2;ex;C@o?Z7ym+ww6=pIj(t z*BNRWUJN{gpdmu}kbN(7M;v^Q?>#s^Lr?z5gN79teQk-f^AqcS3Z5C23_z%9B77uT zHv3XUZIS0~mZjr~7nVOs$^eJN8RDJb9(eeowiFBY%Fe~b-?1i!BLIvA6;5FmfN zXCxYWT4lA|kyU2>&|^{Ib-8!ACHxdG`+&H0^E`<_dA4z-xrPJf3YA7Kb2uY|n!uIZr9SS5L>UyfPO70%+v^BA7s@*6fO<>#32+Ac2 zmCXt8J12+{{p|c71B{kdl}WrMl5!Cn(LX9WQhcK{zaDf>vyE;4ld&40lRFasAd&Gp zR<j!t75F{xm82@u~S+;OMi{5vep=XQp5*u z(dknRK=T!7%%-?Q0YzCId^G?ZfL{Yx^<_nQcM1$ZZQNwU+CZ#idR}r&rgF4n&Z27-5QYsp;m~};^5nY6 zc4Ci2oO3r0y;8!1_42t0ZIC}<_=^i zDcq>t4h4P)C(T2=ouW~sm~p>26zh*i(QuA`W%s`*0;dsy8dx%!f7O0@jk)5a-fUw$ zAF5=U20)IKIv92V000J)ybv3IPbQS21TLSVJL|IPs;+ztYI2weVXGufC$WwcWqtRH z4OD@`)1aVg%RloGEiMd-^AqBSHhiCtF3q7Dl zc&;e72-!<_eQz_WNC~+F>PhvEiScl5K{Y!Ez%?!rLxzmG$Q$2-C;@6kUdR3nK-_(N z#pg1^kv3~nm|!@Jpb+_Ao@m4g0Ji1^D8M0?vsjXn?RYp7vn$hZ=TQ7)j3C9$LAnt9 zG||awYMp}(6O*wTpp%Oj{vdf5*gb@xl7d6o*@@hKv7X&gMi~4p3&gV0VpWAtzeSU& z86X6YlsXub%^4tnmo+S^!A^r-s#^;w?Fe4xJQ_XgbkK|1?M?XPhwONPuQ%)+f?W|m z3wLF!OCCO;w0_%n5r_B?@nLk#IW=@C3_y!%|MKtrpSUTn;+~;%@i!)rM7P(w{WLnwo;f4s&>EL26HE2WUvr!z`&~ql2S$wvwK}#KE JqO-9Yu>zp>ojU*k