前言:

需求:从公链拉取所有交易进行原始交易解析,匹配本地钱包地址根据交易确认数进行充值的确认。

方案:

  • 初始化区块信息(高度、块hash等)持久化到数据库
  • 根据区块hash从主链获取交易txs
  • 解析txs对比充值钱包地址,存储充值信息、Unspent交易信息
  • 更新数据库里的区块信息
  • 进行线程的循环调用即可

1.初始化区块信息到数据库

@Order(value = 1)
@Service
public class BtcoinChargeServiceImpl implements  CommandLineRunner {private Logger LOG = LoggerFactory.getLogger("btcoin");private static final String RECHARSTATE = "0";private static final String CURRENTTYPE = "BTC";//初始化区块信息@Overridepublic void run(String... arg0) throws Exception {//从数据读取信息进行判断CoinBlockInfo blockInfo = blockMapper.selectByCoinType("BTC");if (null == blockInfo || blockInfo.getBlockHeight() == 0) {int blockCount = (int) btcService.getBlockCount();String blockHash = btcService.getBlockHash(blockCount).toString();LOG.info("=== [BTC] init block height is : {} and block hash is :{} start !! ===", blockCount, blockHash);CoinBlockInfo blockInfos = new CoinBlockInfo();blockInfos.setBlockHeight(blockCount); //高度blockInfos.setBlockHash(blockHash);//块HashblockInfos.setCoinType(CURRENTTYPE);blockInfos.setCreateTime(new Date());blockInfos.setRemark("first record");boolean res = blockMapper.insert(blockInfos) > 0 ? true : false;if (res)LOG.info("=== [BTC] init block success !!");}}}

  2.  区块hash从主链获取交易txs并进行解析

//比特币充值交易信息@Service
public class BtcoinChargeServiceImpl implements BtcoinChargeService{private Logger LOG = LoggerFactory.getLogger("btcoin");private static final String RECHARSTATE = "0";private static final String CURRENTTYPE = "BTC";//对比确认次数public int confirm = 9;@Transactional(rollbackFor = CoinException.class)@Overridepublic Object rechargeRecordFromBlockTx(List<UserAccount> userList) throws CoinException {Map<Object, Object> result = new HashMap<Object, Object>();try {// current block from mysqlCoinBlockInfo blockInfo = blockMapper.selectByCoinType("BTC");int parseBlockCount = blockInfo.getBlockHeight(); int blockCount = (int) btcService.getBlockCount(); String blockHash = null;if (parseBlockCount > 0) {LOG.info("=== [BTC] the current BTC block height is {}, and the processing block height is {}. ===", blockCount, parseBlockCount);if (blockCount > parseBlockCount) {int current = parseBlockCount + 1;if ((blockCount - parseBlockCount) >= confirm) {try {blockHash = btcService.getBlockHash(current).toString();//LOG.info("=== [BTC] scan block [\theight:{}\t], [\thash:{}\t] begins !!! ===", current, blockHash);if (parseTransactionInfo(userList, blockHash, current)) {LOG.info("=== [BTC] end of scan block [\theight:{}\t], [\thash:{}\t] !!! ===", current, blockHash);/* current height */blockInfo.setBlockHeight(current);blockInfo.setBlockHash(blockHash);blockInfo.setUpdateTime(new Date());if (blockMapper.updateByPrimaryKeySelective(blockInfo) > 0 ? true : false) {LOG.info("=== [BTC-LOCAL] current block height: {}, previous block height: {} ===", current, parseBlockCount);}current++;} /*else {break;}*/} catch (CoinException e) {LOG.info("=== [BTC] getting block information failed through block height.reason:{} ===", e.getMessage(), e);throw new CoinException(e.getMessage());}}}}} catch (CoinException e) {LOG.info("=== com.wallet.bit.service.btc.impl.BtcoinChargeServiceImpl.rechargeRecordFromBlockTx(List<UserAccount>):{} ===", e.getMessage(), e);throw new CoinException(e.getMessage());}return result;}/** 对钱包地址进行比对处理*/private boolean parseTransactionInfo(List<UserAccount> userList, String blockHash, int current) throws CoinException {Map block = (Map) btcService.getblock(blockHash);JSONObject blocks = JSONObject.parseObject(JSON.toJSONString(block));if (isError(blocks)) {LOG.info("=== [BTC] handling blockTransactions data errors !! ===");return false;}JSONArray txs = JSONArray.parseArray(blocks.getString("tx"));LOG.info("=== [BTC] scan block [\theight:{}\t], [\thash:{}\t], [\ttotal transactions:{}\t] begins !!! ===", current, blockHash, txs.size());for (int i = 0, len = txs.size(); i < len; i++) {String txId = txs.getString(i);// deal block//LOG.info("=== [BTC] scan block [\theight:{}\t], [\thash:{}\t], [\ttx:{}\t] begins !!! ===", current, blockHash, txId);parseBlockInfoByTxId(userList, txId, current);// LOG.info("=== [BTC] current blockheight:{},blockhash:{},txhash:{} operation completion!!", current, blockHash, txId);}return true;}/*** 处理块信息* @throws CoinException* @Title: parseBlockInfoByTxId @param @param userList @param @param txId @param @throws CoinException 参数 @return void 返回类型 @throws*/private boolean parseBlockInfoByTxId(List<UserAccount> userList, String txId, int height) throws CoinException {try {Map transaction = (Map) btcService.getTrawtransaction(txId, 1);JSONObject info = JSONObject.parseObject(JSON.toJSONString(transaction));Integer confirm = info.getInteger("confirmations");Long time = info.getLong("time");Long blocktime = info.getLong("blocktime");// vinJSONArray vins = JSONArray.parseArray(info.getString("vin"));double sumvin = 0;double sumvout = 0;List<String> formAddress = new ArrayList<>();for (int z = 0, lenz = vins.size(); z < lenz; z++) {JSONObject vin = JSONObject.parseObject(vins.getString(z));String txid = vin.getString("txid");if (null != txid) {Integer vinN = vin.getInteger("vout");//              LOG.info("=== [BTC] search vins txid:{} trawtransaction! ===", txid);Map parentTransaction = (Map) btcService.getTrawtransaction(txid, 1);JSONObject parentInfo = JSONObject.parseObject(JSON.toJSONString(parentTransaction));JSONArray vouts = JSONArray.parseArray(parentInfo.getString("vout"));for (int j = 0, leg = vouts.size(); j < leg; j++) {JSONObject vout = vouts.getJSONObject(j);Integer n = vout.getInteger("n");if (n == vinN) { // 收款金额sumvin += vout.getDouble("value");JSONObject scriptPubKey = vout.getJSONObject("scriptPubKey");JSONArray addresses = scriptPubKey.getJSONArray("addresses");formAddress.add(addresses.getString(0));}}}}// voutJSONArray vouts = JSONArray.parseArray(info.getString("vout"));for (int x = 0, lenx = vouts.size(); x < lenx; x++) {JSONObject vout = JSONObject.parseObject(vouts.getString(x));Integer n = vout.getInteger("n");JSONObject scriptPubKey = vout.getJSONObject("scriptPubKey");String hex = scriptPubKey.getString("hex");String type = scriptPubKey.getString("type");// usdt chargeif (!type.equals("nulldata")) {if (n == 0) { // recharge = 0 , utxoJSONArray addresses = scriptPubKey.getJSONArray("addresses");String receviceAddr = addresses.getString(0);for (UserAccount user : userList) {Long userId = user.getUserId();String userAddress = user.getUserAddress();if (userAddress.equals(receviceAddr)) {double amount = vout.getDouble("value");if (amount > 0) {// count feefor (int w = 0, lenw = vouts.size(); w < lenw; w++) {JSONObject feevout = JSONObject.parseObject(vouts.getString(x));sumvout += feevout.getDouble("value");}try {LOG.info("=== [BTC] handling transaction data entry and storage !!! ===");//记录充值信息处理入库} catch (Exception e) {LOG.info("=== [BTC] record user recharge exception:{}  ===", e.getMessage(), e);}}}}}}}} catch (CoinException e) {LOG.info("=== com.wallet.bit.service.btc.impl.BtcoinChargeServiceImpl.parseBlockInfoByTxId(List<UserAccount>, String, int):{} ===", e.getMessage(), e);throw new CoinException(e.getMessage());}return false;}private boolean isError(JSONObject json) {if (json == null || (StringUtils.isNotEmpty(json.getString("error")) && json.get("error") != "null")) {return true;}return false;}}

通过JSON-rpc 进行节点的调用参考:https://blog.csdn.net/u011663149/article/details/87182097

Java BTC、Omni 同步充值交易相关推荐

  1. Java高级-线程同步机制实现

    2019独角兽企业重金招聘Python工程师标准>>> 前言 我们可以在计算机上运行各种计算机软件程序.每一个运行的程序可能包括多个独立运行的线程(Thread). 线程(Threa ...

  2. java的同步关键字_简单了解Java synchronized关键字同步

    简单了解Java synchronized关键字同步 发布于 2021-1-13| 复制链接 摘记:  synchronized synchronized可以用来同步块,同步方法.同步块可以用来更精确 ...

  3. JAVA中线程同步的方法(7种)汇总

    JAVA中线程同步的方法(7种)汇总 同步的方法: 一.同步方法 即有synchronized关键字修饰的方法. 由于java的每个对象都有一个内置锁,当用此关键字修饰方法时, 内置锁会保护整个方法. ...

  4. java实验多线程机制_使用Java多线程的同步机制编写应用程序 PDF 下载

    使用Java多线程的同步机制编写应用程序 PDF 下载 本站整理下载: 相关截图: 主要内容: 一. 实验名称 使用Java多线程的同步机制编写应用程序 二. 实验目的及要求 1.理解并行/并发的概念 ...

  5. Coinbase发生一笔7500枚BTC巨额转出交易 转移金额近2.5亿美元

    据Whale Alert数据显示,美国合规加密货币交易所Coinbase发生一笔7500 BTC巨额转出交易,价值约为237,689,165美元:交易哈希:918ab3747fae55882f5d9d ...

  6. Java内存模型 - 同步八种操作

    Java 内存模型 - 同步操作与规则 Java内存模型 - 同步八种操作 锁定(lock): 作用于主内存中的变量,将他标记为一个线程独享变量. 通常意义上的上锁,就是一个线程正在使用时,其他线程必 ...

  7. Java 异步方法转同步

    Java 异步方法转同步 有一些api提供的方法是异步的,这类的方法大概类型如下: private void asyMethod( String param,RequestCallback callb ...

  8. java中的同步与异步

    经常看到介绍 ArrayList 和HashMap是异步,Vector和HashTable是同步,这里同步是线程安全的,异步不是线程安全的,举例说明: 当创建一个Vector对象时候, Vector ...

  9. Java里面的同步和异步

    在 Java 中,同步(Synchronization)是指一个线程获得了对象的锁,其他线程无法访问这个对象,直到该线程释放了这个对象的锁.同步是用于保证多个线程对共享资源的操作是互斥的,从而避免多线 ...

最新文章

  1. 【转载】关于幂律分布的一个笔记
  2. python 各种推导式玩法
  3. iOS WebView的用法
  4. centos安装ruby
  5. 数据结构与算法--B树原理及实现
  6. splay/fhq-treap 问卷调查反馈—— [JSOI2008]火星人prefix(splay),Strange Queries(fhq-treap)
  7. 屏蔽Idea中不合理的提示警告
  8. 威胁情报工具:更快?更聪明?
  9. 简单易懂的排序算法演示
  10. 所谓“卡常数”的常数到底指什么?
  11. python中水量_Python居然还能用于巨大的工程项目!比如三峡发电量估算系统!
  12. 找出大于200的最小的质数
  13. 旋转矩阵的导数(机器人学)
  14. 无人驾驶计算机控制系统,自动驾驶汽车的无人驾驶系统三大模块是什么?
  15. InnoDB: Assertion failure in thread 140536591259392 in file page0zip.ic
  16. java 发送邮件553错误_使用Java Mail API发送邮件,抛出认证错误553 authentication is required. 解决办法...
  17. Spark【案例】实现黑名单实时过滤
  18. 2020.10.22--AI--立体图形制作、矛盾空间图形设计、3D文字
  19. 诺基亚java模拟器exe,无需模拟器!骁龙810手机成功运行Win10:可开exe程序
  20. 网络抓包工具 wireshark 入门教程

热门文章

  1. 5年Java开发干到月薪38k?当初实习期2.5k的苦我也吃过...
  2. 【C++】Mutex
  3. 嵌套命名实体识别任务简介
  4. MFC使用Create函数创建对话框失败,new出来的对话框内存泄漏
  5. Win10 安装oracle客户端和Navicat Premium出现的问题及解决方法
  6. muduo scoped_ptr详解
  7. 日文半角转全角 java_java将日文半角片假名转成全角的方法
  8. Epson Me xx 打印机清零图解
  9. 销售客户拜访时要获取客户的哪些信息
  10. 在桌面关闭计算机关机不了怎么办,电脑无法正常关机怎么办