diff --git a/cmd/v8/main.go b/cmd/v8/main.go index 6f34bac37..855ffd96c 100644 --- a/cmd/v8/main.go +++ b/cmd/v8/main.go @@ -24,6 +24,7 @@ import ( "os" "time" + "github.com/nebulasio/go-nebulas/core" "github.com/nebulasio/go-nebulas/core/state" "github.com/nebulasio/go-nebulas/nf/nvm" "github.com/nebulasio/go-nebulas/storage" @@ -34,9 +35,9 @@ func main() { mem, _ := storage.NewMemoryStorage() context, _ := state.NewWorldState(nil, mem) - contract, _ := context.CreateContractAccount([]byte("account2"), nil) + contract, _ := context.CreateContractAccount([]byte("account2"), nil, nil) - ctx, err := nvm.NewContext(nil, nil, contract, context) + ctx, err := nvm.NewContext(core.MockBlock(nil, 1), nil, contract, context) if err == nil { engine := nvm.NewV8Engine(ctx) result, err := engine.RunScriptSource(string(data), 0) diff --git a/core/block.go b/core/block.go index b142ddc0a..3379075a6 100644 --- a/core/block.go +++ b/core/block.go @@ -1290,3 +1290,11 @@ func LoadBlockFromStorage(hash byteutils.Hash, chain *BlockChain) (*Block, error block.storage = chain.storage return block, nil } + +// MockBlock nf/nvm/engine.CheckV8Run() & cmd/v8/main.go +func MockBlock(header *BlockHeader, height uint64) *Block { + return &Block{ + header: header, + height: height, + } +} diff --git a/core/compatibility.go b/core/compatibility.go index 702088dac..16d88db18 100644 --- a/core/compatibility.go +++ b/core/compatibility.go @@ -48,16 +48,22 @@ var ( // NOTE: versions should be arranged in ascending order // map[libname][versions] V8JSLibs = map[string][]string{ - "execution_env.js": {"1.0.0", "1.0.1"}, - "bignumber.js": {"1.0.0", "1.0.1"}, - "random.js": {"1.0.0", "1.0.1"}, - "date.js": {"1.0.0", "1.0.1"}, - "blockchain.js": {"1.0.0"}, - "console.js": {"1.0.0"}, - "event.js": {"1.0.0"}, - "storage.js": {"1.0.0"}, - "crypto.js": {"1.0.1"}, - "uint.js": {"1.0.1"}, + "execution_env.js": {"1.0.0", "1.0.1"}, + "bignumber.js": {"1.0.0", "1.0.1"}, + "random.js": {"1.0.0", "1.0.1"}, + "date.js": {"1.0.0", "1.0.1"}, + "tsc.js": {"1.0.0"}, + "util.js": {"1.0.0"}, + "esprima.js": {"1.0.0"}, + "assert.js": {"1.0.0"}, + "instruction_counter.js": {"1.0.0"}, + "typescriptServices.js": {"1.0.0"}, + "blockchain.js": {"1.0.0"}, + "console.js": {"1.0.0"}, + "event.js": {"1.0.0"}, + "storage.js": {"1.0.0"}, + "crypto.js": {"1.0.1"}, + "uint.js": {"1.0.1"}, } ) diff --git a/core/state/account_state.go b/core/state/account_state.go index 3131b945f..1810c3015 100644 --- a/core/state/account_state.go +++ b/core/state/account_state.go @@ -406,3 +406,12 @@ func (as *accountState) String() string { as.storage, ) } + +// MockAccount nf/nvm/engine.CheckV8Run() & cmd/v8/main.go +func MockAccount(version string) Account { + return &account{ + contractMeta: &corepb.ContractMeta{ + Version: version, + }, + } +} diff --git a/nf/nvm/cfuncs.go b/nf/nvm/cfuncs.go index 299572ffc..8fc789def 100644 --- a/nf/nvm/cfuncs.go +++ b/nf/nvm/cfuncs.go @@ -42,6 +42,12 @@ int VerifyAddressFunc(void *handler, const char *address, size_t *gasCnt); // event. void EventTriggerFunc(void *handler, const char *topic, const char *data, size_t *gasCnt); +// crypto +char *Sha256Func(const char *data, size_t *gasCnt); +char *Sha3256Func(const char *data, size_t *gasCnt); +char *Ripemd160Func(const char *data, size_t *gasCnt); +char *RecoverAddressFunc(int alg, const char *data, const char *sign, size_t *gasCnt); + // The gateway functions. void V8Log_cgo(int level, const char *msg) { V8Log(level, msg); @@ -82,5 +88,18 @@ void EventTriggerFunc_cgo(void *handler, const char *topic, const char *data, si EventTriggerFunc(handler, topic, data, gasCnt); }; +char *Sha256Func_cgo(const char *data, size_t *gasCnt) { + return Sha256Func(data, gasCnt); +} +char *Sha3256Func_cgo(const char *data, size_t *gasCnt) { + return Sha3256Func(data, gasCnt); +} +char *Ripemd160Func_cgo(const char *data, size_t *gasCnt) { + return Ripemd160Func(data, gasCnt); +} +char *RecoverAddressFunc_cgo(int alg, const char *data, const char *sign, size_t *gasCnt) { + return RecoverAddressFunc(alg, data, sign, gasCnt); +} + */ import "C" diff --git a/nf/nvm/crypto.go b/nf/nvm/crypto.go new file mode 100644 index 000000000..89a30beb8 --- /dev/null +++ b/nf/nvm/crypto.go @@ -0,0 +1,99 @@ +// Copyright (C) 2018 go-nebulas authors +// +// This file is part of the go-nebulas library. +// +// the go-nebulas library is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// the go-nebulas library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with the go-nebulas library. If not, see . +// + +package nvm + +import "C" + +import ( + "github.com/nebulasio/go-nebulas/core" + "github.com/nebulasio/go-nebulas/crypto/hash" + "github.com/nebulasio/go-nebulas/crypto/keystore" + "github.com/nebulasio/go-nebulas/util/byteutils" + "github.com/nebulasio/go-nebulas/util/logging" + "github.com/sirupsen/logrus" +) + +// Sha256Func .. +//export Sha256Func +func Sha256Func(data *C.char, gasCnt *C.size_t) *C.char { + s := C.GoString(data) + *gasCnt = C.size_t(1000 + len(s)) + + r := hash.Sha256([]byte(s)) + return C.CString(byteutils.Hex(r)) +} + +// Sha3256Func .. +//export Sha3256Func +func Sha3256Func(data *C.char, gasCnt *C.size_t) *C.char { + s := C.GoString(data) + *gasCnt = C.size_t(1000 + len(s)) + + r := hash.Sha3256([]byte(s)) + return C.CString(byteutils.Hex(r)) +} + +// Ripemd160Func .. +//export Ripemd160Func +func Ripemd160Func(data *C.char, gasCnt *C.size_t) *C.char { + s := C.GoString(data) + *gasCnt = C.size_t(1000 + len(s)) + + r := hash.Ripemd160([]byte(s)) + return C.CString(byteutils.Hex(r)) +} + +// RecoverAddressFunc .. +//export RecoverAddressFunc +func RecoverAddressFunc(alg int, data, sign *C.char, gasCnt *C.size_t) *C.char { + d := C.GoString(data) + s := C.GoString(sign) + + *gasCnt = C.size_t(0) + + plain, err := byteutils.FromHex(d) + if err != nil { + logging.VLog().WithFields(logrus.Fields{ + "data": d, + "sign": s, + "alg": alg, + "err": err, + }).Debug("convert data to byte array error.") + } + cipher, err := byteutils.FromHex(s) + if err != nil { + logging.VLog().WithFields(logrus.Fields{ + "data": d, + "sign": s, + "alg": alg, + "err": err, + }).Debug("convert sign to byte array error.") + } + addr, err := core.RecoverSignerFromSignature(keystore.Algorithm(alg), plain, cipher) + if err != nil { + logging.VLog().WithFields(logrus.Fields{ + "data": d, + "sign": s, + "alg": alg, + "err": err, + }).Debug("recover address error.") + } + + return C.CString(addr.String()) +} diff --git a/nf/nvm/engine.go b/nf/nvm/engine.go index b6f10f40c..cb8b82cb7 100644 --- a/nf/nvm/engine.go +++ b/nf/nvm/engine.go @@ -42,7 +42,12 @@ func (nvm *NebulasVM) CreateEngine(block *core.Block, tx *core.Transaction, cont // CheckV8Run to check V8 env is OK func (nvm *NebulasVM) CheckV8Run() error { - engine := NewV8Engine(nil) + engine := NewV8Engine(&Context{ + block: core.MockBlock(nil, 1), + contract: state.MockAccount("1.0.0"), + tx: nil, + state: nil, + }) _, err := engine.RunScriptSource("", 0) engine.Dispose() return err diff --git a/nf/nvm/engine_v8.go b/nf/nvm/engine_v8.go index 33d26c700..2f98e9d9b 100644 --- a/nf/nvm/engine_v8.go +++ b/nf/nvm/engine_v8.go @@ -40,6 +40,11 @@ char *GetAccountStateFunc_cgo(void *handler, const char *address); int TransferFunc_cgo(void *handler, const char *to, const char *value); int VerifyAddressFunc_cgo(void *handler, const char *address); +char *Sha256Func_cgo(const char *data, size_t *gasCnt); +char *Sha3256Func_cgo(const char *data, size_t *gasCnt); +char *Ripemd160Func_cgo(const char *data, size_t *gasCnt); +char *RecoverAddressFunc_cgo(int alg, const char *data, const char *sign, size_t *gasCnt); + void EventTriggerFunc_cgo(void *handler, const char *topic, const char *data, size_t *gasCnt); */ @@ -122,6 +127,12 @@ func InitV8Engine() { // Event. C.InitializeEvent((C.EventTriggerFunc)(unsafe.Pointer(C.EventTriggerFunc_cgo))) + + // Crypto + C.InitializeCrypto((C.Sha256Func)(unsafe.Pointer(C.Sha256Func_cgo)), + (C.Sha3256Func)(unsafe.Pointer(C.Sha3256Func_cgo)), + (C.Ripemd160Func)(unsafe.Pointer(C.Ripemd160Func_cgo)), + (C.RecoverAddressFunc)(unsafe.Pointer(C.RecoverAddressFunc_cgo))) } // DisposeV8Engine dispose the v8 engine. diff --git a/nf/nvm/engine_v8_test.go b/nf/nvm/engine_v8_test.go index eccb16ebd..98d215158 100644 --- a/nf/nvm/engine_v8_test.go +++ b/nf/nvm/engine_v8_test.go @@ -162,7 +162,7 @@ func TestRunScriptSource(t *testing.T) { owner, err := context.GetOrCreateUserAccount([]byte("account1")) assert.Nil(t, err) owner.AddBalance(newUint128FromIntWrapper(1000000000)) - contract, _ := context.CreateContractAccount([]byte("account2"), nil) + contract, _ := context.CreateContractAccount([]byte("account2"), nil, nil) ctx, err := NewContext(mockBlock(), mockTransaction(), contract, context) engine := NewV8Engine(ctx) @@ -201,7 +201,7 @@ func TestRunScriptSourceInModule(t *testing.T) { owner, err := context.GetOrCreateUserAccount([]byte("account1")) assert.Nil(t, err) owner.AddBalance(newUint128FromIntWrapper(1000000000)) - contract, _ := context.CreateContractAccount([]byte("account2"), nil) + contract, _ := context.CreateContractAccount([]byte("account2"), nil, nil) ctx, err := NewContext(mockBlock(), mockTransaction(), contract, context) engine := NewV8Engine(ctx) @@ -245,7 +245,7 @@ func TestRunScriptSourceWithLimits(t *testing.T) { owner, err := context.GetOrCreateUserAccount([]byte("account1")) assert.Nil(t, err) owner.AddBalance(newUint128FromIntWrapper(100000)) - contract, _ := context.CreateContractAccount([]byte("account2"), nil) + contract, _ := context.CreateContractAccount([]byte("account2"), nil, nil) ctx, err := NewContext(mockBlock(), mockTransaction(), contract, context) // direct run. @@ -299,7 +299,7 @@ func TestV8ResourceLimit(t *testing.T) { owner, err := context.GetOrCreateUserAccount([]byte("account1")) assert.Nil(t, err) owner.AddBalance(newUint128FromIntWrapper(10000000)) - contract, _ := context.CreateContractAccount([]byte("account2"), nil) + contract, _ := context.CreateContractAccount([]byte("account2"), nil, nil) ctx, err := NewContext(mockBlock(), mockTransaction(), contract, context) engine := NewV8Engine(ctx) @@ -351,7 +351,7 @@ func TestRunScriptSourceTimeout(t *testing.T) { // owner, err := context.GetOrCreateUserAccount([]byte("account1")) // assert.Nil(t, err) - contract, _ := context.CreateContractAccount([]byte("account2"), nil) + contract, _ := context.CreateContractAccount([]byte("account2"), nil, nil) ctx, err := NewContext(mockBlock(), mockTransaction(), contract, context) // direct run. @@ -398,7 +398,7 @@ func TestDeployAndInitAndCall(t *testing.T) { owner, err := context.GetOrCreateUserAccount([]byte("account1")) assert.Nil(t, err) owner.AddBalance(newUint128FromIntWrapper(10000000)) - contract, _ := context.CreateContractAccount([]byte("account2"), nil) + contract, _ := context.CreateContractAccount([]byte("account2"), nil, nil) ctx, err := NewContext(mockBlock(), mockTransaction(), contract, context) engine := NewV8Engine(ctx) @@ -424,7 +424,7 @@ func TestDeployAndInitAndCall(t *testing.T) { context, _ = state.NewWorldState(dpos.NewDpos(), mem) owner, err = context.GetOrCreateUserAccount([]byte("account1")) assert.Nil(t, err) - contract, err = context.CreateContractAccount([]byte("account2"), nil) + contract, err = context.CreateContractAccount([]byte("account2"), nil, nil) assert.Nil(t, err) ctx, err = NewContext(mockBlock(), mockTransaction(), contract, context) @@ -459,7 +459,7 @@ func TestERC20(t *testing.T) { owner, err := context.GetOrCreateUserAccount([]byte("account1")) assert.Nil(t, err) owner.AddBalance(newUint128FromIntWrapper(10000000)) - contract, _ := context.CreateContractAccount([]byte("account2"), nil) + contract, _ := context.CreateContractAccount([]byte("account2"), nil, nil) ctx, err := NewContext(mockBlock(), mockTransaction(), contract, context) engine := NewV8Engine(ctx) @@ -519,7 +519,7 @@ func TestContracts(t *testing.T) { owner, err := context.GetOrCreateUserAccount([]byte("account1")) assert.Nil(t, err) owner.AddBalance(newUint128FromIntWrapper(10000000)) - contract, err := context.CreateContractAccount([]byte("account2"), nil) + contract, err := context.CreateContractAccount([]byte("account2"), nil, nil) assert.Nil(t, err) ctx, err := NewContext(mockBlock(), mockTransaction(), contract, context) @@ -568,7 +568,7 @@ func TestFunctionNameCheck(t *testing.T) { owner, err := context.GetOrCreateUserAccount([]byte("account1")) assert.Nil(t, err) owner.AddBalance(newUint128FromIntWrapper(1000000)) - contract, _ := context.CreateContractAccount([]byte("account2"), nil) + contract, _ := context.CreateContractAccount([]byte("account2"), nil, nil) ctx, err := NewContext(mockBlock(), mockTransaction(), contract, context) engine := NewV8Engine(ctx) @@ -586,7 +586,7 @@ func TestMultiEngine(t *testing.T) { owner, err := context.GetOrCreateUserAccount([]byte("account1")) assert.Nil(t, err) owner.AddBalance(newUint128FromIntWrapper(1000000)) - contract, _ := context.CreateContractAccount([]byte("account2"), nil) + contract, _ := context.CreateContractAccount([]byte("account2"), nil, nil) var wg sync.WaitGroup for i := 0; i < 100; i++ { @@ -655,7 +655,7 @@ func TestInstructionCounterTestSuite(t *testing.T) { owner.AddBalance(newUint128FromIntWrapper(1000000000)) addr, err := core.NewContractAddressFromData([]byte("n1FkntVUMPAsESuCAAPK711omQk19JotBjM"), byteutils.FromUint64(1)) assert.Nil(t, err) - contract, err := context.CreateContractAccount(addr.Bytes(), nil) + contract, err := context.CreateContractAccount(addr.Bytes(), nil, nil) assert.Nil(t, err) ctx, err := NewContext(mockBlock(), mockTransaction(), contract, context) @@ -696,7 +696,7 @@ func TestTypeScriptExecution(t *testing.T) { owner, err := context.GetOrCreateUserAccount([]byte("account1")) assert.Nil(t, err) owner.AddBalance(newUint128FromIntWrapper(1000000000)) - contract, err := context.CreateContractAccount([]byte("account2"), nil) + contract, err := context.CreateContractAccount([]byte("account2"), nil, nil) assert.Nil(t, err) ctx, err := NewContext(mockBlock(), mockTransaction(), contract, context) @@ -731,7 +731,7 @@ func DeprecatedTestRunMozillaJSTestSuite(t *testing.T) { assert.Nil(t, err) owner.AddBalance(newUint128FromIntWrapper(1000000000)) - contract, err := context.CreateContractAccount([]byte("account2"), nil) + contract, err := context.CreateContractAccount([]byte("account2"), nil, nil) assert.Nil(t, err) ctx, err := NewContext(mockBlock(), mockTransaction(), contract, context) @@ -810,7 +810,7 @@ func TestBlockChain(t *testing.T) { owner, err := context.GetOrCreateUserAccount([]byte("n1FkntVUMPAsESuCAAPK711omQk19JotBjM")) assert.Nil(t, err) owner.AddBalance(newUint128FromIntWrapper(1000000000)) - contract, err := context.CreateContractAccount([]byte("n1JNHZJEUvfBYfjDRD14Q73FX62nJAzXkMR"), nil) + contract, err := context.CreateContractAccount([]byte("n1JNHZJEUvfBYfjDRD14Q73FX62nJAzXkMR"), nil, nil) assert.Nil(t, err) ctx, err := NewContext(mockBlock(), mockTransaction(), contract, context) @@ -871,7 +871,7 @@ func TestBankVaultContract(t *testing.T) { // prepare the contract. addr, err := core.NewContractAddressFromData([]byte("n1FkntVUMPAsESuCAAPK711omQk19JotBjM"), byteutils.FromUint64(1)) assert.Nil(t, err) - contract, _ := context.CreateContractAccount(addr.Bytes(), nil) + contract, _ := context.CreateContractAccount(addr.Bytes(), nil, nil) contract.AddBalance(newUint128FromIntWrapper(5)) // parepare env, block & transactions. @@ -949,7 +949,7 @@ func TestEvent(t *testing.T) { owner, err := context.GetOrCreateUserAccount([]byte("n1FkntVUMPAsESuCAAPK711omQk19JotBjM")) assert.Nil(t, err) owner.AddBalance(newUint128FromIntWrapper(1000000000)) - contract, _ := context.CreateContractAccount([]byte("n1JNHZJEUvfBYfjDRD14Q73FX62nJAzXkMR"), nil) + contract, _ := context.CreateContractAccount([]byte("n1JNHZJEUvfBYfjDRD14Q73FX62nJAzXkMR"), nil, nil) ctx, err := NewContext(mockBlock(), mockTransaction(), contract, context) engine := NewV8Engine(ctx) @@ -1000,7 +1000,7 @@ func TestNRC20Contract(t *testing.T) { owner.AddBalance(newUint128FromIntWrapper(10000000)) // prepare the contract. - contract, _ := context.CreateContractAccount([]byte("account2"), nil) + contract, _ := context.CreateContractAccount([]byte("account2"), nil, nil) contract.AddBalance(newUint128FromIntWrapper(5)) // parepare env, block & transactions. @@ -1154,7 +1154,7 @@ func TestNRC721Contract(t *testing.T) { assert.Nil(t, err) // prepare the contract. - contract, _ := context.CreateContractAccount([]byte("account2"), nil) + contract, _ := context.CreateContractAccount([]byte("account2"), nil, nil) contract.AddBalance(newUint128FromIntWrapper(5)) // parepare env, block & transactions. @@ -1251,7 +1251,7 @@ func TestNebulasContract(t *testing.T) { owner.AddBalance(newUint128FromIntWrapper(1000000000)) addr, _ = core.NewContractAddressFromData([]byte{1, 2, 3, 5, 7}, []byte{1, 2, 3, 5, 7}) - contract, _ := context.CreateContractAccount(addr.Bytes(), nil) + contract, _ := context.CreateContractAccount(addr.Bytes(), nil, nil) ctx, err := NewContext(mockBlock(), mockTransaction(), contract, context) @@ -1318,7 +1318,7 @@ func TestTransferValueFromContracts(t *testing.T) { owner.AddBalance(newUint128FromIntWrapper(10000000)) addr, err := core.NewContractAddressFromData([]byte("n1FkntVUMPAsESuCAAPK711omQk19JotBjM"), byteutils.FromUint64(1)) assert.Nil(t, err) - contract, err := context.CreateContractAccount(addr.Bytes(), nil) + contract, err := context.CreateContractAccount(addr.Bytes(), nil, nil) assert.Nil(t, err) contract.AddBalance(newUint128FromIntWrapper(100)) @@ -1369,7 +1369,7 @@ func TestRequireModule(t *testing.T) { owner, err := context.GetOrCreateUserAccount([]byte("account1")) assert.Nil(t, err) owner.AddBalance(newUint128FromIntWrapper(10000000)) - contract, _ := context.CreateContractAccount([]byte("account2"), nil) + contract, _ := context.CreateContractAccount([]byte("account2"), nil, nil) ctx, err := NewContext(mockBlock(), mockTransaction(), contract, context) engine := NewV8Engine(ctx) diff --git a/nf/nvm/lib/1.0.0 b/nf/nvm/lib/1.0.0 new file mode 120000 index 000000000..208c4b65e --- /dev/null +++ b/nf/nvm/lib/1.0.0 @@ -0,0 +1 @@ +../v8/libjs/1.0.0 \ No newline at end of file diff --git a/nf/nvm/lib/1.0.1 b/nf/nvm/lib/1.0.1 new file mode 120000 index 000000000..528128ebc --- /dev/null +++ b/nf/nvm/lib/1.0.1 @@ -0,0 +1 @@ +../v8/libjs/1.0.1 \ No newline at end of file diff --git a/nf/nvm/lib/assert.js b/nf/nvm/lib/assert.js deleted file mode 120000 index ddafcddbb..000000000 --- a/nf/nvm/lib/assert.js +++ /dev/null @@ -1 +0,0 @@ -../v8/lib/assert.js \ No newline at end of file diff --git a/nf/nvm/lib/bignumber.js b/nf/nvm/lib/bignumber.js deleted file mode 120000 index eba9ebef5..000000000 --- a/nf/nvm/lib/bignumber.js +++ /dev/null @@ -1 +0,0 @@ -../v8/lib/bignumber.js \ No newline at end of file diff --git a/nf/nvm/lib/blockchain.js b/nf/nvm/lib/blockchain.js deleted file mode 120000 index 67b4d0d49..000000000 --- a/nf/nvm/lib/blockchain.js +++ /dev/null @@ -1 +0,0 @@ -../v8/lib/blockchain.js \ No newline at end of file diff --git a/nf/nvm/lib/console.js b/nf/nvm/lib/console.js deleted file mode 120000 index 10c76f55a..000000000 --- a/nf/nvm/lib/console.js +++ /dev/null @@ -1 +0,0 @@ -../v8/lib/console.js \ No newline at end of file diff --git a/nf/nvm/lib/date.js b/nf/nvm/lib/date.js deleted file mode 120000 index b2d62a9aa..000000000 --- a/nf/nvm/lib/date.js +++ /dev/null @@ -1 +0,0 @@ -../v8/lib/date.js \ No newline at end of file diff --git a/nf/nvm/lib/esprima.js b/nf/nvm/lib/esprima.js deleted file mode 120000 index 8cd1c783b..000000000 --- a/nf/nvm/lib/esprima.js +++ /dev/null @@ -1 +0,0 @@ -../v8/lib/esprima.js \ No newline at end of file diff --git a/nf/nvm/lib/event.js b/nf/nvm/lib/event.js deleted file mode 120000 index f0fbddf55..000000000 --- a/nf/nvm/lib/event.js +++ /dev/null @@ -1 +0,0 @@ -../v8/lib/event.js \ No newline at end of file diff --git a/nf/nvm/lib/execution_env.js b/nf/nvm/lib/execution_env.js deleted file mode 120000 index 6ec3b8ba2..000000000 --- a/nf/nvm/lib/execution_env.js +++ /dev/null @@ -1 +0,0 @@ -../v8/lib/execution_env.js \ No newline at end of file diff --git a/nf/nvm/lib/instruction_counter.js b/nf/nvm/lib/instruction_counter.js deleted file mode 120000 index 5b3f86ee4..000000000 --- a/nf/nvm/lib/instruction_counter.js +++ /dev/null @@ -1 +0,0 @@ -../v8/lib/instruction_counter.js \ No newline at end of file diff --git a/nf/nvm/lib/random.js b/nf/nvm/lib/random.js deleted file mode 120000 index 6d184e127..000000000 --- a/nf/nvm/lib/random.js +++ /dev/null @@ -1 +0,0 @@ -../v8/lib/random.js \ No newline at end of file diff --git a/nf/nvm/lib/storage.js b/nf/nvm/lib/storage.js deleted file mode 120000 index b15a085c4..000000000 --- a/nf/nvm/lib/storage.js +++ /dev/null @@ -1 +0,0 @@ -../v8/lib/storage.js \ No newline at end of file diff --git a/nf/nvm/lib/tsc.js b/nf/nvm/lib/tsc.js deleted file mode 120000 index 8592113a7..000000000 --- a/nf/nvm/lib/tsc.js +++ /dev/null @@ -1 +0,0 @@ -../v8/lib/tsc.js \ No newline at end of file diff --git a/nf/nvm/lib/typescriptServices.js b/nf/nvm/lib/typescriptServices.js deleted file mode 120000 index 0ec58b48a..000000000 --- a/nf/nvm/lib/typescriptServices.js +++ /dev/null @@ -1 +0,0 @@ -../v8/lib/typescriptServices.js \ No newline at end of file diff --git a/nf/nvm/module.go b/nf/nvm/module.go index 19e8241ad..3f3609a35 100644 --- a/nf/nvm/module.go +++ b/nf/nvm/module.go @@ -107,6 +107,8 @@ func RequireDelegateFunc(handler unsafe.Pointer, filename *C.char, lineOffset *C //export AttachLibVersionDelegateFunc func AttachLibVersionDelegateFunc(handler unsafe.Pointer, require *C.char) *C.char { libname := C.GoString(require) + libname = strings.Replace(libname, `\\`, "/", -1) + libname = strings.Replace(libname, `\`, "/", -1) e := getEngineByEngineHandler(handler) if e == nil { logging.VLog().WithFields(logrus.Fields{ @@ -119,10 +121,27 @@ func AttachLibVersionDelegateFunc(handler unsafe.Pointer, require *C.char) *C.ch return nil } + if e.ctx == nil { + logging.VLog().Error("context is nil.") + return nil + } + if e.ctx.block == nil { + logging.VLog().Error("context.block is nil.") + return nil + } + // block after core.V8JSLibVersionControlHeight, inclusive if e.ctx.block.Height() >= core.V8JSLibVersionControlHeight { - - cv := e.ctx.contract.ContractMeta().Version // TODO: check nil + // fmt.Println(e.ctx.block.Height(), core.V8JSLibVersionControlHeight, libname) + if e.ctx.contract == nil { + logging.VLog().Error("context.contract is nil.") + return nil + } + if e.ctx.contract.ContractMeta() == nil { + logging.VLog().Error("context.contract.ContractMeta() return nil.") + return nil + } + cv := e.ctx.contract.ContractMeta().Version if len(cv) == 0 { logging.VLog().WithFields(logrus.Fields{ @@ -165,11 +184,16 @@ func AttachLibVersionDelegateFunc(handler unsafe.Pointer, require *C.char) *C.ch return C.CString(JSLibRootName + "1.0.0" + libname[JSLibRootNameLen-1:]) } + v := "1.0.0" + if !strings.HasPrefix(libname, "/") { + v += "/" + } + logging.VLog().WithFields(logrus.Fields{ "libname": libname, - "return": "1.0.0" + libname, + "return": v + libname, }).Debug("attach lib.") - return C.CString("1.0.0" + libname) + return C.CString(v + libname) } func reformatModuleID(id string) string { diff --git a/nf/nvm/native-lib/libnebulasv8.dylib b/nf/nvm/native-lib/libnebulasv8.dylib index e6b6173e6..f4938da6f 100755 Binary files a/nf/nvm/native-lib/libnebulasv8.dylib and b/nf/nvm/native-lib/libnebulasv8.dylib differ diff --git a/nf/nvm/v8/Makefile b/nf/nvm/v8/Makefile index 306440985..f2fc0e0b9 100644 --- a/nf/nvm/v8/Makefile +++ b/nf/nvm/v8/Makefile @@ -56,10 +56,10 @@ all: main %.cpp.o: %.cpp $(CXX) $(CXXFLAGS) -c $< -o $<.o -main: samples/main.cc.o samples/memory_storage.cc.o samples/memory_modules.cc.o engine.cc.o allocator.cc.o lib/global.cc.o lib/execution_env.cc.o lib/storage_object.cc.o lib/log_callback.cc.o lib/require_callback.cc.o lib/instruction_counter.cc.o lib/blockchain.cc.o lib/fake_blockchain.cc.o lib/tracing.cc.o lib/file.cc.o lib/util.cc.o lib/typescript.cc.o lib/event.cc.o +main: samples/main.cc.o samples/memory_storage.cc.o samples/memory_modules.cc.o engine.cc.o allocator.cc.o lib/global.cc.o lib/execution_env.cc.o lib/storage_object.cc.o lib/log_callback.cc.o lib/require_callback.cc.o lib/instruction_counter.cc.o lib/blockchain.cc.o lib/fake_blockchain.cc.o lib/tracing.cc.o lib/file.cc.o lib/util.cc.o lib/typescript.cc.o lib/event.cc.o lib/crypto.cc.o $(LD) $(LDFLAGS) $^ -o $@ $(LIBS_PATH) $(LIBS) -engine: engine.cc.o allocator.cc.o lib/global.cc.o lib/execution_env.cc.o lib/storage_object.cc.o lib/log_callback.cc.o lib/require_callback.cc.o lib/instruction_counter.cc.o lib/blockchain.cc.o lib/tracing.cc.o lib/file.cc.o lib/util.cc.o lib/typescript.cc.o lib/event.cc.o +engine: engine.cc.o allocator.cc.o lib/global.cc.o lib/execution_env.cc.o lib/storage_object.cc.o lib/log_callback.cc.o lib/require_callback.cc.o lib/instruction_counter.cc.o lib/blockchain.cc.o lib/tracing.cc.o lib/file.cc.o lib/util.cc.o lib/typescript.cc.o lib/event.cc.o lib/crypto.cc.o $(LD) -shared $(LDFLAGS) $^ -o libnebulasv8$(DYLIB) $(LIBS_PATH) $(LIBS) install: engine diff --git a/nf/nvm/v8/engine.h b/nf/nvm/v8/engine.h index f72fcf923..6cf179400 100644 --- a/nf/nvm/v8/engine.h +++ b/nf/nvm/v8/engine.h @@ -75,6 +75,21 @@ EXPORT void InitializeBlockchain(GetTxByHashFunc getTx, TransferFunc transfer, VerifyAddressFunc verifyAddress); +// crypto +typedef char *(*Sha256Func)(void *handler, const char *data, + size_t *counterVal); +typedef char *(*Sha3256Func)(void *handler, const char *data, + size_t *counterVal); +typedef char *(*Ripemd160Func)(void *handler, const char *data, + size_t *counterVal); +typedef char *(*RecoverAddressFunc)(void *handler, int alg, const char *data, const char *sign, + size_t *counterVal); + +EXPORT void InitializeCrypto(Sha256Func sha256, + Sha3256Func sha3256, + Ripemd160Func ripemd160, + RecoverAddressFunc recoverAddress); + // version EXPORT char *GetV8Version(); diff --git a/nf/nvm/v8/lib/crypto.cc b/nf/nvm/v8/lib/crypto.cc new file mode 100644 index 000000000..9fbbe34bf --- /dev/null +++ b/nf/nvm/v8/lib/crypto.cc @@ -0,0 +1,213 @@ +// Copyright (C) 2018 go-nebulas authors +// +// This file is part of the go-nebulas library. +// +// the go-nebulas library is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// the go-nebulas library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with the go-nebulas library. If not, see . +// + +#include "crypto.h" +#include "../engine.h" +#include "instruction_counter.h" + +static Sha256Func sSha256 = NULL; +static Sha3256Func sSha3256 = NULL; +static Ripemd160Func sRipemd160 = NULL; +static RecoverAddressFunc sRecoverAddress = NULL; + +void InitializeCrypto(Sha256Func sha256, + Sha3256Func sha3256, + Ripemd160Func ripemd160, + RecoverAddressFunc recoverAddress) { + sSha256 = sha256; + sSha3256 = sha3256; + sRipemd160 = ripemd160; + sRecoverAddress = recoverAddress; +} + +void NewCryptoInstance(Isolate *isolate, Local context) { + Local cryptoTpl = ObjectTemplate::New(isolate); +// cryptoTpl->SetInternalFieldCount(1); + + cryptoTpl->Set(String::NewFromUtf8(isolate, "sha256"), + FunctionTemplate::New(isolate, Sha256Callback), + static_cast(PropertyAttribute::DontDelete | + PropertyAttribute::ReadOnly)); + + cryptoTpl->Set(String::NewFromUtf8(isolate, "sha3256"), + FunctionTemplate::New(isolate, Sha3256Callback), + static_cast(PropertyAttribute::DontDelete | + PropertyAttribute::ReadOnly)); + + cryptoTpl->Set(String::NewFromUtf8(isolate, "ripemd160"), + FunctionTemplate::New(isolate, Ripemd160Callback), + static_cast(PropertyAttribute::DontDelete | + PropertyAttribute::ReadOnly)); + + cryptoTpl->Set(String::NewFromUtf8(isolate, "recoverAddress"), + FunctionTemplate::New(isolate, RecoverAddressCallback), + static_cast(PropertyAttribute::DontDelete | + PropertyAttribute::ReadOnly)); + + Local instance = cryptoTpl->NewInstance(context).ToLocalChecked(); +// instance->SetInternalField(0, External::New(isolate, handler)); + + context->Global()->DefineOwnProperty( + context, String::NewFromUtf8(isolate, "_native_crypto"), instance, + static_cast(PropertyAttribute::DontDelete | + PropertyAttribute::ReadOnly)); +} + +// Sha256Callback +void Sha256Callback(const FunctionCallbackInfo &info) { + Isolate *isolate = info.GetIsolate(); + Local thisArg = info.Holder(); + Local handler = Local::Cast(thisArg->GetInternalField(0)); + + if (info.Length() != 1) { + isolate->ThrowException(String::NewFromUtf8( + isolate, "_native_crypto.sha256() requires only 1 argument")); + return; + } + + Local data = info[0]; + if (!data->IsString()) { + isolate->ThrowException(String::NewFromUtf8(isolate, "_native_crypto.sha256(): argument must be string")); + return; + } + + size_t cnt = 0; + + char *value = sSha256(handler->Value(), *String::Utf8Value(data->ToString()), &cnt); + if (value == NULL) { + info.GetReturnValue().SetNull(); + } else { + info.GetReturnValue().Set(String::NewFromUtf8(isolate, value)); + free(value); + } + + // record storage usage. + IncrCounter(isolate, isolate->GetCurrentContext(), cnt); +} + +// Sha3256Callback +void Sha3256Callback(const FunctionCallbackInfo &info) { + Isolate *isolate = info.GetIsolate(); + Local thisArg = info.Holder(); + Local handler = Local::Cast(thisArg->GetInternalField(0)); + + if (info.Length() != 1) { + isolate->ThrowException(String::NewFromUtf8( + isolate, "_native_crypto.sha3256() requires only 1 argument")); + return; + } + + Local data = info[0]; + if (!data->IsString()) { + isolate->ThrowException(String::NewFromUtf8(isolate, "_native_crypto.sha3256(): argument must be string")); + return; + } + + size_t cnt = 0; + + char *value = sSha3256(handler->Value(), *String::Utf8Value(data->ToString()), &cnt); + if (value == NULL) { + info.GetReturnValue().SetNull(); + } else { + info.GetReturnValue().Set(String::NewFromUtf8(isolate, value)); + free(value); + } + + // record storage usage. + IncrCounter(isolate, isolate->GetCurrentContext(), cnt); +} + +// Ripemd160Callback +void Ripemd160Callback(const FunctionCallbackInfo &info) { + Isolate *isolate = info.GetIsolate(); + Local thisArg = info.Holder(); + Local handler = Local::Cast(thisArg->GetInternalField(0)); + + if (info.Length() != 1) { + isolate->ThrowException(String::NewFromUtf8( + isolate, "_native_crypto.ripemd() requires only 1 argument")); + return; + } + + Local data = info[0]; + if (!data->IsString()) { + isolate->ThrowException(String::NewFromUtf8(isolate, "_native_crypto.ripemd(): argument must be string")); + return; + } + + size_t cnt = 0; + + char *value = sRipemd160(handler->Value(), *String::Utf8Value(data->ToString()), &cnt); + if (value == NULL) { + info.GetReturnValue().SetNull(); + } else { + info.GetReturnValue().Set(String::NewFromUtf8(isolate, value)); + free(value); + } + + // record storage usage. + IncrCounter(isolate, isolate->GetCurrentContext(), cnt); +} + +// RecoverAddressCallback +void RecoverAddressCallback(const FunctionCallbackInfo &info) { + Isolate *isolate = info.GetIsolate(); + Local thisArg = info.Holder(); + Local handler = Local::Cast(thisArg->GetInternalField(0)); + + if (info.Length() != 3) { + isolate->ThrowException(String::NewFromUtf8( + isolate, "_native_crypto.recoverAddress() requires 3 arguments")); + return; + } + + Local alg = info[0]; + if (!alg->IsInt32()) { + isolate->ThrowException( + String::NewFromUtf8(isolate, "_native_crypto.recoverAddress(): alg must be integer")); + return; + } + + Local data = info[1]; + if (!data->IsString()) { + isolate->ThrowException( + String::NewFromUtf8(isolate, "_native_crypto.recoverAddress(): data must be string")); + return; + } + + Local sign = info[2]; + if (!sign->IsString()) { + isolate->ThrowException( + String::NewFromUtf8(isolate, "_native_crypto.recoverAddress(): sign must be string")); + return; + } + + size_t cnt = 0; + + char *value = sRecoverAddress(handler->Value(), alg->ToInt32()->Int32Value(), *String::Utf8Value(data->ToString()), + *String::Utf8Value(sign->ToString()), &cnt); + if (value == NULL) { + info.GetReturnValue().SetNull(); + } else { + info.GetReturnValue().Set(String::NewFromUtf8(isolate, value)); + free(value); + } + + // record storage usage. + IncrCounter(isolate, isolate->GetCurrentContext(), cnt); +} diff --git a/nf/nvm/v8/lib/crypto.h b/nf/nvm/v8/lib/crypto.h new file mode 100644 index 000000000..ce09b1f82 --- /dev/null +++ b/nf/nvm/v8/lib/crypto.h @@ -0,0 +1,33 @@ +// Copyright (C) 2018 go-nebulas authors +// +// This file is part of the go-nebulas library. +// +// the go-nebulas library is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// the go-nebulas library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with the go-nebulas library. If not, see . +// + +#ifndef _NEBULAS_NF_NVM_V8_LIB_CRYPTO_H_ +#define _NEBULAS_NF_NVM_V8_LIB_CRYPTO_H_ + +#include + +using namespace v8; + +void NewCryptoInstance(Isolate *isolate, Local context); + +void Sha256Callback(const FunctionCallbackInfo &info); +void Sha3256Callback(const FunctionCallbackInfo &info); +void Ripemd160Callback(const FunctionCallbackInfo &info); +void RecoverAddressCallback(const FunctionCallbackInfo &info); + +#endif //_NEBULAS_NF_NVM_V8_LIB_CRYPTO_H_ \ No newline at end of file diff --git a/nf/nvm/v8/lib/global.cc b/nf/nvm/v8/lib/global.cc index 907b5f657..de7e86648 100644 --- a/nf/nvm/v8/lib/global.cc +++ b/nf/nvm/v8/lib/global.cc @@ -24,6 +24,7 @@ #include "log_callback.h" #include "require_callback.h" #include "storage_object.h" +#include "crypto.h" Local CreateGlobalObjectTemplate(Isolate *isolate) { Local globalTpl = ObjectTemplate::New(isolate); @@ -49,6 +50,7 @@ void SetGlobalObjectProperties(Isolate *isolate, Local context, NewInstructionCounterInstance(isolate, context, &(e->stats.count_of_executed_instructions), e); NewBlockchainInstance(isolate, context, lcsHandler); + NewCryptoInstance(isolate, context); } V8Engine *GetV8EngineInstance(Local context) { diff --git a/nf/nvm/v8/lib/assert.js b/nf/nvm/v8/libjs/1.0.0/assert.js similarity index 100% rename from nf/nvm/v8/lib/assert.js rename to nf/nvm/v8/libjs/1.0.0/assert.js diff --git a/nf/nvm/v8/lib/esprima.js b/nf/nvm/v8/libjs/1.0.0/esprima.js similarity index 100% rename from nf/nvm/v8/lib/esprima.js rename to nf/nvm/v8/libjs/1.0.0/esprima.js diff --git a/nf/nvm/v8/lib/instruction_counter.js b/nf/nvm/v8/libjs/1.0.0/instruction_counter.js similarity index 100% rename from nf/nvm/v8/lib/instruction_counter.js rename to nf/nvm/v8/libjs/1.0.0/instruction_counter.js diff --git a/nf/nvm/v8/lib/tsc.js b/nf/nvm/v8/libjs/1.0.0/tsc.js similarity index 100% rename from nf/nvm/v8/lib/tsc.js rename to nf/nvm/v8/libjs/1.0.0/tsc.js diff --git a/nf/nvm/v8/lib/typescriptServices.js b/nf/nvm/v8/libjs/1.0.0/typescriptServices.js similarity index 100% rename from nf/nvm/v8/lib/typescriptServices.js rename to nf/nvm/v8/libjs/1.0.0/typescriptServices.js diff --git a/nf/nvm/v8/lib/util.js b/nf/nvm/v8/libjs/1.0.0/util.js similarity index 100% rename from nf/nvm/v8/lib/util.js rename to nf/nvm/v8/libjs/1.0.0/util.js diff --git a/nf/nvm/v8/libjs/1.0.1/crypto.js b/nf/nvm/v8/libjs/1.0.1/crypto.js index eb5d7569c..35e59a581 100644 --- a/nf/nvm/v8/libjs/1.0.1/crypto.js +++ b/nf/nvm/v8/libjs/1.0.1/crypto.js @@ -29,7 +29,39 @@ var Crypto = function() { }; Crypto.prototype = { - + + sha256: function(data) { + if (typeof data !== "string") { + throw new Error("input must be string"); + } + return this.nativeCrypto.sha256(data); + }, + + sha3256: function(data) { + if (typeof data !== "string") { + throw new Error("input must be string"); + } + return this.nativeCrypto.sha3256(data); + }, + + ripemd160: function(data) { + if (typeof data !== "string") { + throw new Error("input must be string"); + } + return this.nativeCrypto.ripemd160(data); + }, + + recoverAddress: function(alg, data, sign) { + if (!Number.isInteger(alg)) { + throw new Error("alg must be integer"); + } + + if (typeof data != "string" || typeof sign != "string") { + throw new Error("data & sign must be string"); + } + + return this.nativeCrypto.recoverAddress(alg, data, sign); + }, }; -module.exports = Crypto; \ No newline at end of file +module.exports = new Crypto(); \ No newline at end of file diff --git a/nf/nvm/v8/samples/main.cc b/nf/nvm/v8/samples/main.cc index 7ca39731f..3d9a5bce4 100644 --- a/nf/nvm/v8/samples/main.cc +++ b/nf/nvm/v8/samples/main.cc @@ -231,7 +231,8 @@ int main(int argc, const char *argv[]) { Initialize(); InitializeLogger(logFunc); - InitializeRequireDelegate(RequireDelegateFunc); + InitializeRequireDelegate(RequireDelegateFunc, AttachLibVersionDelegateFunc); + InitializeExecutionEnvDelegate(AttachLibVersionDelegateFunc); InitializeStorage(StorageGet, StoragePut, StorageDel); InitializeBlockchain(GetTxByHash, GetAccountState, Transfer, VerifyAddress); InitializeEvent(eventTriggerFunc); diff --git a/nf/nvm/v8/samples/memory_modules.cc b/nf/nvm/v8/samples/memory_modules.cc index 18491b0b5..bd1c5feab 100644 --- a/nf/nvm/v8/samples/memory_modules.cc +++ b/nf/nvm/v8/samples/memory_modules.cc @@ -99,6 +99,17 @@ char *RequireDelegateFunc(void *handler, const char *filepath, return ret; } +char *AttachLibVersionDelegateFunc(void *handler, const char *libname) { + char *path = (char *)calloc(128, sizeof(char)); + if (strncmp(libname, "lib/", 4) == 0) { + sprintf(path, "lib/1.0.0/%s", libname + 4); + } else { + sprintf(path, "1.0.0/%s", libname); + } + LogDebugf("AttachLibVersion: %s -> %s", libname, path); + return path; +} + void AddModule(void *handler, const char *filename, const char *source, int lineOffset) { char filepath[128]; diff --git a/nf/nvm/v8/samples/memory_modules.h b/nf/nvm/v8/samples/memory_modules.h index 99135083b..05fc6c3a6 100644 --- a/nf/nvm/v8/samples/memory_modules.h +++ b/nf/nvm/v8/samples/memory_modules.h @@ -25,6 +25,8 @@ char *RequireDelegateFunc(void *handler, const char *filename, size_t *lineOffset); +char *AttachLibVersionDelegateFunc(void *handler, const char *libname); + void AddModule(void *handler, const char *filename, const char *source, int lineOffset);