以太坊多重钱包离线签名

pragma solidity ^0.4.23;

contract MultiSign {

    uint public nonce;                 
    uint public threshold;             // 满足threshold个签名即可转账
    mapping (address => bool) owners; // 共同拥有人
    address[] public ownersArr;        // 共同拥有人地址
    
    modifier isManager{
        require(
            owners[msg.sender] == true);
        _;
    }
    //充值事件
    event DepositFunds(address from, uint amount);
    //转账事件
    event TransferFunds(address to, uint amount);

    constructor(uint threshold_, address[] owners_) public {
        require(owners_.length <= 10 && threshold_ <= owners_.length && threshold_ != 0);
        for (uint i=0; i<owners_.length; i++) {
            require(owners_[i] != address(0x0) && owners[owners_[i]] == false);
            owners[owners_[i]] = true;
        }
        ownersArr = owners_;
        threshold = threshold_;
    }

    //转账
    function executeTransfer(uint8[] sigV, bytes32[] sigR, bytes32[] sigS, address destination, uint value, bytes data) isManager public{
        require(sigR.length == threshold);
        require(sigR.length == sigS.length && sigR.length == sigV.length);
        bytes32 txHash = keccak256(byte(0x19), byte(0), address(this), destination, value, data, nonce);

        bytes memory prefix = "\x19Ethereum Signed Message:\n32";
        for (uint i = 0; i < threshold; i++) {
            bytes32 prefixedHash = keccak256(prefix, txHash);
            address recovered = ecrecover(prefixedHash, sigV[i], sigR[i], sigS[i]);
            require(recovered != address(0x0) && owners[recovered] == true);
        }
        require(address(destination).call.value(value)(data));
        nonce = nonce + 1;
        emit TransferFunds(destination, value);
    }
    
    function balanceOf() public view returns(uint){
        return address(this).balance;
    }

     //充值
     function () public payable{
        emit DepositFunds(msg.sender, msg.value);
    }

}

测试:

package com.osp.blockchain.eth.sign.test;

import static org.web3j.tx.Contract.GAS_LIMIT;
import static org.web3j.tx.ManagedTransaction.GAS_PRICE;

import java.math.BigInteger;
import java.util.Collections;

import org.web3j.crypto.Credentials;
import org.web3j.crypto.Hash;
import org.web3j.crypto.Sign;
import org.web3j.utils.Convert;
import org.web3j.utils.Numeric;

import com.osp.blockchain.eth.client.Web3JClient;
import com.osp.blockchain.eth.transaction.ETHTransaction;
import com.osp.blockchain.eth.wallet.ETHWallet;

/**
* 多重签名钱包交易测试
*
* @author zmc
*
*/
public class SignTest {

// 0xc23a4fd38ba45f6e7d66aa9dc892fac683238c29
// 0xf7e5da402d15cf1f6c954bad4b402a58fac5a6fa
public static final String RPCAddress = "http://10.20.31.114:8545/";
Credentials credentials = Credentials.create("f5b37f8daa631f49e64124b41a1f4768b6e755fc906781614024772710711cf0");
public MultiSign_sol_MultiSign multi = MultiSign_sol_MultiSign.load("0xf7e5da402d15cf1f6c954bad4b402a58fac5a6fa",
Web3JClient.getClient(RPCAddress), credentials, GAS_PRICE, GAS_LIMIT);

public static void main(String[] args) throws Exception {
System.out.println(new SignTest().verifyAddress());
// new SignTest().createContract();
}

/**
* 创建合约
*/
public void createContract() {
String data = "0x608060405234801561001057600080fd5b5061042f806100206000396000f300608060405260043610610057576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680630a5606a21461005c5780631d972d41146100f65780636eceb96f14610151575b600080fd5b34801561006857600080fd5b506100b46004803603810190808035600019169060200190929190803560ff169060200190929190803560001916906020019092919080356000191690602001909291905050506101c3565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561010257600080fd5b50610137600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610303565b604051808215151515815260200191505060405180910390f35b34801561015d57600080fd5b506101a96004803603810190808035600019169060200190929190803560ff16906020019092919080356000191690602001909291908035600019169060200190929190505050610323565b604051808215151515815260200191505060405180910390f35b6000606060006040805190810160405280601c81526020017f19457468657265756d205369676e6564204d6573736167653a0a333200000000815250915081876040518083805190602001908083835b6020831015156102385780518252602082019150602081019050602083039250610213565b6001836020036101000a03801982511681845116808217855250505050505090500182600019166000191681526020019250505060405180910390209050600181878787604051600081526020016040526040518085600019166000191681526020018460ff1660ff1681526020018360001916600019168152602001826000191660001916815260200194505050505060206040516020810390808403906000865af11580156102ed573d6000803e3d6000fd5b5050506020604051035192505050949350505050565b60006020528060005260406000206000915054906101000a900460ff1681565b600080600186868686604051600081526020016040526040518085600019166000191681526020018460ff1660ff1681526020018360001916600019168152602001826000191660001916815260200194505050505060206040516020810390808403906000865af115801561039d573d6000803e3d6000fd5b5050506020604051035190506000808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff169150819150509493505050505600a165627a7a72305820284ccf723039373644f6d49849d7572140dd16e466af3fd4c40afe94c7195bc10029";
String accountAddress = "0x481a4f58ac488cd09e09321378c867999887f2af";
// 0x481a4f58ac488cd09e09321378c867999887f2af证书私钥
Credentials credentials = ETHWallet.getCredentials(
new BigInteger("28048228501442048189267956591015494076577030861667140253009833017711730989442"));
BigInteger nonce = ETHTransaction.ethGetTransactionCount(Web3JClient.getClient(RPCAddress), accountAddress);
BigInteger value = Convert.toWei("0", Convert.Unit.ETHER).toBigInteger();
String txnHashString = ETHTransaction.createContractTransaction(Web3JClient.getClient(RPCAddress), credentials,
nonce, GAS_PRICE, GAS_LIMIT, value, data);
System.out.println("交易Hash====" + txnHashString);
}

public String verifyAddress() throws Exception {
String hash = Hash.sha3String("https://steemit.com/@chaimyu");
Credentials credentials = Credentials
.create("f5b37f8daa631f49e64124b41a1f4768b6e755fc906781614024772710711cf0");
System.out.println(credentials.getAddress());
byte[] data = Numeric.hexStringToByteArray(hash);
Sign.SignatureData signature = Sign.signPrefixedMessage(data, credentials.getEcKeyPair());
System.out.println("R: " + Numeric.toHexString(signature.getR()));
System.out.println("S: " + Numeric.toHexString(signature.getS()));
System.out.println("V: " + Numeric.toBigInt(signature.getV()));
byte[] myStringInByte = Numeric.hexStringToByteArray(hash);

String dataString = this.multi
.verify_addr(myStringInByte, Numeric.toBigInt(signature.getV()), signature.getR(), signature.getS())
.send();
return dataString;
}

// String to 64 length HexString (equivalent to 32 Hex lenght)
public static String asciiToHex(String asciiValue) {
char[] chars = asciiValue.toCharArray();
StringBuffer hex = new StringBuffer();
for (int i = 0; i < chars.length; i++) {
hex.append(Integer.toHexString((int) chars[i]));
}

return hex.toString() + "".join("", Collections.nCopies(32 - (hex.length() / 2), "00"));
}

}

  

posted @ 2019-11-19 18:34  人艰不拆_zmc  阅读(634)  评论(0编辑  收藏  举报