Skip to content
This repository has been archived by the owner on Jan 25, 2021. It is now read-only.

Commit

Permalink
Merge pull request #29 from O3Labs/ontttttt
Browse files Browse the repository at this point in the history
onttttttt
  • Loading branch information
apisit authored Jul 20, 2018
2 parents c9e1812 + b001eec commit 8265275
Show file tree
Hide file tree
Showing 13 changed files with 328 additions and 82 deletions.
2 changes: 1 addition & 1 deletion neoutils/btckey/btckey_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -492,7 +492,7 @@ func TestGenerateKey(t *testing.T) {

func TestSignData(t *testing.T) {

wif := "L5hbtj4mX16TnVnQTdda4znw1nvt3DB7DVxU6sP97RDVMtufQwbT"
wif := ""
var priv PrivateKey
err := priv.FromWIF(wif)

Expand Down
37 changes: 18 additions & 19 deletions neoutils/multisig.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,20 @@ package neoutils

import (
"fmt"
"sort"

"github.com/o3labs/neo-utils/neoutils/btckey"
"github.com/o3labs/neo-utils/neoutils/smartcontract"
)

type MultiSigInterface interface {
CreateMultiSignedAddress(publicKeys [][]byte) error
CreateMultiSigRedeemScript(numerOfRequiredSignature int, publicKeys [][]byte) ([]byte, error)
}

type MultiSig struct{}

var _ MultiSigInterface = (*MultiSig)(nil)

//TODO: finish this
func (m *MultiSig) CreateMultiSignedAddress(publicKeys [][]byte) error {
return nil
}

//TODO: finish this
func (m *MultiSig) CreateMultiSigRedeemScript(numerOfRequiredSignature int, publicKeys [][]byte) ([]byte, error) {
numberOfPublicKeys := len(publicKeys)
if numberOfPublicKeys <= 1 {
Expand All @@ -31,19 +26,23 @@ func (m *MultiSig) CreateMultiSigRedeemScript(numerOfRequiredSignature int, publ
return nil, fmt.Errorf("Number of required Signature is more than public keys provided.")
}

sb := smartcontract.NewScriptBuilder()
sb.EmitPush(numerOfRequiredSignature)
for _, publicKey := range publicKeys {
// pub := btckey.PublicKey{}
// err := pub.FromBytes(publicKey)
// if err != nil {
// return err
// }
//this publicKey is already a compressed bytes so we can add that directly
sb.EmitPush(publicKey)
//sort public key
keys := []btckey.PublicKey{}
for _, pb := range publicKeys {
publicKey := btckey.PublicKey{}
publicKey.FromBytes(pb)
keys = append(keys, publicKey)
}

sb.EmitPush(numberOfPublicKeys)
sb.EmitPush(smartcontract.CHECKMULTISIG)
//https://golang.org/pkg/math/big/#Int.Cmp
sort.SliceStable(keys, func(i, j int) bool { return keys[i].Point.X.Cmp(keys[j].Point.X) == -1 })

sb := smartcontract.NewScriptBuilder()
sb.Push(numerOfRequiredSignature)
for _, publicKey := range keys {
sb.Push(publicKey.ToBytes())
}
sb.Push(numberOfPublicKeys)
sb.PushOpCode(smartcontract.CHECKMULTISIG)
return sb.ToBytes(), nil
}
56 changes: 56 additions & 0 deletions neoutils/multisig_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package neoutils_test

import (
"log"
"sort"
"testing"

"github.com/o3labs/neo-utils/neoutils"
"github.com/o3labs/neo-utils/neoutils/btckey"
)

func TestGenerateMultiSigAddress(t *testing.T) {

pb1 := "02e77ff280db51ef3638009f11947c544ed094d4e5f2d96a9e654dc817bc3a8986"
pb2 := "024da93f9a66981e499b36ce763e57fd89a47a052e86d40b42f81708c40fe9eff0"
require := 2
pubKeys := [][]byte{}

pubKeys = append(pubKeys, neoutils.HexTobytes(pb1))
pubKeys = append(pubKeys, neoutils.HexTobytes(pb2))

multisign := neoutils.MultiSig{}
vmCode, err := multisign.CreateMultiSigRedeemScript(require, pubKeys)
if err != nil {
log.Printf("%v", err)
}
log.Printf("vm code %x", vmCode)

multisigAddress := neoutils.VMCodeToNEOAddress(vmCode)
log.Printf("multi sig address %v", multisigAddress)
if multisigAddress != "AKo8k27H5nCG8MwSirmnraH6uUG6fQQVC2" {
t.Fail()
}
}

func TestSortPublicKeys(t *testing.T) {
p1Hex := "02e77ff280db51ef3638009f11947c544ed094d4e5f2d96a9e654dc817bc3a8986"
p2Hex := "024da93f9a66981e499b36ce763e57fd89a47a052e86d40b42f81708c40fe9eff0"
p3Hex := "035ca1deea29ccb25a3a4d32701a0e735f76f3b44d233e23930cd74b68a63d10c3"
p1 := btckey.PublicKey{}
p2 := btckey.PublicKey{}
p3 := btckey.PublicKey{}
p1.FromBytes(neoutils.HexTobytes(p1Hex))
p2.FromBytes(neoutils.HexTobytes(p2Hex))
p3.FromBytes(neoutils.HexTobytes(p3Hex))

keys := []btckey.PublicKey{p3, p1, p2}

//https://golang.org/pkg/math/big/#Int.Cmp
sort.SliceStable(keys, func(i, j int) bool { return keys[i].Point.X.Cmp(keys[j].Point.X) == -1 })
for _, k := range keys {
log.Printf("%x", k.ToBytes())
}
//correct order is p2, p3, p1

}
77 changes: 41 additions & 36 deletions neoutils/native_asset.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (

type NativeAssetInterface interface {
SendNativeAssetRawTransaction(wallet Wallet, asset smartcontract.NativeAsset, amount float64, to smartcontract.NEOAddress, unspent smartcontract.Unspent, attributes map[smartcontract.TransactionAttribute][]byte) ([]byte, string, error)
GenerateRawTx(fromAddress string, asset smartcontract.NativeAsset, amount float64, to smartcontract.NEOAddress, unspent smartcontract.Unspent, attributes map[smartcontract.TransactionAttribute][]byte) ([]byte, string, error)
}

type NativeAsset struct {
Expand All @@ -23,42 +24,14 @@ func UseNativeAsset(networkFeeAmount smartcontract.NetworkFeeAmount) NativeAsset
var _ NativeAssetInterface = (*NativeAsset)(nil)

func (n *NativeAsset) SendNativeAssetRawTransaction(wallet Wallet, asset smartcontract.NativeAsset, amount float64, to smartcontract.NEOAddress, unspent smartcontract.Unspent, attributes map[smartcontract.TransactionAttribute][]byte) ([]byte, string, error) {
//New invocation transaction struct and fill with all necessary data
tx := smartcontract.NewContractTransaction()

amountToSend := amount
assetToSend := asset

//generate transaction inputs
txInputs, err := smartcontract.NewScriptBuilder().GenerateTransactionInput(unspent, assetToSend, amountToSend, n.NetworkFeeAmount)
if err != nil {
return nil, "", err
}
//transaction inputs
tx.Inputs = txInputs

//generate transaction outputs
txAttributes, err := smartcontract.NewScriptBuilder().GenerateTransactionAttributes(attributes)
tx, txID, err := n.GenerateRawTx(wallet.Address, asset, amount, to, unspent, attributes)
if err != nil {
return nil, "", err
}
//transaction attributes
tx.Attributes = txAttributes

sender := smartcontract.ParseNEOAddress(wallet.Address)
receiver := to
txOutputs, err := smartcontract.NewScriptBuilder().GenerateTransactionOutput(sender, receiver, unspent, assetToSend, amountToSend, n.NetworkFeeAmount)
if err != nil {
log.Printf("%v", err)
return nil, "", err
}

tx.Outputs = txOutputs

//begin signing process and invocation script
//begin signing
privateKeyInHex := bytesToHex(wallet.PrivateKey)

signedData, err := Sign(tx.ToBytes(), privateKeyInHex)
signedData, err := Sign(tx, privateKeyInHex)
if err != nil {
log.Printf("err signing %v", err)
return nil, "", err
Expand All @@ -68,17 +41,49 @@ func (n *NativeAsset) SendNativeAssetRawTransaction(wallet Wallet, asset smartco
SignedData: signedData,
PublicKey: wallet.PublicKey,
}
// try to verify it
// hash := sha256.Sum256(tx.ToBytes())
// valid := Verify(wallet.PublicKey, signedData, hash[:])
// log.Printf("verify tx %v", valid)

scripts := []interface{}{signature}
txScripts := smartcontract.NewScriptBuilder().GenerateVerificationScripts(scripts)
//assign scripts to the tx
tx.Script = txScripts
//end signing process

//concat data
endPayload := []byte{}
endPayload = append(endPayload, tx.ToBytes()...)
endPayload = append(endPayload, tx...)
endPayload = append(endPayload, txScripts...)

txID := tx.ToTXID()
return endPayload, txID, nil
}

func (n *NativeAsset) GenerateRawTx(fromAddress string, asset smartcontract.NativeAsset, amount float64, to smartcontract.NEOAddress, unspent smartcontract.Unspent, attributes map[smartcontract.TransactionAttribute][]byte) ([]byte, string, error) {
//New invocation transaction struct and fill with all necessary data
tx := smartcontract.NewContractTransaction()

//generate transaction inputs
txInputs, err := smartcontract.NewScriptBuilder().GenerateTransactionInput(unspent, asset, amount, n.NetworkFeeAmount)
if err != nil {
return nil, "", err
}
tx.Inputs = txInputs

txAttributes, err := smartcontract.NewScriptBuilder().GenerateTransactionAttributes(attributes)
if err != nil {
return nil, "", err
}

tx.Attributes = txAttributes

sender := smartcontract.ParseNEOAddress(fromAddress)

txOutputs, err := smartcontract.NewScriptBuilder().GenerateTransactionOutput(sender, to, unspent, asset, amount, n.NetworkFeeAmount)
if err != nil {
log.Printf("%v", err)
return nil, "", err
}

tx.Outputs = txOutputs

return tx.ToBytes(), tx.ToTXID(), nil
}
80 changes: 75 additions & 5 deletions neoutils/native_asset_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package neoutils_test

import (
"crypto/sha256"
"fmt"
"log"
"strconv"
Expand Down Expand Up @@ -82,19 +83,19 @@ func TestSendingGAS(t *testing.T) {
t.Fail()
}

unspent, err := utxoFromO3Platform("private", privateNetwallet.Address)
unspent, err := utxoFromO3Platform("test", privateNetwallet.Address)
if err != nil {
log.Printf("error %v", err)
t.Fail()
return
}
asset := smartcontract.GAS
amount := float64(10)
toAddress := "AaZmUKtuNEA2NTsjKGyjoAnFLxWsuQgeP3"
amount := float64(0.1)
toAddress := "AKo8k27H5nCG8MwSirmnraH6uUG6fQQVC2" //this is multi signature adddress 3/2
to := smartcontract.ParseNEOAddress(toAddress)
remark := "O3TX"
// remark := "O3TX"
attributes := map[smartcontract.TransactionAttribute][]byte{}
attributes[smartcontract.Remark1] = []byte(remark)
// attributes[smartcontract.Remark1] = []byte(remark)

fee := smartcontract.NetworkFeeAmount(0.0)
nativeAsset := neoutils.UseNativeAsset(fee)
Expand Down Expand Up @@ -140,3 +141,72 @@ func TestSendingNEO(t *testing.T) {
}
log.Printf("%v\n%x", txid, rawtx)
}

func TestSendingGASFromMultiSig(t *testing.T) {
fromAddress := "AKo8k27H5nCG8MwSirmnraH6uUG6fQQVC2" //this is multi signature adddress 3/2
unspent, err := utxoFromO3Platform("test", fromAddress)
if err != nil {
log.Printf("error %v", err)
t.Fail()
return
}
asset := smartcontract.GAS
amount := float64(0.1)

toAddress := "AKo8k27H5nCG8MwSirmnraH6uUG6fQQVC2"
to := smartcontract.ParseNEOAddress(toAddress)

attributes := map[smartcontract.TransactionAttribute][]byte{}

fee := smartcontract.NetworkFeeAmount(0.0)
nativeAsset := neoutils.UseNativeAsset(fee)
rawtx, txid, err := nativeAsset.GenerateRawTx(fromAddress, asset, amount, to, unspent, attributes)
if err != nil {
log.Printf("error sending natie %v", err)
t.Fail()
return
}
log.Printf("txid %v\n", txid)
log.Printf("raw %x\n", rawtx)

wallet1, _ := neoutils.GenerateFromWIF("")
wallet2, _ := neoutils.GenerateFromWIF("")

wallets := []*neoutils.Wallet{wallet1, wallet2}

signatures := []smartcontract.TransactionSignature{}

for _, w := range wallets {
privateKeyInHex := neoutils.BytesToHex(w.PrivateKey)

signedData, err := neoutils.Sign(rawtx, privateKeyInHex)
if err != nil {
log.Printf("err signing %v", err)
return
}

signature := smartcontract.TransactionSignature{
SignedData: signedData,
PublicKey: w.PublicKey,
}
signatures = append(signatures, signature)

log.Printf("pub key = %x\n", w.PublicKey)
log.Printf("signedData = %x\n", signedData)
hash := sha256.Sum256(rawtx)
valid := neoutils.Verify(w.PublicKey, signedData, hash[:])
log.Printf("valid %v", valid)
}

verificationScripts := smartcontract.NewScriptBuilder().GenerateVerificationScriptsMultiSig(signatures)

//concat data
endPayload := []byte{}
endPayload = append(endPayload, rawtx...)
endPayload = append(endPayload, verificationScripts...)

redeemScript := "5221024da93f9a66981e499b36ce763e57fd89a47a052e86d40b42f81708c40fe9eff02102e77ff280db51ef3638009f11947c544ed094d4e5f2d96a9e654dc817bc3a898652ae"
b := neoutils.HexTobytes(redeemScript)
length := len(b)
log.Printf("%x%x%v", endPayload, length, redeemScript)
}
2 changes: 0 additions & 2 deletions neoutils/neorpc/rpc.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"bytes"
"encoding/json"
"fmt"
"log"
"net/http"
"net/url"
"time"
Expand Down Expand Up @@ -156,7 +155,6 @@ func (n *NEORPCClient) GetTokenBalance(tokenHash string, neoAddress string) Toke
return TokenBalanceResponse{}
}
adddressScriptHash := fmt.Sprintf("%x", b)
log.Printf("adddressScriptHash %v", adddressScriptHash)
input := NewInvokeFunctionStackByteArray(adddressScriptHash)
args = append(args, input)

Expand Down
4 changes: 2 additions & 2 deletions neoutils/neorpc/rpc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,12 +87,12 @@ func TestGetAccountState(t *testing.T) {
}

func TestGetTokenBalance(t *testing.T) {
client := neorpc.NewClient("http://localhost:30333")
client := neorpc.NewClient("http://seed3.aphelion-neo.com:10332")
if client == nil {
t.Fail()
}

result := client.GetTokenBalance("0xc2b0fed82b8fa28c358f99849136f45f057bb6fe", "APLNwfJTHp1MBHYNeMAxkeqNCquLpBVjcD")
result := client.GetTokenBalance("fc732edee1efdf968c23c20a9628eaa5a6ccb934", "AcydXy1MvrzaT8qD3Qe4B8mqEoinTvRy8U")
log.Printf("%+v", result.Result)
}

Expand Down
22 changes: 22 additions & 0 deletions neoutils/ont.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package neoutils

import (
"log"

"github.com/o3labs/ont-mobile/ontmobile"
)

func OntologyTransfer(endpoint string, gasPrice uint, gasLimit uint, wif string, asset string, to string, amount float64) (string, error) {
raw, err := ontmobile.Transfer(gasPrice, gasLimit, wif, asset, to, amount)
if err != nil {
return "", err
}
log.Printf("%x", raw.Data)
return "", nil
// txid, err := ontmobile.SendRawTransaction(endpoint, fmt.Sprintf("%x", raw.Data))
// if err != nil {
// return "", err
// }

// return txid, nil
}
Loading

0 comments on commit 8265275

Please sign in to comment.