content: /*
   * Copyright 2024 Ant Group
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *     http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  
  package com.alipay.antchain.bridge.plugins.mychain;
  
  import java.io.ByteArrayInputStream;
  import java.lang.reflect.Method;
  import java.security.PrivateKey;
  
  import cn.hutool.core.collection.ListUtil;
  import cn.hutool.core.util.HexUtil;
  import cn.hutool.core.util.ReflectUtil;
  import cn.hutool.crypto.PemUtil;
  import com.alipay.antchain.bridge.commons.core.base.ConsensusState;
  import com.alipay.antchain.bridge.commons.core.base.CrossChainMessage;
  import com.alipay.antchain.bridge.commons.core.base.ObjectIdentity;
  import com.alipay.antchain.bridge.commons.core.base.X509PubkeyInfoObjectIdentity;
  import com.alipay.antchain.bridge.commons.core.bta.BlockchainTrustAnchorFactory;
  import com.alipay.antchain.bridge.commons.core.bta.IBlockchainTrustAnchor;
  import com.alipay.antchain.bridge.commons.utils.crypto.SignAlgoEnum;
  import com.alipay.antchain.bridge.plugins.mychain.crypto.CryptoSuiteEnum;
  import com.alipay.antchain.bridge.plugins.mychain.model.ContractAddressInfo;
  import com.alipay.antchain.bridge.plugins.mychain.model.MychainSubjectIdentity;
  import com.alipay.antchain.bridge.plugins.spi.ptc.core.VerifyResult;
  import lombok.extern.slf4j.Slf4j;
  import org.junit.Assert;
  import org.junit.Before;
  import org.junit.Test;
  import org.slf4j.Logger;
  
  @Slf4j
  public class MychainHcdvsServiceTest {
  
      private static final CrossChainMessage currMessage = CrossChainMessage.decode(HexUtil.decodeHex("0000ce070000000001000000000100080100000000000f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008b4e714872656365697665722e646f6d61696e00000000000000000000000000ffffffffa967598803bc58ff39ae8c4f92cf6eabb270e91891f77c70030b007a0000000000000000000000000000000000000000000000000000000000000004746573740000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a400000000d9acd4555ef3083c043500716e832a9e1e8d2084cbb413d8d565dcf415042a82000000010200b30600000000ad060000000003000000333469010020000000c5f77d95d203d30b1a1e4c5e51107021c5b7a769295d6d364195a587e18558b2020008000000bcd1d3899201000003007e0500007b22616d436f6e74726163744964486578223a2262666638363231386432393231366333656566316136663064646439613864366363373334356261363639376362353161336639366365343166623037656461222c226c6f67496e646578223a312c226c6f67546f706963486578223a22353336353665363434313735373436383464363537333733363136373635222c2272656365697074223a227b5c22726573756c745c223a302c5c226f75747075745c223a5c225c222c5c226761735f757365645c223a353138343933342c5c226c6f67735c223a5b7b5c22746f706963735c223a5b5c2263616c6c5f636f6e74726163745c225d2c5c2266726f6d5c223a5c22633630613964343831303539353061306363613037613463363332306239386333303361643432643639346136333435323965386531613061313666636462355c222c5c226c6f675f646174615c223a5c225c222c5c22746f5c223a5c22643961636434353535656633303833633034333530303731366538333261396531653864323038346362623431336438643536356463663431353034326138325c227d2c7b5c22746f706963735c223a5b5c223533363536653634343137353734363834643635373337333631363736355c222c5c2230303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303230303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303130383030303030303066303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030386234653731343837323635363336353639373636353732326536343666366436313639366530303030303030303030303030303030303030303030303030306666666666666666613936373539383830336263353866663339616538633466393263663665616262323730653931383931663737633730303330623030376130303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303034373436353733373430303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030613430303030303030306439616364343535356566333038336330343335303037313665383332613965316538643230383463626234313364386435363564636634313530343261383230303030303030313030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030305c225d2c5c2266726f6d5c223a5c22656633663837623863346135353466393962373664356230393333363834356262393564633339396136313433383834663239616431353161383330323532365c222c5c226c6f675f646174615c223a5c2230663533363536653634343137353734363834643635373337333631363736355c222c5c22746f5c223a5c22626666383632313864323932313663336565663161366630646464396138643663633733343562613636393763623531613366393663653431666230376564615c227d5d7d222c2272656365697074496e646578223a337d0400c0000000e0b6d9013195594002730aa7cdba82b2cb1aabd469b8554ea90086c9f6422d90e0b6d9013195594002730aa7cdba82b2cb1aabd469b8554ea90086c9f6422d90e0b6d9013195594002730aa7cdba82b2cb1aabd469b8554ea90086c9f6422d90e0b6d9013195594002730aa7cdba82b2cb1aabd469b8554ea90086c9f6422d90e0b6d9013195594002730aa7cdba82b2cb1aabd469b8554ea90086c9f6422d90e0b6d9013195594002730aa7cdba82b2cb1aabd469b8554ea90086c9f6422d90050020000000eba5dd66345d1b643a5f204687bc4fa3a9749c324c5568725fa9f690aa18d280"));
  
      private static final String CHAIN_DOMAIN = "test.domain";
  
      public static final byte[] RAW_PUBLIC_KEY = PemUtil.readPem(new ByteArrayInputStream(
                      ("-----BEGIN PUBLIC KEY-----\n" +
                              "MFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEULzSDPM4mhRkGpCiVirHZTWfzuZ/PfO6\n" +
                              "+/RfVgGpZxs4EUQZhw5SnYWIwK99KxDPNxtYG7OEiWDA7+EKZUWBIw==\n" +
                              "-----END PUBLIC KEY-----\n").getBytes()
              )
      );
  
      public static final PrivateKey PRIVATE_KEY = SignAlgoEnum.KECCAK256_WITH_SECP256K1.getSigner().readPemPrivateKey(
              ("-----BEGIN EC PRIVATE KEY-----\n" +
                      "MHQCAQEEINtcJsfWygsBn4u8sscy/04yPSpafFwCW4yVg1Vrb8looAcGBSuBBAAK\n" +
                      "oUQDQgAEULzSDPM4mhRkGpCiVirHZTWfzuZ/PfO6+/RfVgGpZxs4EUQZhw5SnYWI\n" +
                      "wK99KxDPNxtYG7OEiWDA7+EKZUWBIw==\n" +
                      "-----END EC PRIVATE KEY-----\n").getBytes()
      );
  
      private static final String amEvm = "AM_EVM_CONTRACT_ac81f2ed-f07b-471f-ae6f-4d823ef32e34";
  
      private static final String amWasm = "AM_WASM_CONTRACT_2aebab20-21d8-4b57-8660-34236caf4360";
  
      private static final ObjectIdentity oid;
  
      private static MychainHcdvsService mychainHcdvsService;
  
      static {
          oid = new X509PubkeyInfoObjectIdentity(RAW_PUBLIC_KEY);
      }
  
      private ConsensusState anchorState;
  
      private ConsensusState currentState;
  
      private  MychainSubjectIdentity subjectIdentity;
  
      private IBlockchainTrustAnchor mychainBta;
  
      @Before
      public void init() throws Exception {
          anchorState = ConsensusState.decode(HexUtil.decodeHex("00001a060000000002000000010001000b000000746573742e646f6d61696e020003000000333468030020000000cf523d1ec68127ac3d88fab9e7952977f18413b4f77069d3e68693b329e2aec504002000000097e80f53e2bc36cfc5588ffa4e17957039973f68ecd349cc6725eb73a11f3f7e050008000000c8cfd389920100000600fe0300007b226e756d626572223a333335353735322c227472616e73616374696f6e5f726f6f74223a2236653566316366303063313461333235393465346266646137333736633737613439613035313766633663353536663637646436623265373962663534623735222c226761735f75736564223a313236323634362c2276657273696f6e223a3739323633333536303233373334353238322c22726563656970745f726f6f74223a2265363465333238613938633839393936363139613130626134646538663361343663393035646633366565396634323063663632373736656639646161633134222c2268617368223a2263663532336431656336383132376163336438386661623965373935323937376631383431336234663737303639643365363836393362333239653261656335222c22706172656e745f68617368223a2239376538306635336532626333366366633535383866666134653137393537303339393733663638656364333439636336373235656237336131316633663765222c2273746174655f726f6f74223a2238373630316539366335616464376564313364386666373161353936333437383134306365393761643538333736626534333564633338323232653539626264222c2274696d657374616d70223a313732383838393231323837322c226c6f675f626c6f6f6d223a223030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303038303030303030303030303030303030303030303030303030303030303030303030303038303030303030303030303030303030303030303030343030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030313030303030303030303030303030303030303030303030303030303030303030303030303030303030303030313030303130303030303030303030303230303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030313030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303230303030303030303030303030303030303030303030227d07009d0000007b22616d436f6e7472616374496473223a5b22414d5f45564d5f434f4e54524143545f61633831663265642d663037622d343731662d616536662d346438323365663332653334222c22414d5f5741534d5f434f4e54524143545f32616562616232302d323164382d346235372d383636302d333432333663616634333630225d2c226d79636861696e4861736854797065223a22534841323536227d0800f10000007b2270726f6f66223a2266383663663834336238343130636631396565383433666565643631383831666630306365303262303437343934313136323033646635663935363365643030353737626139653065393731313434373363333832303232303538613039323932623430636636353733336463633830653166346539313362666333313861333737316564363937303937613030653638303833333333343638613065383863613365656630656138623336653439643937333930653638336630363237303865656339643163313835613936326635633635373464353064653361222c2274797065223a307d"));
          currentState = ConsensusState.decode(HexUtil.decodeHex("00001b060000000002000000010001000b000000746573742e646f6d61696e020003000000333469030020000000c5f77d95d203d30b1a1e4c5e51107021c5b7a769295d6d364195a587e18558b2040020000000cf523d1ec68127ac3d88fab9e7952977f18413b4f77069d3e68693b329e2aec5050008000000bcd1d389920100000600ff0300007b226e756d626572223a333335353735332c227472616e73616374696f6e5f726f6f74223a2261646362303336386634613465363230613063373639353434643439326137636133613730366232323863323337636530303036373738396131366339353364222c226761735f75736564223a33313130393630342c2276657273696f6e223a3739323633333536303233373334353238322c22726563656970745f726f6f74223a2266336664343539323132646132336330306466316263383938643430343963663438643633366639656630663634613334313562313762663562336461656464222c2268617368223a2263356637376439356432303364333062316131653463356535313130373032316335623761373639323935643664333634313935613538376531383535386232222c22706172656e745f68617368223a2263663532336431656336383132376163336438386661623965373935323937376631383431336234663737303639643365363836393362333239653261656335222c2273746174655f726f6f74223a2238373630316539366335616464376564313364386666373161353936333437383134306365393761643538333736626534333564633338323232653539626264222c2274696d657374616d70223a313732383838393231333337322c226c6f675f626c6f6f6d223a223031303030303030303030303030303030313030303030303030303030303030303030303030303030303030303030303830303030303030303030303030303030303038303030303030303030303030303030303030303030303030303030303030303030303038303030303030303030303030303030303030303030343030303030303030303030303030303032303034303030303030303030303030313030303030303030303030303030313030303030303030303030303030303030303030303030303030303030303030303030303030303032303030313030303130303030303030303030303230303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303031303030303030303030303030303030303030303030303030303030343030303030303030303030303030303030303030303031303030303030313030303030303030303030303030303030303030303030303030313030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303430303030303030303030303030303030303030303030303030303030303230303030303030303030303030303030303030303030227d07009d0000007b22616d436f6e7472616374496473223a5b22414d5f45564d5f434f4e54524143545f61633831663265642d663037622d343731662d616536662d346438323365663332653334222c22414d5f5741534d5f434f4e54524143545f32616562616232302d323164382d346235372d383636302d333432333663616634333630225d2c226d79636861696e4861736854797065223a22534841323536227d0800f10000007b2270726f6f66223a2266383663663834336238343162326131363539346661373334323266323633386666623835626632306566643033653637623432376634343737653664613061306439306461633937316164323966396433646364653636623736326532363635383331373731626335636636366363353764303466663632623061363936643962393931383937313936323031653638303833333333343639613061336436313235353039386632653934356338363761316138323034633962623731306363383336303264613138373566353534633363316363346435353334222c2274797065223a307d"));
  
          subjectIdentity = MychainSubjectIdentity.builder()
                  .blockHash(anchorState.getHash())
                  .blockHeight(anchorState.getHeight())
                  .cryptoSuite(CryptoSuiteEnum.CRYPTO_SUITE_DEFAULT)
                  .poaCertsPubKeyHash(
                          ListUtil.toList(HexUtil.decodeHex("70151cb5850b90319013a1b120a9589aac581837ffb1408def695df6100898f21b7a84798d2d0859d78b2c64fd6c88e5d3d28a3436d5d4e732dbe4f5c9bbb85a"))
                  ).build();
  
          mychainBta = BlockchainTrustAnchorFactory.createBTAv1(
                  CHAIN_DOMAIN,
                  "mychain",
                  1,
                  RAW_PUBLIC_KEY,
                  SignAlgoEnum.KECCAK256_WITH_SECP256K1,
                  subjectIdentity.encode(),
                  anchorState.getHeight(),
                  anchorState.getHash(),
                  new ContractAddressInfo(amEvm, amWasm).toJson().getBytes(),
                  oid,
                  "".getBytes()
          );
  
          mychainHcdvsService = new MychainHcdvsService();
          Method setLoggerMethod = ReflectUtil.getMethod(MychainHcdvsService.class, "setLogger", Logger.class);
          setLoggerMethod.setAccessible(true);
          setLoggerMethod.invoke(mychainHcdvsService, log);
      }
  
      @Test
      public void testVerifyAnchor() {
          VerifyResult result = mychainHcdvsService.verifyAnchorConsensusState(mychainBta, anchorState);
          Assert.assertNotNull(result);
          Assert.assertTrue(result.isSuccess());
      }
  
      @Test
      public void testVerifyConsensusState() {
          mychainHcdvsService.verifyAnchorConsensusState(mychainBta, anchorState);
          VerifyResult result = mychainHcdvsService.verifyConsensusState(currentState, anchorState);
          Assert.assertNotNull(result);
          Assert.assertTrue(result.isSuccess());
      }
  
      @Test
      public void testVerifyCrossChainMessage() {
          mychainHcdvsService.verifyAnchorConsensusState(mychainBta, anchorState);
          mychainHcdvsService.verifyConsensusState(currentState, anchorState);
          VerifyResult result = mychainHcdvsService.verifyCrossChainMessage(currMessage, currentState);
          Assert.assertNotNull(result);
          Assert.assertTrue(result.isSuccess());
      }
  }
  