以太坊多重钱包离线签名
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"));
}
}
浙公网安备 33010602011771号